diff --git a/Binary Artifacts/Support Files/bios.bin b/Binary Artifacts/Support Files/bios.bin index 6c8bc9f6..e4323c05 100644 Binary files a/Binary Artifacts/Support Files/bios.bin and b/Binary Artifacts/Support Files/bios.bin differ diff --git a/TESTFILES/WinQemu.dll b/TESTFILES/WinQemu.dll index 1787d9c8..a1d0b963 100644 Binary files a/TESTFILES/WinQemu.dll and b/TESTFILES/WinQemu.dll differ diff --git a/TESTFILES/WinQemu.pdb b/TESTFILES/WinQemu.pdb index aab4fe34..68ef7e54 100644 Binary files a/TESTFILES/WinQemu.pdb and b/TESTFILES/WinQemu.pdb differ diff --git a/TESTFILES/bios.bin b/TESTFILES/bios.bin index 8aa5b713..e4323c05 100644 Binary files a/TESTFILES/bios.bin and b/TESTFILES/bios.bin differ diff --git a/WinQemu.vcxproj b/WinQemu.vcxproj index bdac325a..54092dc1 100644 --- a/WinQemu.vcxproj +++ b/WinQemu.vcxproj @@ -196,6 +196,8 @@ true + + @@ -1107,6 +1109,7 @@ + diff --git a/WinQemu.vcxproj.filters b/WinQemu.vcxproj.filters index 2977366a..3a3ad81f 100644 --- a/WinQemu.vcxproj.filters +++ b/WinQemu.vcxproj.filters @@ -1134,9 +1134,6 @@ qemu\block\src - - qemu\src - qemu\src @@ -1191,6 +1188,15 @@ qemu\src + + qemu\hw\src + + + qemu\hw\src + + + qemu\hw\src + @@ -1796,6 +1802,9 @@ qemu\inc + + qemu\hw\inc + diff --git a/qemu/Makefile b/qemu/Makefile index caf85309..a3ae99fd 100644 --- a/qemu/Makefile +++ b/qemu/Makefile @@ -108,7 +108,7 @@ obj-y += bt-hci-csr.o obj-y += buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o obj-y += qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o obj-y += msmouse.o ps2.o -obj-y += qdev.o ssi.o +obj-y += qdev.o qdev-properties.o ssi.o obj-$(CONFIG_BRLAPI) += baum.o diff --git a/qemu/Makefile.hw b/qemu/Makefile.hw index f7a9507e..571e5184 100644 --- a/qemu/Makefile.hw +++ b/qemu/Makefile.hw @@ -26,7 +26,7 @@ obj-y += m48t59.o escc.o # SCSI layer obj-y += lsi53c895a.o esp.o -obj-y += dma-helpers.o sysbus.o +obj-y += dma-helpers.o sysbus.o qdev-addr.o all: $(HWLIB) # Dummy command so that make thinks it has done something diff --git a/qemu/block.c b/qemu/block.c index e8b689db..bdbf3863 100644 --- a/qemu/block.c +++ b/qemu/block.c @@ -1183,24 +1183,26 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) return drv->bdrv_get_info(bs, bdi); } -int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size) +int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, + int64_t pos, int size) { BlockDriver *drv = bs->drv; if (!drv) return -ENOMEDIUM; - if (!drv->bdrv_put_buffer) + if (!drv->bdrv_save_vmstate) return -ENOTSUP; - return drv->bdrv_put_buffer(bs, buf, pos, size); + return drv->bdrv_save_vmstate(bs, buf, pos, size); } -int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size) +int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, + int64_t pos, int size) { BlockDriver *drv = bs->drv; if (!drv) return -ENOMEDIUM; - if (!drv->bdrv_get_buffer) + if (!drv->bdrv_load_vmstate) return -ENOTSUP; - return drv->bdrv_get_buffer(bs, buf, pos, size); + return drv->bdrv_load_vmstate(bs, buf, pos, size); } /**************************************************************/ @@ -1399,6 +1401,7 @@ static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb) { BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb; qemu_bh_delete(acb->bh); + acb->bh = NULL; qemu_aio_release(acb); } @@ -1416,6 +1419,7 @@ static void bdrv_aio_bh_cb(void *opaque) qemu_vfree(acb->bounce); acb->common.cb(acb->common.opaque, acb->ret); qemu_bh_delete(acb->bh); + acb->bh = NULL; qemu_aio_release(acb); } diff --git a/qemu/block.h b/qemu/block.h index 406a1994..ccd4c1e7 100644 --- a/qemu/block.h +++ b/qemu/block.h @@ -159,9 +159,10 @@ void path_combine(char *dest, int dest_size, const char *base_path, const char *filename); -int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf, - int64_t pos, int size); +int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, + int64_t pos, int size); -int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size); +int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, + int64_t pos, int size); #endif diff --git a/qemu/block/qcow.c b/qemu/block/qcow.c index 329b364b..7fc85ae5 100644 --- a/qemu/block/qcow.c +++ b/qemu/block/qcow.c @@ -723,7 +723,7 @@ static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs, s->cluster_cache_offset = -1; /* disable compressed cache */ - acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); + acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1); if (!acb) return NULL; @@ -909,9 +909,21 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) static QEMUOptionParameter qcow_create_options[] = { - { BLOCK_OPT_SIZE, OPT_SIZE }, - { BLOCK_OPT_BACKING_FILE, OPT_STRING }, - { BLOCK_OPT_ENCRYPT, OPT_FLAG }, + { + .name = BLOCK_OPT_SIZE, + .type = OPT_SIZE, + .help = "Virtual disk size" + }, + { + .name = BLOCK_OPT_BACKING_FILE, + .type = OPT_STRING, + .help = "File name of a base image" + }, + { + .name = BLOCK_OPT_ENCRYPT, + .type = OPT_FLAG, + .help = "Encrypt the image" + }, { NULL } }; diff --git a/qemu/block/qcow2-cluster.c b/qemu/block/qcow2-cluster.c index d349655d..057dac57 100644 --- a/qemu/block/qcow2-cluster.c +++ b/qemu/block/qcow2-cluster.c @@ -47,7 +47,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size) #endif new_l1_size2 = sizeof(uint64_t) * new_l1_size; - new_l1_table = qemu_mallocz(new_l1_size2); + new_l1_table = qemu_mallocz(align_offset(new_l1_size2, 512)); memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t)); /* write new table (align to cluster) */ diff --git a/qemu/block/qcow2-refcount.c b/qemu/block/qcow2-refcount.c index d42c6e64..e6c857e0 100644 --- a/qemu/block/qcow2-refcount.c +++ b/qemu/block/qcow2-refcount.c @@ -513,7 +513,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, l1_size2 = l1_size * sizeof(uint64_t); l1_allocated = 0; if (l1_table_offset != s->l1_table_offset) { - l1_table = qemu_malloc(l1_size2); + l1_table = qemu_mallocz(align_offset(l1_size2, 512)); l1_allocated = 1; if (bdrv_pread(s->hd, l1_table_offset, l1_table, l1_size2) != l1_size2) diff --git a/qemu/block/qcow2.c b/qemu/block/qcow2.c index 9a7c666e..a5bf2052 100644 --- a/qemu/block/qcow2.c +++ b/qemu/block/qcow2.c @@ -200,7 +200,8 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags) if (s->l1_size < s->l1_vm_state_index) goto fail; s->l1_table_offset = header.l1_table_offset; - s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t)); + s->l1_table = qemu_mallocz( + align_offset(s->l1_size * sizeof(uint64_t), 512)); if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) != s->l1_size * sizeof(uint64_t)) goto fail; @@ -889,12 +890,16 @@ static void qcow_flush(BlockDriverState *bs) bdrv_flush(s->hd); } +static int64_t qcow_vm_state_offset(BDRVQcowState *s) +{ + return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits); +} + static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVQcowState *s = bs->opaque; bdi->cluster_size = s->cluster_size; - bdi->vm_state_offset = (int64_t)s->l1_vm_state_index << - (s->cluster_bits + s->l2_bits); + bdi->vm_state_offset = qcow_vm_state_offset(s); return 0; } @@ -924,26 +929,28 @@ static void dump_refcounts(BlockDriverState *bs) } #endif -static int qcow_put_buffer(BlockDriverState *bs, const uint8_t *buf, +static int qcow_save_vmstate(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size) { + BDRVQcowState *s = bs->opaque; int growable = bs->growable; bs->growable = 1; - bdrv_pwrite(bs, pos, buf, size); + bdrv_pwrite(bs, qcow_vm_state_offset(s) + pos, buf, size); bs->growable = growable; return size; } -static int qcow_get_buffer(BlockDriverState *bs, uint8_t *buf, +static int qcow_load_vmstate(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size) { + BDRVQcowState *s = bs->opaque; int growable = bs->growable; int ret; bs->growable = 1; - ret = bdrv_pread(bs, pos, buf, size); + ret = bdrv_pread(bs, qcow_vm_state_offset(s) + pos, buf, size); bs->growable = growable; return ret; @@ -1000,8 +1007,8 @@ static BlockDriver bdrv_qcow2 = { .bdrv_snapshot_list = qcow2_snapshot_list, .bdrv_get_info = qcow_get_info, - .bdrv_put_buffer = qcow_put_buffer, - .bdrv_get_buffer = qcow_get_buffer, + .bdrv_save_vmstate = qcow_save_vmstate, + .bdrv_load_vmstate = qcow_load_vmstate, .create_options = qcow_create_options, .bdrv_check = qcow_check, diff --git a/qemu/block/raw-posix.c b/qemu/block/raw-posix.c index fa4f83e8..389903e4 100644 --- a/qemu/block/raw-posix.c +++ b/qemu/block/raw-posix.c @@ -852,6 +852,7 @@ static int64_t raw_getlength(BlockDriverState *bs) static int raw_create(const char *filename, QEMUOptionParameter *options) { int fd; + int result = 0; int64_t total_size = 0; /* Read out options */ @@ -864,11 +865,17 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); - if (fd < 0) - return -EIO; - ftruncate(fd, total_size * 512); - close(fd); - return 0; + if (fd < 0) { + result = -errno; + } else { + if (ftruncate(fd, total_size * 512) != 0) { + result = -errno; + } + if (close(fd) != 0) { + result = -errno; + } + } + return result; } static void raw_flush(BlockDriverState *bs) diff --git a/qemu/block_int.h b/qemu/block_int.h index 830b7e9c..8898d91f 100644 --- a/qemu/block_int.h +++ b/qemu/block_int.h @@ -84,10 +84,10 @@ struct BlockDriver { QEMUSnapshotInfo **psn_info); int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); - int (*bdrv_put_buffer)(BlockDriverState *bs, const uint8_t *buf, - int64_t pos, int size); - int (*bdrv_get_buffer)(BlockDriverState *bs, uint8_t *buf, - int64_t pos, int size); + int (*bdrv_save_vmstate)(BlockDriverState *bs, const uint8_t *buf, + int64_t pos, int size); + int (*bdrv_load_vmstate)(BlockDriverState *bs, uint8_t *buf, + int64_t pos, int size); /* removable device specific */ int (*bdrv_is_inserted)(BlockDriverState *bs); diff --git a/qemu/configure b/qemu/configure index a55dbc5e..cba0c08a 100644 --- a/qemu/configure +++ b/qemu/configure @@ -34,6 +34,8 @@ ar="ar" make="make" install="install" strip="strip" +objcopy="objcopy" +ld="ld" # parse CC options first for opt do @@ -53,6 +55,8 @@ done cc="${cross_prefix}${cc}" ar="${cross_prefix}${ar}" strip="${cross_prefix}${strip}" +objcopy="${cross_prefix}${objcopy}" +ld="${cross_prefix}${ld}" # check that the C compiler works. cat > $TMPC <> $config_mak echo "CC=$cc" >> $config_mak echo "HOST_CC=$host_cc" >> $config_mak echo "AR=$ar" >> $config_mak +echo "OBJCOPY=$objcopy" >> $config_mak +echo "LD=$ld" >> $config_mak # XXX: only use CFLAGS and LDFLAGS ? # XXX: should export HOST_CFLAGS and HOST_LDFLAGS for cross # compilation of dyngen tool (useful for win32 build on Linux host) diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index f21169b9..64322a05 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.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 . */ /* @@ -421,7 +420,7 @@ int cpu_exec(CPUState *env1) env->hflags2 |= HF2_NMI_MASK; do_interrupt(EXCP02_NMI, 0, 0, 0, 1); next_tb = 0; - } else if (interrupt_request & CPU_INTERRUPT_MCE) { + } else if (interrupt_request & CPU_INTERRUPT_MCE) { env->interrupt_request &= ~CPU_INTERRUPT_MCE; do_interrupt(EXCP12_MCHK, 0, 0, 0, 0); next_tb = 0; @@ -496,7 +495,7 @@ int cpu_exec(CPUState *env1) } #elif defined(TARGET_SPARC) if ((interrupt_request & CPU_INTERRUPT_HARD) && - (env->psret != 0)) { + cpu_interrupts_enabled(env)) { int pil = env->interrupt_index & 15; int type = env->interrupt_index & 0xf0; @@ -507,7 +506,7 @@ int cpu_exec(CPUState *env1) env->exception_index = env->interrupt_index; do_interrupt(env); env->interrupt_index = 0; -#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) +#if !defined(CONFIG_USER_ONLY) cpu_check_irqs(env); #endif next_tb = 0; diff --git a/qemu/exec.c b/qemu/exec.c index e591a099..b4458b96 100644 --- a/qemu/exec.c +++ b/qemu/exec.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 . */ #include "config.h" #ifdef _WIN32 @@ -1508,7 +1507,6 @@ void cpu_single_step(CPUState *env, int enabled) } } - /* enable or disable low levels log */ void cpu_set_log(int log_flags) { @@ -1770,6 +1768,13 @@ static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr) TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *)); } +static CPUTLBEntry s_cputlb_empty_entry = { + .addr_read = -1, + .addr_write = -1, + .addr_code = -1, + .addend = -1, +}; + /* NOTE: if flush_global is true, also flush global entries (not implemented yet) */ void tlb_flush(CPUState *env, int flush_global) @@ -1786,9 +1791,7 @@ void tlb_flush(CPUState *env, int flush_global) for(i = 0; i < CPU_TLB_SIZE; i++) { int mmu_idx; for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { - env->tlb_table[mmu_idx][i].addr_read = -1; - env->tlb_table[mmu_idx][i].addr_write = -1; - env->tlb_table[mmu_idx][i].addr_code = -1; + env->tlb_table[mmu_idx][i] = s_cputlb_empty_entry; } } @@ -1810,9 +1813,7 @@ static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr) (TARGET_PAGE_MASK | TLB_INVALID_MASK)) || addr == (tlb_entry->addr_code & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - tlb_entry->addr_read = -1; - tlb_entry->addr_write = -1; - tlb_entry->addr_code = -1; + *tlb_entry = s_cputlb_empty_entry; } } diff --git a/qemu/gdb-xml/power-core.xml b/qemu/gdb-xml/power-core.xml index dae13a67..0c69e8c8 100644 --- a/qemu/gdb-xml/power-core.xml +++ b/qemu/gdb-xml/power-core.xml @@ -46,13 +46,4 @@ - - diff --git a/qemu/gdb-xml/power-fpu.xml b/qemu/gdb-xml/power-fpu.xml index d1ca3a3d..38705515 100644 --- a/qemu/gdb-xml/power-fpu.xml +++ b/qemu/gdb-xml/power-fpu.xml @@ -7,7 +7,7 @@ - + diff --git a/qemu/gdb-xml/power-spe.xml b/qemu/gdb-xml/power-spe.xml index 1ec15d66..57740cc5 100644 --- a/qemu/gdb-xml/power-spe.xml +++ b/qemu/gdb-xml/power-spe.xml @@ -7,7 +7,7 @@ - + diff --git a/qemu/gdb-xml/power64-core.xml b/qemu/gdb-xml/power64-core.xml index fef42e41..6cc15312 100644 --- a/qemu/gdb-xml/power64-core.xml +++ b/qemu/gdb-xml/power64-core.xml @@ -46,13 +46,4 @@ - - diff --git a/qemu/gdbstub.c b/qemu/gdbstub.c index 5549bcc2..157e031a 100644 --- a/qemu/gdbstub.c +++ b/qemu/gdbstub.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 . */ #include "config.h" #include "qemu-common.h" @@ -511,112 +510,136 @@ static const int gpr_map[8] = {0, 1, 2, 3, 4, 5, 6, 7}; #define NUM_CORE_REGS (CPU_NB_REGS * 2 + 25) +#define IDX_IP_REG CPU_NB_REGS +#define IDX_FLAGS_REG (IDX_IP_REG + 1) +#define IDX_SEG_REGS (IDX_FLAGS_REG + 1) +#define IDX_FP_REGS (IDX_SEG_REGS + 6) +#define IDX_XMM_REGS (IDX_FP_REGS + 16) +#define IDX_MXCSR_REG (IDX_XMM_REGS + CPU_NB_REGS) + static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n) { if (n < CPU_NB_REGS) { GET_REGL(env->regs[gpr_map[n]]); - } else if (n >= CPU_NB_REGS + 8 && n < CPU_NB_REGS + 16) { - /* FIXME: byteswap float values. */ + } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) { #ifdef USE_X86LDOUBLE - memcpy(mem_buf, &env->fpregs[n - (CPU_NB_REGS + 8)], 10); + /* FIXME: byteswap float values - after fixing fpregs layout. */ + memcpy(mem_buf, &env->fpregs[n - IDX_FP_REGS], 10); #else memset(mem_buf, 0, 10); #endif return 10; - } else if (n >= CPU_NB_REGS + 24) { - n -= CPU_NB_REGS + 24; - if (n < CPU_NB_REGS) { - stq_p(mem_buf, env->xmm_regs[n].XMM_Q(0)); - stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1)); - return 16; - } else if (n == CPU_NB_REGS) { - GET_REG32(env->mxcsr); - } + } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) { + n -= IDX_XMM_REGS; + stq_p(mem_buf, env->xmm_regs[n].XMM_Q(0)); + stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1)); + return 16; } else { - n -= CPU_NB_REGS; switch (n) { - case 0: GET_REGL(env->eip); - case 1: GET_REG32(env->eflags); - case 2: GET_REG32(env->segs[R_CS].selector); - case 3: GET_REG32(env->segs[R_SS].selector); - case 4: GET_REG32(env->segs[R_DS].selector); - case 5: GET_REG32(env->segs[R_ES].selector); - case 6: GET_REG32(env->segs[R_FS].selector); - case 7: GET_REG32(env->segs[R_GS].selector); - /* 8...15 x87 regs. */ - case 16: GET_REG32(env->fpuc); - case 17: GET_REG32((env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11); - case 18: GET_REG32(0); /* ftag */ - case 19: GET_REG32(0); /* fiseg */ - case 20: GET_REG32(0); /* fioff */ - case 21: GET_REG32(0); /* foseg */ - case 22: GET_REG32(0); /* fooff */ - case 23: GET_REG32(0); /* fop */ - /* 24+ xmm regs. */ + case IDX_IP_REG: GET_REGL(env->eip); + case IDX_FLAGS_REG: GET_REG32(env->eflags); + + case IDX_SEG_REGS: GET_REG32(env->segs[R_CS].selector); + case IDX_SEG_REGS + 1: GET_REG32(env->segs[R_SS].selector); + case IDX_SEG_REGS + 2: GET_REG32(env->segs[R_DS].selector); + case IDX_SEG_REGS + 3: GET_REG32(env->segs[R_ES].selector); + case IDX_SEG_REGS + 4: GET_REG32(env->segs[R_FS].selector); + case IDX_SEG_REGS + 5: GET_REG32(env->segs[R_GS].selector); + + case IDX_FP_REGS + 8: GET_REG32(env->fpuc); + case IDX_FP_REGS + 9: GET_REG32((env->fpus & ~0x3800) | + (env->fpstt & 0x7) << 11); + case IDX_FP_REGS + 10: GET_REG32(0); /* ftag */ + case IDX_FP_REGS + 11: GET_REG32(0); /* fiseg */ + case IDX_FP_REGS + 12: GET_REG32(0); /* fioff */ + case IDX_FP_REGS + 13: GET_REG32(0); /* foseg */ + case IDX_FP_REGS + 14: GET_REG32(0); /* fooff */ + case IDX_FP_REGS + 15: GET_REG32(0); /* fop */ + + case IDX_MXCSR_REG: GET_REG32(env->mxcsr); } } return 0; } -static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int i) +static int cpu_x86_gdb_load_seg(CPUState *env, int sreg, uint8_t *mem_buf) +{ + uint16_t selector = ldl_p(mem_buf); + + if (selector != env->segs[sreg].selector) { +#if defined(CONFIG_USER_ONLY) + cpu_x86_load_seg(env, sreg, selector); +#else + unsigned int limit, flags; + target_ulong base; + + if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) { + base = selector << 4; + limit = 0xffff; + flags = 0; + } else { + if (!cpu_x86_get_descr_debug(env, selector, &base, &limit, &flags)) + return 4; + } + cpu_x86_load_seg_cache(env, sreg, selector, base, limit, flags); +#endif + } + return 4; +} + +static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n) { uint32_t tmp; - if (i < CPU_NB_REGS) { - env->regs[gpr_map[i]] = ldtul_p(mem_buf); + if (n < CPU_NB_REGS) { + env->regs[gpr_map[n]] = ldtul_p(mem_buf); return sizeof(target_ulong); - } else if (i >= CPU_NB_REGS + 8 && i < CPU_NB_REGS + 16) { - i -= CPU_NB_REGS + 8; + } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) { #ifdef USE_X86LDOUBLE - memcpy(&env->fpregs[i], mem_buf, 10); + /* FIXME: byteswap float values - after fixing fpregs layout. */ + memcpy(&env->fpregs[n - IDX_FP_REGS], mem_buf, 10); #endif return 10; - } else if (i >= CPU_NB_REGS + 24) { - i -= CPU_NB_REGS + 24; - if (i < CPU_NB_REGS) { - env->xmm_regs[i].XMM_Q(0) = ldq_p(mem_buf); - env->xmm_regs[i].XMM_Q(1) = ldq_p(mem_buf + 8); - return 16; - } else if (i == CPU_NB_REGS) { + } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) { + n -= IDX_XMM_REGS; + env->xmm_regs[n].XMM_Q(0) = ldq_p(mem_buf); + env->xmm_regs[n].XMM_Q(1) = ldq_p(mem_buf + 8); + return 16; + } else { + switch (n) { + case IDX_IP_REG: + env->eip = ldtul_p(mem_buf); + return sizeof(target_ulong); + case IDX_FLAGS_REG: + env->eflags = ldl_p(mem_buf); + return 4; + + case IDX_SEG_REGS: return cpu_x86_gdb_load_seg(env, R_CS, mem_buf); + case IDX_SEG_REGS + 1: return cpu_x86_gdb_load_seg(env, R_SS, mem_buf); + case IDX_SEG_REGS + 2: return cpu_x86_gdb_load_seg(env, R_DS, mem_buf); + case IDX_SEG_REGS + 3: return cpu_x86_gdb_load_seg(env, R_ES, mem_buf); + case IDX_SEG_REGS + 4: return cpu_x86_gdb_load_seg(env, R_FS, mem_buf); + case IDX_SEG_REGS + 5: return cpu_x86_gdb_load_seg(env, R_GS, mem_buf); + + case IDX_FP_REGS + 8: + env->fpuc = ldl_p(mem_buf); + return 4; + case IDX_FP_REGS + 9: + tmp = ldl_p(mem_buf); + env->fpstt = (tmp >> 11) & 7; + env->fpus = tmp & ~0x3800; + return 4; + case IDX_FP_REGS + 10: /* ftag */ return 4; + case IDX_FP_REGS + 11: /* fiseg */ return 4; + case IDX_FP_REGS + 12: /* fioff */ return 4; + case IDX_FP_REGS + 13: /* foseg */ return 4; + case IDX_FP_REGS + 14: /* fooff */ return 4; + case IDX_FP_REGS + 15: /* fop */ return 4; + + case IDX_MXCSR_REG: env->mxcsr = ldl_p(mem_buf); return 4; } - } else { - i -= CPU_NB_REGS; - switch (i) { - case 0: env->eip = ldtul_p(mem_buf); return sizeof(target_ulong); - case 1: env->eflags = ldl_p(mem_buf); return 4; -#if defined(CONFIG_USER_ONLY) -#define LOAD_SEG(index, sreg)\ - tmp = ldl_p(mem_buf);\ - if (tmp != env->segs[sreg].selector)\ - cpu_x86_load_seg(env, sreg, tmp); -#else -/* FIXME: Honor segment registers. Needs to avoid raising an exception - when the selector is invalid. */ -#define LOAD_SEG(index, sreg) do {} while(0) -#endif - case 2: LOAD_SEG(10, R_CS); return 4; - case 3: LOAD_SEG(11, R_SS); return 4; - case 4: LOAD_SEG(12, R_DS); return 4; - case 5: LOAD_SEG(13, R_ES); return 4; - case 6: LOAD_SEG(14, R_FS); return 4; - case 7: LOAD_SEG(15, R_GS); return 4; - /* 8...15 x87 regs. */ - case 16: env->fpuc = ldl_p(mem_buf); return 4; - case 17: - tmp = ldl_p(mem_buf); - env->fpstt = (tmp >> 11) & 7; - env->fpus = tmp & ~0x3800; - return 4; - case 18: /* ftag */ return 4; - case 19: /* fiseg */ return 4; - case 20: /* fioff */ return 4; - case 21: /* foseg */ return 4; - case 22: /* fooff */ return 4; - case 23: /* fop */ return 4; - /* 24+ xmm regs. */ - } } /* Unrecognised register. */ return 0; @@ -1634,6 +1657,64 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) s->signal = 0; gdb_continue(s); return RS_IDLE; + case 'v': + if (strncmp(p, "Cont", 4) == 0) { + int res_signal, res_thread; + + p += 4; + if (*p == '?') { + put_packet(s, "vCont;c;C;s;S"); + break; + } + res = 0; + res_signal = 0; + res_thread = 0; + while (*p) { + int action, signal; + + if (*p++ != ';') { + res = 0; + break; + } + action = *p++; + signal = 0; + if (action == 'C' || action == 'S') { + signal = strtoul(p, (char **)&p, 16); + } else if (action != 'c' && action != 's') { + res = 0; + break; + } + thread = 0; + if (*p == ':') { + thread = strtoull(p+1, (char **)&p, 16); + } + action = tolower(action); + if (res == 0 || (res == 'c' && action == 's')) { + res = action; + res_signal = signal; + res_thread = thread; + } + } + if (res) { + if (res_thread != -1 && res_thread != 0) { + env = find_cpu(res_thread); + if (env == NULL) { + put_packet(s, "E22"); + break; + } + s->c_cpu = env; + } + if (res == 's') { + cpu_single_step(s->c_cpu, sstep_flags); + } + s->signal = res_signal; + gdb_continue(s); + return RS_IDLE; + } + break; + } else { + goto unknown_command; + } case 'k': /* Kill the target */ fprintf(stderr, "\nQEMU: Terminated via GDBstub\n"); diff --git a/qemu/hw/ac97.c b/qemu/hw/ac97.c index 37aca9e8..f18fa524 100644 --- a/qemu/hw/ac97.c +++ b/qemu/hw/ac97.c @@ -1308,9 +1308,9 @@ static void ac97_on_reset (void *opaque) mixer_reset (s); } -static void ac97_initfn(PCIDevice *dev) +static void ac97_initfn (PCIDevice *dev) { - PCIAC97LinkState *d = DO_UPCAST(PCIAC97LinkState, dev, dev); + PCIAC97LinkState *d = DO_UPCAST (PCIAC97LinkState, dev, dev); AC97LinkState *s = &d->ac97; uint8_t *c = d->dev.config; @@ -1360,19 +1360,19 @@ static void ac97_initfn(PCIDevice *dev) int ac97_init (PCIBus *bus) { - pci_create_simple(bus, -1, "AC97"); + pci_create_simple (bus, -1, "AC97"); return 0; } static PCIDeviceInfo ac97_info = { .qdev.name = "AC97", - .qdev.size = sizeof(PCIAC97LinkState), + .qdev.size = sizeof (PCIAC97LinkState), .init = ac97_initfn, }; -static void ac97_register(void) +static void ac97_register (void) { - pci_qdev_register(&ac97_info); + pci_qdev_register (&ac97_info); } -device_init(ac97_register); +device_init (ac97_register); diff --git a/qemu/hw/apb_pci.c b/qemu/hw/apb_pci.c index 5f411aa0..9f2a44d5 100644 --- a/qemu/hw/apb_pci.c +++ b/qemu/hw/apb_pci.c @@ -263,7 +263,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base, d->config[0x09] = 0x00; // programming i/f pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); d->config[0x0D] = 0x10; // latency_timer - d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_BRIDGE; // header_type + d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type /* APB secondary busses */ *bus2 = pci_bridge_init(s->bus, 8, PCI_VENDOR_ID_SUN, diff --git a/qemu/hw/arm_sysctl.c b/qemu/hw/arm_sysctl.c index c9d1e3ff..bb005c80 100644 --- a/qemu/hw/arm_sysctl.c +++ b/qemu/hw/arm_sysctl.c @@ -194,7 +194,6 @@ static void arm_sysctl_init1(SysBusDevice *dev) arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev); int iomemtype; - s->sys_id = qdev_get_prop_int(&dev->qdev, "sys_id", 0); /* The MPcore bootloader uses these flags to start secondary CPUs. We don't use a bootloader, so do this here. */ s->flags = 3; @@ -210,15 +209,28 @@ void arm_sysctl_init(uint32_t base, uint32_t sys_id) DeviceState *dev; dev = qdev_create(NULL, "realview_sysctl"); - qdev_set_prop_int(dev, "sys_id", sys_id); + qdev_prop_set_uint32(dev, "sys_id", sys_id); qdev_init(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); } +static SysBusDeviceInfo arm_sysctl_info = { + .init = arm_sysctl_init1, + .qdev.name = "realview_sysctl", + .qdev.size = sizeof(arm_sysctl_state), + .qdev.props = (Property[]) { + { + .name = "sys_id", + .info = &qdev_prop_uint32, + .offset = offsetof(arm_sysctl_state, sys_id), + }, + {/* end of list */} + } +}; + static void arm_sysctl_register_devices(void) { - sysbus_register_dev("realview_sysctl", sizeof(arm_sysctl_state), - arm_sysctl_init1); + sysbus_register_withprop(&arm_sysctl_info); } device_init(arm_sysctl_register_devices) diff --git a/qemu/hw/armv7m.c b/qemu/hw/armv7m.c index 297a3e1f..2e66d7e9 100644 --- a/qemu/hw/armv7m.c +++ b/qemu/hw/armv7m.c @@ -127,7 +127,6 @@ static void bitband_init(SysBusDevice *dev) BitBandState *s = FROM_SYSBUS(BitBandState, dev); int iomemtype; - s->base = qdev_get_prop_int(&dev->qdev, "base", 0); iomemtype = cpu_register_io_memory(bitband_readfn, bitband_writefn, &s->base); sysbus_init_mmio(dev, 0x02000000, iomemtype); @@ -138,12 +137,12 @@ static void armv7m_bitband_init(void) DeviceState *dev; dev = qdev_create(NULL, "ARM,bitband-memory"); - qdev_set_prop_int(dev, "base", 0x20000000); + qdev_prop_set_uint32(dev, "base", 0x20000000); qdev_init(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x22000000); dev = qdev_create(NULL, "ARM,bitband-memory"); - qdev_set_prop_int(dev, "base", 0x40000000); + qdev_prop_set_uint32(dev, "base", 0x40000000); qdev_init(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x42000000); } @@ -238,10 +237,23 @@ qemu_irq *armv7m_init(int flash_size, int sram_size, return pic; } +static SysBusDeviceInfo bitband_info = { + .init = bitband_init, + .qdev.name = "ARM,bitband-memory", + .qdev.size = sizeof(BitBandState), + .qdev.props = (Property[]) { + { + .name = "base", + .info = &qdev_prop_hex32, + .offset = offsetof(BitBandState, base), + }, + {/* end of list */} + } +}; + static void armv7m_register_devices(void) { - sysbus_register_dev("ARM,bitband-memory", sizeof(BitBandState), - bitband_init); + sysbus_register_withprop(&bitband_info); } device_init(armv7m_register_devices) diff --git a/qemu/hw/axis_dev88.c b/qemu/hw/axis_dev88.c index 79a4d710..f93f4314 100644 --- a/qemu/hw/axis_dev88.c +++ b/qemu/hw/axis_dev88.c @@ -297,7 +297,7 @@ void axisdev88_init (ram_addr_t ram_size, cpu_irq = cris_pic_init_cpu(env); dev = qdev_create(NULL, "etraxfs,pic"); /* FIXME: Is there a proper way to signal vectors to the CPU core? */ - qdev_set_prop_ptr(dev, "interrupt_vector", &env->interrupt_vector); + qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector); qdev_init(dev); s = sysbus_from_qdev(dev); sysbus_mmio_map(s, 0, 0x3001c000); diff --git a/qemu/hw/boards.h b/qemu/hw/boards.h index f6733b7c..11acb89f 100644 --- a/qemu/hw/boards.h +++ b/qemu/hw/boards.h @@ -3,6 +3,8 @@ #ifndef HW_BOARDS_H #define HW_BOARDS_H +#include "qdev.h" + typedef void QEMUMachineInitFunc(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, @@ -17,6 +19,7 @@ typedef struct QEMUMachine { int use_scsi; int max_cpus; int is_default; + CompatProperty *compat_props; struct QEMUMachine *next; } QEMUMachine; diff --git a/qemu/hw/cs4231.c b/qemu/hw/cs4231.c index a981b094..da841027 100644 --- a/qemu/hw/cs4231.c +++ b/qemu/hw/cs4231.c @@ -21,8 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" + #include "sun4m.h" +#include "sysbus.h" /* debug CS4231 */ //#define DEBUG_CS @@ -36,9 +37,10 @@ #define CS_MAXDREG (CS_DREGS - 1) typedef struct CSState { + SysBusDevice busdev; + qemu_irq irq; uint32_t regs[CS_REGS]; uint8_t dregs[CS_DREGS]; - void *intctl; } CSState; #define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG) @@ -165,16 +167,32 @@ static int cs_load(QEMUFile *f, void *opaque, int version_id) return 0; } -void cs_init(target_phys_addr_t base, int irq, void *intctl) +static void cs4231_init1(SysBusDevice *dev) { - int cs_io_memory; - CSState *s; + int io; + CSState *s = FROM_SYSBUS(CSState, dev); - s = qemu_mallocz(sizeof(CSState)); + io = cpu_register_io_memory(cs_mem_read, cs_mem_write, s); + sysbus_init_mmio(dev, CS_SIZE, io); + sysbus_init_irq(dev, &s->irq); - cs_io_memory = cpu_register_io_memory(cs_mem_read, cs_mem_write, s); - cpu_register_physical_memory(base, CS_SIZE, cs_io_memory); - register_savevm("cs4231", base, 1, cs_save, cs_load, s); + register_savevm("cs4231", -1, 1, cs_save, cs_load, s); qemu_register_reset(cs_reset, s); cs_reset(s); } + +static SysBusDeviceInfo cs4231_info = { + .init = cs4231_init1, + .qdev.name = "SUNW,CS4231", + .qdev.size = sizeof(CSState), + .qdev.props = (Property[]) { + {.name = NULL} + } +}; + +static void cs4231_register_devices(void) +{ + sysbus_register_withprop(&cs4231_info); +} + +device_init(cs4231_register_devices); diff --git a/qemu/hw/eccmemctl.c b/qemu/hw/eccmemctl.c index 3430481c..193248c4 100644 --- a/qemu/hw/eccmemctl.c +++ b/qemu/hw/eccmemctl.c @@ -21,9 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" + #include "sun4m.h" -#include "sysemu.h" +#include "sysbus.h" //#define DEBUG_ECC @@ -126,6 +126,7 @@ #define ECC_DIAG_MASK (ECC_DIAG_SIZE - 1) typedef struct ECCState { + SysBusDevice busdev; qemu_irq irq; uint32_t regs[ECC_NREGS]; uint8_t diag[ECC_DIAG_SIZE]; @@ -314,27 +315,61 @@ static void ecc_reset(void *opaque) s->regs[ECC_ECR1] = 0; } -void * ecc_init(target_phys_addr_t base, qemu_irq irq, uint32_t version) +static void ecc_init1(SysBusDevice *dev) { int ecc_io_memory; - ECCState *s; - - s = qemu_mallocz(sizeof(ECCState)); - - s->version = version; - s->regs[0] = version; - s->irq = irq; + ECCState *s = FROM_SYSBUS(ECCState, dev); + sysbus_init_irq(dev, &s->irq); + s->regs[0] = s->version; ecc_io_memory = cpu_register_io_memory(ecc_mem_read, ecc_mem_write, s); - cpu_register_physical_memory(base, ECC_SIZE, ecc_io_memory); - if (version == ECC_MCC) { // SS-600MP only + sysbus_init_mmio(dev, ECC_SIZE, ecc_io_memory); + + if (s->version == ECC_MCC) { // SS-600MP only ecc_io_memory = cpu_register_io_memory(ecc_diag_mem_read, ecc_diag_mem_write, s); - cpu_register_physical_memory(base + 0x1000, ECC_DIAG_SIZE, - ecc_io_memory); + sysbus_init_mmio(dev, ECC_DIAG_SIZE, ecc_io_memory); } - register_savevm("ECC", base, 3, ecc_save, ecc_load, s); + register_savevm("ECC", -1, 3, ecc_save, ecc_load, s); qemu_register_reset(ecc_reset, s); ecc_reset(s); - return s; } + +void ecc_init(target_phys_addr_t base, qemu_irq irq, uint32_t version) +{ + DeviceState *dev; + SysBusDevice *s; + + dev = qdev_create(NULL, "eccmemctl"); + qdev_prop_set_uint32(dev, "version", version); + qdev_init(dev); + s = sysbus_from_qdev(dev); + sysbus_connect_irq(s, 0, irq); + sysbus_mmio_map(s, 0, base); + if (version == ECC_MCC) { // SS-600MP only + sysbus_mmio_map(s, 1, base + 0x1000); + } +} + +static SysBusDeviceInfo ecc_info = { + .init = ecc_init1, + .qdev.name = "eccmemctl", + .qdev.size = sizeof(ECCState), + .qdev.props = (Property[]) { + { + .name = "version", + .info = &qdev_prop_uint32, + .offset = offsetof(ECCState, version), + .defval = (uint32_t[]) { -1 }, + }, + {/* end of list */} + } +}; + + +static void ecc_register_devices(void) +{ + sysbus_register_withprop(&ecc_info); +} + +device_init(ecc_register_devices); diff --git a/qemu/hw/es1370.c b/qemu/hw/es1370.c index 9e860f9b..8d5a9f98 100644 --- a/qemu/hw/es1370.c +++ b/qemu/hw/es1370.c @@ -1054,13 +1054,13 @@ int es1370_init (PCIBus *bus) static PCIDeviceInfo es1370_info = { .qdev.name = "ES1370", - .qdev.size = sizeof(PCIES1370State), + .qdev.size = sizeof (PCIES1370State), .init = es1370_initfn, }; static void es1370_register(void) { - pci_qdev_register(&es1370_info); + pci_qdev_register (&es1370_info); } -device_init(es1370_register); +device_init (es1370_register); diff --git a/qemu/hw/escc.c b/qemu/hw/escc.c index fe5655d0..34ca2240 100644 --- a/qemu/hw/escc.c +++ b/qemu/hw/escc.c @@ -21,7 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #include "hw.h" +#include "sysbus.h" #include "escc.h" #include "qemu-char.h" #include "console.h" @@ -124,8 +126,12 @@ typedef struct ChannelState { } ChannelState; struct SerialState { + SysBusDevice busdev; struct ChannelState chn[2]; int it_shift; + int mmio_index; + uint32_t disabled; + uint32_t frequency; }; #define SERIAL_CTRL 0 @@ -750,44 +756,28 @@ int escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB, CharDriverState *chrA, CharDriverState *chrB, int clock, int it_shift) { - int escc_io_memory, i; - SerialState *s; - - s = qemu_mallocz(sizeof(SerialState)); - - escc_io_memory = cpu_register_io_memory(escc_mem_read, - escc_mem_write, - s); - if (base) - cpu_register_physical_memory(base, ESCC_SIZE << it_shift, - escc_io_memory); - - s->it_shift = it_shift; - s->chn[0].chr = chrB; - s->chn[1].chr = chrA; - s->chn[0].disabled = 0; - s->chn[1].disabled = 0; - s->chn[0].irq = irqB; - s->chn[1].irq = irqA; - - for (i = 0; i < 2; i++) { - s->chn[i].chn = 1 - i; - s->chn[i].type = ser; - s->chn[i].clock = clock / 2; - if (s->chn[i].chr) { - qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive, - serial_receive1, serial_event, &s->chn[i]); - } + DeviceState *dev; + SysBusDevice *s; + SerialState *d; + + dev = qdev_create(NULL, "escc"); + qdev_prop_set_uint32(dev, "disabled", 0); + qdev_prop_set_uint32(dev, "frequency", clock); + qdev_prop_set_uint32(dev, "it_shift", it_shift); + qdev_prop_set_ptr(dev, "chrB", chrB); + qdev_prop_set_ptr(dev, "chrA", chrA); + qdev_prop_set_uint32(dev, "chnBtype", ser); + qdev_prop_set_uint32(dev, "chnAtype", ser); + qdev_init(dev); + s = sysbus_from_qdev(dev); + sysbus_connect_irq(s, 0, irqA); + sysbus_connect_irq(s, 1, irqB); + if (base) { + sysbus_mmio_map(s, 0, base); } - s->chn[0].otherchn = &s->chn[1]; - s->chn[1].otherchn = &s->chn[0]; - if (base) - register_savevm("escc", base, 2, escc_save, escc_load, s); - else - register_savevm("escc", -1, 2, escc_save, escc_load, s); - qemu_register_reset(escc_reset, s); - escc_reset(s); - return escc_io_memory; + + d = FROM_SYSBUS(SerialState, s); + return d->mmio_index; } static const uint8_t keycodes[128] = { @@ -930,35 +920,107 @@ static void sunmouse_event(void *opaque, void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq, int disabled, int clock, int it_shift) { - int slavio_serial_io_memory, i; - SerialState *s; + DeviceState *dev; + SysBusDevice *s; + + dev = qdev_create(NULL, "escc"); + qdev_prop_set_uint32(dev, "disabled", disabled); + qdev_prop_set_uint32(dev, "frequency", clock); + qdev_prop_set_uint32(dev, "it_shift", it_shift); + qdev_prop_set_ptr(dev, "chrB", NULL); + qdev_prop_set_ptr(dev, "chrA", NULL); + qdev_prop_set_uint32(dev, "chnBtype", mouse); + qdev_prop_set_uint32(dev, "chnAtype", kbd); + qdev_init(dev); + s = sysbus_from_qdev(dev); + sysbus_connect_irq(s, 0, irq); + sysbus_connect_irq(s, 1, irq); + sysbus_mmio_map(s, 0, base); +} - s = qemu_mallocz(sizeof(SerialState)); +static void escc_init1(SysBusDevice *dev) +{ + SerialState *s = FROM_SYSBUS(SerialState, dev); + int io; + unsigned int i; - s->it_shift = it_shift; + s->chn[0].disabled = s->disabled; + s->chn[1].disabled = s->disabled; for (i = 0; i < 2; i++) { - s->chn[i].irq = irq; + sysbus_init_irq(dev, &s->chn[i].irq); s->chn[i].chn = 1 - i; - s->chn[i].chr = NULL; - s->chn[i].clock = clock / 2; + s->chn[i].clock = s->frequency / 2; + if (s->chn[i].chr) { + qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive, + serial_receive1, serial_event, &s->chn[i]); + } } s->chn[0].otherchn = &s->chn[1]; s->chn[1].otherchn = &s->chn[0]; - s->chn[0].type = mouse; - s->chn[1].type = kbd; - s->chn[0].disabled = disabled; - s->chn[1].disabled = disabled; - - slavio_serial_io_memory = cpu_register_io_memory(escc_mem_read, - escc_mem_write, - s); - cpu_register_physical_memory(base, ESCC_SIZE << it_shift, - slavio_serial_io_memory); - - qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, - "QEMU Sun Mouse"); - qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]); - register_savevm("slavio_serial_mouse", base, 2, escc_save, escc_load, s); + + io = cpu_register_io_memory(escc_mem_read, escc_mem_write, s); + sysbus_init_mmio(dev, ESCC_SIZE << s->it_shift, io); + s->mmio_index = io; + + if (s->chn[0].type == mouse) { + qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, + "QEMU Sun Mouse"); + } + if (s->chn[1].type == kbd) { + qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]); + } + register_savevm("escc", -1, 2, escc_save, escc_load, s); qemu_register_reset(escc_reset, s); escc_reset(s); } + +static SysBusDeviceInfo escc_info = { + .init = escc_init1, + .qdev.name = "escc", + .qdev.size = sizeof(SerialState), + .qdev.props = (Property[]) { + { + .name = "frequency", + .info = &qdev_prop_uint32, + .offset = offsetof(SerialState, frequency), + }, + { + .name = "it_shift", + .info = &qdev_prop_uint32, + .offset = offsetof(SerialState, it_shift), + }, + { + .name = "disabled", + .info = &qdev_prop_uint32, + .offset = offsetof(SerialState, disabled), + }, + { + .name = "chrB", + .info = &qdev_prop_ptr, + .offset = offsetof(SerialState, chn[1].chr), + }, + { + .name = "chrA", + .info = &qdev_prop_ptr, + .offset = offsetof(SerialState, chn[0].chr), + }, + { + .name = "chnBtype", + .info = &qdev_prop_uint32, + .offset = offsetof(SerialState, chn[1].type), + }, + { + .name = "chnAtype", + .info = &qdev_prop_uint32, + .offset = offsetof(SerialState, chn[0].type), + }, + {/* end of list */} + } +}; + +static void escc_register_devices(void) +{ + sysbus_register_withprop(&escc_info); +} + +device_init(escc_register_devices); diff --git a/qemu/hw/esp.c b/qemu/hw/esp.c index 469acc10..207570a4 100644 --- a/qemu/hw/esp.c +++ b/qemu/hw/esp.c @@ -678,12 +678,14 @@ void esp_init(target_phys_addr_t espaddr, int it_shift, { DeviceState *dev; SysBusDevice *s; + ESPState *esp; dev = qdev_create(NULL, "esp"); - qdev_set_prop_ptr(dev, "dma_memory_read", dma_memory_read); - qdev_set_prop_ptr(dev, "dma_memory_write", dma_memory_write); - qdev_set_prop_ptr(dev, "dma_opaque", dma_opaque); - qdev_set_prop_int(dev, "it_shift", it_shift); + esp = DO_UPCAST(ESPState, busdev.qdev, dev); + esp->dma_memory_read = dma_memory_read; + esp->dma_memory_write = dma_memory_write; + esp->dma_opaque = dma_opaque; + esp->it_shift = it_shift; qdev_init(dev); s = sysbus_from_qdev(dev); sysbus_connect_irq(s, 0, irq); @@ -696,11 +698,7 @@ static void esp_init1(SysBusDevice *dev) int esp_io_memory; sysbus_init_irq(dev, &s->irq); - s->it_shift = qdev_get_prop_int(&dev->qdev, "it_shift", -1); assert(s->it_shift != -1); - s->dma_memory_read = qdev_get_prop_ptr(&dev->qdev, "dma_memory_read"); - s->dma_memory_write = qdev_get_prop_ptr(&dev->qdev, "dma_memory_write"); - s->dma_opaque = qdev_get_prop_ptr(&dev->qdev, "dma_opaque"); esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s); sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory); diff --git a/qemu/hw/etraxfs.c b/qemu/hw/etraxfs.c index 94cd6bc8..c2eca527 100644 --- a/qemu/hw/etraxfs.c +++ b/qemu/hw/etraxfs.c @@ -88,7 +88,7 @@ void bareetraxfs_init (ram_addr_t ram_size, cpu_irq = cris_pic_init_cpu(env); dev = qdev_create(NULL, "etraxfs,pic"); /* FIXME: Is there a proper way to signal vectors to the CPU core? */ - qdev_set_prop_ptr(dev, "interrupt_vector", &env->interrupt_vector); + qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector); qdev_init(dev); s = sysbus_from_qdev(dev); sysbus_mmio_map(s, 0, 0x3001c000); diff --git a/qemu/hw/etraxfs_pic.c b/qemu/hw/etraxfs_pic.c index 1c674279..e6272189 100644 --- a/qemu/hw/etraxfs_pic.c +++ b/qemu/hw/etraxfs_pic.c @@ -140,7 +140,6 @@ static void etraxfs_pic_init(SysBusDevice *dev) struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev); int intr_vect_regs; - s->interrupt_vector = qdev_get_prop_ptr(&dev->qdev, "interrupt_vector"); qdev_init_gpio_in(&dev->qdev, irq_handler, 32); sysbus_init_irq(dev, &s->parent_irq); sysbus_init_irq(dev, &s->parent_nmi); @@ -149,10 +148,23 @@ static void etraxfs_pic_init(SysBusDevice *dev) sysbus_init_mmio(dev, R_MAX * 4, intr_vect_regs); } +static SysBusDeviceInfo etraxfs_pic_info = { + .init = etraxfs_pic_init, + .qdev.name = "etraxfs,pic", + .qdev.size = sizeof(struct etrax_pic), + .qdev.props = (Property[]) { + { + .name = "interrupt_vector", + .info = &qdev_prop_ptr, + .offset = offsetof(struct etrax_pic, interrupt_vector), + }, + {/* end of list */} + } +}; + static void etraxfs_pic_register(void) { - sysbus_register_dev("etraxfs,pic", sizeof (struct etrax_pic), - etraxfs_pic_init); + sysbus_register_withprop(&etraxfs_pic_info); } device_init(etraxfs_pic_register) diff --git a/qemu/hw/fdc.c b/qemu/hw/fdc.c index 311e7cb7..e8177d97 100644 --- a/qemu/hw/fdc.c +++ b/qemu/hw/fdc.c @@ -26,11 +26,13 @@ * The controller is used in Sun4m systems in a slightly different * way. There are changes in DOR register and DMA is not available. */ + #include "hw.h" #include "fdc.h" #include "block.h" #include "qemu-timer.h" #include "isa.h" +#include "sysbus.h" /********************************************************/ /* debug Floppy devices */ @@ -468,6 +470,7 @@ enum { #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT) struct fdctrl_t { + SysBusDevice busdev; /* Controller's identification */ uint8_t version; /* HW */ @@ -508,6 +511,8 @@ struct fdctrl_t { /* Floppy drives */ fdrive_t drives[MAX_FD]; int reset_sensei; + uint32_t strict_io; + uint32_t mem_mapped; }; static uint32_t fdctrl_read (void *opaque, uint32_t reg) @@ -1849,11 +1854,10 @@ static void fdctrl_result_timer(void *opaque) } /* Init functions */ -static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, - target_phys_addr_t io_base, - BlockDriverState **fds) +static void fdctrl_init_common (fdctrl_t *fdctrl, int dma_chann, + target_phys_addr_t io_base, + BlockDriverState **fds) { - fdctrl_t *fdctrl; int i, j; /* Fill 'command_to_handler' lookup table */ @@ -1865,13 +1869,11 @@ static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, } FLOPPY_DPRINTF("init controller\n"); - fdctrl = qemu_mallocz(sizeof(fdctrl_t)); fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN); fdctrl->result_timer = qemu_new_timer(vm_clock, fdctrl_result_timer, fdctrl); fdctrl->version = 0x90; /* Intel 82078 controller */ - fdctrl->irq = irq; fdctrl->dma_chann = dma_chann; fdctrl->io_base = io_base; fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */ @@ -1887,24 +1889,26 @@ static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, for (i = 0; i < MAX_FD; i++) { fd_revalidate(&fdctrl->drives[i]); } - - return fdctrl; } fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, target_phys_addr_t io_base, BlockDriverState **fds) { + DeviceState *dev; + SysBusDevice *s; fdctrl_t *fdctrl; - int io_mem; - - fdctrl = fdctrl_init_common(irq, dma_chann, io_base, fds); - fdctrl->sun4m = 0; + dev = qdev_create(NULL, "fdc"); + qdev_prop_set_uint32(dev, "strict_io", 0); + qdev_prop_set_uint32(dev, "mem_mapped", mem_mapped); + qdev_prop_set_uint32(dev, "sun4m", 0); + qdev_init(dev); + s = sysbus_from_qdev(dev); + sysbus_connect_irq(s, 0, irq); + fdctrl = FROM_SYSBUS(fdctrl_t, s); if (mem_mapped) { - io_mem = cpu_register_io_memory(fdctrl_mem_read, fdctrl_mem_write, - fdctrl); - cpu_register_physical_memory(io_base, 0x08, io_mem); + sysbus_mmio_map(s, 0, io_base); } else { register_ioport_read((uint32_t)io_base + 0x01, 5, 1, &fdctrl_read_port, fdctrl); @@ -1916,22 +1920,83 @@ fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, &fdctrl_write_port, fdctrl); } + fdctrl_init_common(fdctrl, dma_chann, io_base, fds); + return fdctrl; } fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base, BlockDriverState **fds, qemu_irq *fdc_tc) { + DeviceState *dev; + SysBusDevice *s; fdctrl_t *fdctrl; - int io_mem; - fdctrl = fdctrl_init_common(irq, -1, io_base, fds); - fdctrl->sun4m = 1; - io_mem = cpu_register_io_memory(fdctrl_mem_read_strict, - fdctrl_mem_write_strict, - fdctrl); - cpu_register_physical_memory(io_base, 0x08, io_mem); - *fdc_tc = *qemu_allocate_irqs(fdctrl_handle_tc, fdctrl, 1); + dev = qdev_create(NULL, "fdc"); + qdev_prop_set_uint32(dev, "strict_io", 1); + qdev_prop_set_uint32(dev, "mem_mapped", 1); + qdev_prop_set_uint32(dev, "sun4m", 1); + qdev_init(dev); + s = sysbus_from_qdev(dev); + sysbus_connect_irq(s, 0, irq); + sysbus_mmio_map(s, 0, io_base); + *fdc_tc = qdev_get_gpio_in(dev, 0); + + fdctrl = FROM_SYSBUS(fdctrl_t, s); + fdctrl_init_common(fdctrl, -1, io_base, fds); return fdctrl; } + +static void fdc_init1(SysBusDevice *dev) +{ + fdctrl_t *s = FROM_SYSBUS(fdctrl_t, dev); + int io; + + sysbus_init_irq(dev, &s->irq); + qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1); + if (s->strict_io) { + io = cpu_register_io_memory(fdctrl_mem_read_strict, + fdctrl_mem_write_strict, s); + } else { + io = cpu_register_io_memory(fdctrl_mem_read, fdctrl_mem_write, s); + } + sysbus_init_mmio(dev, 0x08, io); +} + + +static SysBusDeviceInfo fdc_info = { + .init = fdc_init1, + .qdev.name = "fdc", + .qdev.size = sizeof(fdctrl_t), + .qdev.props = (Property[]) { + { + .name = "io_base", + .info = &qdev_prop_uint32, + .offset = offsetof(fdctrl_t, io_base), + }, + { + .name = "strict_io", + .info = &qdev_prop_uint32, + .offset = offsetof(fdctrl_t, strict_io), + }, + { + .name = "mem_mapped", + .info = &qdev_prop_uint32, + .offset = offsetof(fdctrl_t, mem_mapped), + }, + { + .name = "sun4m", + .info = &qdev_prop_uint32, + .offset = offsetof(fdctrl_t, sun4m), + }, + {/* end of properties */} + } +}; + +static void fdc_register_devices(void) +{ + sysbus_register_withprop(&fdc_info); +} + +device_init(fdc_register_devices); diff --git a/qemu/hw/fw_cfg.c b/qemu/hw/fw_cfg.c index ce57de7d..d75cce46 100644 --- a/qemu/hw/fw_cfg.c +++ b/qemu/hw/fw_cfg.c @@ -279,6 +279,7 @@ void *fw_cfg_init(uint32_t ctl_port, uint32_t data_port, fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16); fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC)); fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); + fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu); register_savevm("fw_cfg", -1, 1, fw_cfg_save, fw_cfg_load, s); qemu_register_reset(fw_cfg_reset, s); diff --git a/qemu/hw/fw_cfg.h b/qemu/hw/fw_cfg.h index f616ed2f..9fee1810 100644 --- a/qemu/hw/fw_cfg.h +++ b/qemu/hw/fw_cfg.h @@ -15,6 +15,7 @@ #define FW_CFG_INITRD_SIZE 0x0b #define FW_CFG_BOOT_DEVICE 0x0c #define FW_CFG_NUMA 0x0d +#define FW_CFG_BOOT_MENU 0x0e #define FW_CFG_MAX_ENTRY 0x10 #define FW_CFG_WRITE_CHANNEL 0x4000 diff --git a/qemu/hw/hpet.c b/qemu/hw/hpet.c index 186d6715..24aee6a2 100644 --- a/qemu/hw/hpet.c +++ b/qemu/hw/hpet.c @@ -17,8 +17,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 . * * ***************************************************************** * @@ -554,6 +553,7 @@ static void hpet_reset(void *opaque) { /* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */ s->capability = 0x8086a201ULL; s->capability |= ((HPET_CLK_PERIOD) << 32); + s->config = 0ULL; if (count > 0) /* we don't enable pit when hpet_reset is first called (by hpet_init) * because hpet is taking over for pit here. On subsequent invocations, diff --git a/qemu/hw/hw.h b/qemu/hw/hw.h index a424d28f..1e5783d9 100644 --- a/qemu/hw/hw.h +++ b/qemu/hw/hw.h @@ -261,10 +261,12 @@ void unregister_savevm(const char *idstr, void *opaque); typedef void QEMUResetHandler(void *opaque); void qemu_register_reset(QEMUResetHandler *func, void *opaque); +void qemu_unregister_reset(QEMUResetHandler *func, void *opaque); -/* handler to set the boot_device for a specific type of QEMUMachine */ +/* handler to set the boot_device order for a specific type of QEMUMachine */ /* return 0 if success */ -typedef int QEMUBootSetHandler(void *opaque, const char *boot_device); +typedef int QEMUBootSetHandler(void *opaque, const char *boot_devices); void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque); +int qemu_boot_set(const char *boot_devices); #endif diff --git a/qemu/hw/i2c.c b/qemu/hw/i2c.c index 98aa7fcd..42a5d7a6 100644 --- a/qemu/hw/i2c.c +++ b/qemu/hw/i2c.c @@ -20,6 +20,14 @@ struct i2c_bus static struct BusInfo i2c_bus_info = { .name = "I2C", .size = sizeof(i2c_bus), + .props = (Property[]) { + { + .name = "address", + .info = &qdev_prop_uint32, + .offset = offsetof(struct i2c_slave, address), + }, + {/* end of list */} + } }; static void i2c_bus_save(QEMUFile *f, void *opaque) @@ -151,7 +159,6 @@ static void i2c_slave_qdev_init(DeviceState *dev, DeviceInfo *base) i2c_slave *s = I2C_SLAVE_FROM_QDEV(dev); s->info = info; - s->address = qdev_get_prop_int(dev, "address", 0); info->init(s); } @@ -169,7 +176,7 @@ DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, int addr) DeviceState *dev; dev = qdev_create(&bus->qbus, name); - qdev_set_prop_int(dev, "address", addr); + qdev_prop_set_uint32(dev, "address", addr); qdev_init(dev); return dev; } diff --git a/qemu/hw/i2c.h b/qemu/hw/i2c.h index c4df3998..479ff4b9 100644 --- a/qemu/hw/i2c.h +++ b/qemu/hw/i2c.h @@ -40,7 +40,7 @@ struct i2c_slave I2CSlaveInfo *info; /* Remaining fields for internal use by the I2C code. */ - int address; + uint32_t address; }; i2c_bus *i2c_init_bus(DeviceState *parent, const char *name); diff --git a/qemu/hw/integratorcp.c b/qemu/hw/integratorcp.c index 50eae0c3..ddc8d855 100644 --- a/qemu/hw/integratorcp.c +++ b/qemu/hw/integratorcp.c @@ -17,6 +17,7 @@ typedef struct { SysBusDevice busdev; + uint32_t memsz; uint32_t flash_offset; uint32_t cm_osc; uint32_t cm_ctrl; @@ -230,23 +231,21 @@ static void integratorcm_init(SysBusDevice *dev) { int iomemtype; integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev); - int memsz; - memsz = qdev_get_prop_int(&dev->qdev, "memsz", 0); s->cm_osc = 0x01000048; /* ??? What should the high bits of this value be? */ s->cm_auxosc = 0x0007feff; s->cm_sdram = 0x00011122; - if (memsz >= 256) { + if (s->memsz >= 256) { integrator_spd[31] = 64; s->cm_sdram |= 0x10; - } else if (memsz >= 128) { + } else if (s->memsz >= 128) { integrator_spd[31] = 32; s->cm_sdram |= 0x0c; - } else if (memsz >= 64) { + } else if (s->memsz >= 64) { integrator_spd[31] = 16; s->cm_sdram |= 0x08; - } else if (memsz >= 32) { + } else if (s->memsz >= 32) { integrator_spd[31] = 4; s->cm_sdram |= 0x04; } else { @@ -475,7 +474,7 @@ static void integratorcp_init(ram_addr_t ram_size, cpu_register_physical_memory(0x80000000, ram_size, ram_offset | IO_MEM_RAM); dev = qdev_create(NULL, "integrator_core"); - qdev_set_prop_int(dev, "memsz", ram_size >> 20); + qdev_prop_set_uint32(dev, "memsz", ram_size >> 20); qdev_init(dev); sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000); @@ -522,11 +521,24 @@ static void integratorcp_machine_init(void) machine_init(integratorcp_machine_init); +static SysBusDeviceInfo core_info = { + .init = integratorcm_init, + .qdev.name = "integrator_core", + .qdev.size = sizeof(integratorcm_state), + .qdev.props = (Property[]) { + { + .name = "memsz", + .info = &qdev_prop_uint32, + .offset = offsetof(integratorcm_state, memsz), + }, + {/* end of list */} + } +}; + static void integratorcp_register_devices(void) { sysbus_register_dev("integrator_pic", sizeof(icp_pic_state), icp_pic_init); - sysbus_register_dev("integrator_core", sizeof(integratorcm_state), - integratorcm_init); + sysbus_register_withprop(&core_info); } device_init(integratorcp_register_devices) diff --git a/qemu/hw/iommu.c b/qemu/hw/iommu.c index 0af6d32a..b172f152 100644 --- a/qemu/hw/iommu.c +++ b/qemu/hw/iommu.c @@ -21,8 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" + #include "sun4m.h" +#include "sysbus.h" /* debug iommu */ //#define DEBUG_IOMMU @@ -127,6 +128,7 @@ #define IOMMU_PAGE_MASK ~(IOMMU_PAGE_SIZE - 1) typedef struct IOMMUState { + SysBusDevice busdev; uint32_t regs[IOMMU_NREGS]; target_phys_addr_t iostart; uint32_t version; @@ -366,20 +368,54 @@ static void iommu_reset(void *opaque) void *iommu_init(target_phys_addr_t addr, uint32_t version, qemu_irq irq) { - IOMMUState *s; - int iommu_io_memory; + DeviceState *dev; + SysBusDevice *s; + IOMMUState *d; + + dev = qdev_create(NULL, "iommu"); + qdev_prop_set_uint32(dev, "version", version); + qdev_init(dev); + s = sysbus_from_qdev(dev); + sysbus_connect_irq(s, 0, irq); + sysbus_mmio_map(s, 0, addr); - s = qemu_mallocz(sizeof(IOMMUState)); + d = FROM_SYSBUS(IOMMUState, s); - s->version = version; - s->irq = irq; + return d; +} - iommu_io_memory = cpu_register_io_memory(iommu_mem_read, - iommu_mem_write, s); - cpu_register_physical_memory(addr, IOMMU_NREGS * 4, iommu_io_memory); +static void iommu_init1(SysBusDevice *dev) +{ + IOMMUState *s = FROM_SYSBUS(IOMMUState, dev); + int io; - register_savevm("iommu", addr, 2, iommu_save, iommu_load, s); + sysbus_init_irq(dev, &s->irq); + + io = cpu_register_io_memory(iommu_mem_read, iommu_mem_write, s); + sysbus_init_mmio(dev, IOMMU_NREGS * sizeof(uint32_t), io); + + register_savevm("iommu", -1, 2, iommu_save, iommu_load, s); qemu_register_reset(iommu_reset, s); iommu_reset(s); - return s; } + +static SysBusDeviceInfo iommu_info = { + .init = iommu_init1, + .qdev.name = "iommu", + .qdev.size = sizeof(IOMMUState), + .qdev.props = (Property[]) { + { + .name = "version", + .info = &qdev_prop_uint32, + .offset = offsetof(IOMMUState, version), + }, + {/* end of property list */} + } +}; + +static void iommu_register_devices(void) +{ + sysbus_register_withprop(&iommu_info); +} + +device_init(iommu_register_devices); diff --git a/qemu/hw/m48t59.c b/qemu/hw/m48t59.c index f5de4c10..d2c65f8f 100644 --- a/qemu/hw/m48t59.c +++ b/qemu/hw/m48t59.c @@ -23,9 +23,9 @@ */ #include "hw.h" #include "nvram.h" -#include "isa.h" #include "qemu-timer.h" #include "sysemu.h" +#include "sysbus.h" //#define DEBUG_NVRAM @@ -41,13 +41,13 @@ * PPC platform there is also a nvram lock function. */ struct m48t59_t { + SysBusDevice busdev; /* Model parameters */ - int type; // 2 = m48t02, 8 = m48t08, 59 = m48t59 + uint32_t type; // 2 = m48t02, 8 = m48t08, 59 = m48t59 /* Hardware parameters */ qemu_irq IRQ; - int mem_index; uint32_t io_base; - uint16_t size; + uint32_t size; /* RTC management */ time_t time_offset; time_t stop_time; @@ -618,32 +618,78 @@ m48t59_t *m48t59_init (qemu_irq IRQ, target_phys_addr_t mem_base, uint32_t io_base, uint16_t size, int type) { - m48t59_t *s; - target_phys_addr_t save_base; - - s = qemu_mallocz(sizeof(m48t59_t)); - s->buffer = qemu_mallocz(size); - s->IRQ = IRQ; - s->size = size; - s->io_base = io_base; - s->type = type; + DeviceState *dev; + SysBusDevice *s; + m48t59_t *d; + + dev = qdev_create(NULL, "m48t59"); + qdev_prop_set_uint32(dev, "type", type); + qdev_prop_set_uint32(dev, "size", size); + qdev_prop_set_uint32(dev, "io_base", io_base); + qdev_init(dev); + s = sysbus_from_qdev(dev); + sysbus_connect_irq(s, 0, IRQ); if (io_base != 0) { register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s); register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s); } if (mem_base != 0) { - s->mem_index = cpu_register_io_memory(nvram_read, nvram_write, s); - cpu_register_physical_memory(mem_base, size, s->mem_index); + sysbus_mmio_map(s, 0, mem_base); } - if (type == 59) { + + d = FROM_SYSBUS(m48t59_t, s); + + return d; +} + +static void m48t59_init1(SysBusDevice *dev) +{ + m48t59_t *s = FROM_SYSBUS(m48t59_t, dev); + int mem_index; + + s->buffer = qemu_mallocz(s->size); + sysbus_init_irq(dev, &s->IRQ); + + mem_index = cpu_register_io_memory(nvram_read, nvram_write, s); + sysbus_init_mmio(dev, s->size, mem_index); + + if (s->type == 59) { s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s); s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s); } qemu_get_timedate(&s->alarm, 0); qemu_register_reset(m48t59_reset, s); - save_base = mem_base ? mem_base : io_base; - register_savevm("m48t59", save_base, 1, m48t59_save, m48t59_load, s); + register_savevm("m48t59", -1, 1, m48t59_save, m48t59_load, s); +} + +static SysBusDeviceInfo m48t59_info = { + .init = m48t59_init1, + .qdev.name = "m48t59", + .qdev.size = sizeof(m48t59_t), + .qdev.props = (Property[]) { + { + .name = "size", + .info = &qdev_prop_uint32, + .offset = offsetof(m48t59_t, size), + .defval = (uint32_t[]) { -1 }, + },{ + .name = "type", + .info = &qdev_prop_uint32, + .offset = offsetof(m48t59_t, type), + .defval = (uint32_t[]) { -1 }, + },{ + .name = "io_base", + .info = &qdev_prop_hex32, + .offset = offsetof(m48t59_t, io_base), + }, + {/* end of list */} + } +}; - return s; +static void m48t59_register_devices(void) +{ + sysbus_register_withprop(&m48t59_info); } + +device_init(m48t59_register_devices); diff --git a/qemu/hw/mips_malta.c b/qemu/hw/mips_malta.c index 853ec2b8..7728e58c 100644 --- a/qemu/hw/mips_malta.c +++ b/qemu/hw/mips_malta.c @@ -914,8 +914,8 @@ void mips_malta_init (ram_addr_t ram_size, /* TODO: Populate SPD eeprom data. */ DeviceState *eeprom; eeprom = qdev_create((BusState *)smbus, "smbus-eeprom"); - qdev_set_prop_int(eeprom, "address", 0x50 + i); - qdev_set_prop_ptr(eeprom, "data", eeprom_buf + (i * 256)); + qdev_prop_set_uint32(eeprom, "address", 0x50 + i); + qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256)); qdev_init(eeprom); } pit = pit_init(0x40, i8259[0]); diff --git a/qemu/hw/msix.c b/qemu/hw/msix.c index e1308572..3420ce9b 100644 --- a/qemu/hw/msix.c +++ b/qemu/hw/msix.c @@ -286,8 +286,9 @@ void msix_save(PCIDevice *dev, QEMUFile *f) { unsigned n = dev->msix_entries_nr; - if (!dev->cap_present & QEMU_PCI_CAP_MSIX) + if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) { return; + } qemu_put_buffer(f, dev->msix_table_page, n * MSIX_ENTRY_SIZE); qemu_put_buffer(f, dev->msix_table_page + MSIX_PAGE_PENDING, (n + 7) / 8); @@ -302,6 +303,7 @@ void msix_load(PCIDevice *dev, QEMUFile *f) return; } + msix_free_irq_entries(dev); qemu_get_buffer(f, dev->msix_table_page, n * MSIX_ENTRY_SIZE); qemu_get_buffer(f, dev->msix_table_page + MSIX_PAGE_PENDING, (n + 7) / 8); } diff --git a/qemu/hw/musicpal.c b/qemu/hw/musicpal.c index 10be69be..e6367919 100644 --- a/qemu/hw/musicpal.c +++ b/qemu/hw/musicpal.c @@ -1578,7 +1578,7 @@ static void musicpal_init(ram_addr_t ram_size, qemu_check_nic_model(&nd_table[0], "mv88w8618"); dev = qdev_create(NULL, "mv88w8618_eth"); - qdev_set_netdev(dev, &nd_table[0]); + dev->nd = &nd_table[0]; qdev_init(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, MP_ETH_BASE); sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[MP_ETH_IRQ]); diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c index 553ba5c8..8a1582c2 100644 --- a/qemu/hw/pc.c +++ b/qemu/hw/pc.c @@ -825,6 +825,7 @@ static void load_linux(void *fw_cfg, uint8_t header[8192]; target_phys_addr_t real_addr, prot_addr, cmdline_addr, initrd_addr = 0; FILE *f, *fi; + char *vmode; /* Align to 16 bytes as a paranoia measure */ cmdline_size = (strlen(kernel_cmdline)+16) & ~15; @@ -900,6 +901,24 @@ static void load_linux(void *fw_cfg, 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 @@ -1081,12 +1100,20 @@ static CPUState *pc_new_cpu(const char *cpu_model) return env; } +enum { + COMPAT_DEFAULT = 0, + COMPAT_0_10, /* compatible with qemu 0.10.x */ +}; + /* PC hardware initialisation */ static void pc_init1(ram_addr_t ram_size, const char *boot_device, - const char *kernel_filename, const char *kernel_cmdline, + const char *kernel_filename, + const char *kernel_cmdline, const char *initrd_filename, - int pci_enabled, const char *cpu_model) + const char *cpu_model, + int pci_enabled, + int compat_level) { char *filename; int ret, linux_boot, i; @@ -1104,6 +1131,7 @@ static void pc_init1(ram_addr_t ram_size, BlockDriverState *fd[MAX_FD]; int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled; void *fw_cfg; + const char *virtio_blk_name, *virtio_console_name; if (ram_size >= 0xe0000000 ) { above_4g_mem_size = ram_size - 0xe0000000; @@ -1374,8 +1402,8 @@ static void pc_init1(ram_addr_t ram_size, for (i = 0; i < 8; i++) { DeviceState *eeprom; eeprom = qdev_create((BusState *)smbus, "smbus-eeprom"); - qdev_set_prop_int(eeprom, "address", 0x50 + i); - qdev_set_prop_ptr(eeprom, "data", eeprom_buf + (i * 256)); + qdev_prop_set_uint32(eeprom, "address", 0x50 + i); + qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256)); qdev_init(eeprom); } } @@ -1394,13 +1422,26 @@ static void pc_init1(ram_addr_t ram_size, } } + switch (compat_level) { + case COMPAT_DEFAULT: + default: + virtio_blk_name = "virtio-blk-pci"; + virtio_console_name = "virtio-console-pci"; + break; + + case COMPAT_0_10: + virtio_blk_name = "virtio-blk-pci-0-10"; + virtio_console_name = "virtio-console-pci-0-10"; + break; + } + /* Add virtio block devices */ if (pci_enabled) { int index; int unit_id = 0; while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) { - pci_dev = pci_create("virtio-blk-pci", + pci_dev = pci_create(virtio_blk_name, drives_table[index].devaddr); qdev_init(&pci_dev->qdev); unit_id++; @@ -1417,7 +1458,7 @@ static void pc_init1(ram_addr_t ram_size, if (pci_enabled) { for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { if (virtcon_hds[i]) { - pci_create_simple(pci_bus, -1, "virtio-console-pci"); + pci_create_simple(pci_bus, -1, virtio_console_name); } } } @@ -1432,7 +1473,8 @@ static void pc_init_pci(ram_addr_t ram_size, { pc_init1(ram_size, boot_device, kernel_filename, kernel_cmdline, - initrd_filename, 1, cpu_model); + initrd_filename, cpu_model, + 1, COMPAT_DEFAULT); } static void pc_init_isa(ram_addr_t ram_size, @@ -1444,7 +1486,21 @@ static void pc_init_isa(ram_addr_t ram_size, { pc_init1(ram_size, boot_device, kernel_filename, kernel_cmdline, - initrd_filename, 0, cpu_model); + initrd_filename, cpu_model, + 0, COMPAT_DEFAULT); +} + +static void pc_init_pci_0_10(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + const char *cpu_model) +{ + pc_init1(ram_size, boot_device, + kernel_filename, kernel_cmdline, + initrd_filename, cpu_model, + 1, COMPAT_0_10); } /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE) @@ -1463,6 +1519,25 @@ static QEMUMachine pc_machine = { .is_default = 1, }; +static QEMUMachine pc_machine_v0_10 = { + .name = "pc-0.10", + .desc = "Standard PC, qemu 0.10", + .init = pc_init_pci, + .max_cpus = 255, + .compat_props = (CompatProperty[]) { + { + .driver = "virtio-blk-pci", + .property = "class", + .value = stringify(PCI_CLASS_STORAGE_OTHER), + },{ + .driver = "virtio-console-pci", + .property = "class", + .value = stringify(PCI_CLASS_DISPLAY_OTHER), + }, + { /* end of list */ } + }, +}; + static QEMUMachine isapc_machine = { .name = "isapc", .desc = "ISA-only PC", @@ -1470,10 +1545,21 @@ static QEMUMachine isapc_machine = { .max_cpus = 1, }; +static QEMUMachine pc_0_10_machine = { + .name = "pc-0-10", + .desc = "Standard PC compatible with qemu 0.10.x", + .init = pc_init_pci_0_10, + .max_cpus = 255, +}; + static void pc_machine_init(void) { qemu_register_machine(&pc_machine); + qemu_register_machine(&pc_machine_v0_10); qemu_register_machine(&isapc_machine); + + /* For compatibility with 0.10.x */ + qemu_register_machine(&pc_0_10_machine); } machine_init(pc_machine_init); diff --git a/qemu/hw/pci.c b/qemu/hw/pci.c index 71d9227a..3b5a9477 100644 --- a/qemu/hw/pci.c +++ b/qemu/hw/pci.c @@ -28,6 +28,11 @@ #include "sysemu.h" //#define DEBUG_PCI +#ifdef DEBUG_PCI +# define PCI_DPRINTF(format, ...) printf(format, __VA_ARGS__) +#else +# define PCI_DPRINTF(format, ...) do { } while (0) +#endif struct PCIBus { BusState qbus; @@ -54,6 +59,15 @@ static struct BusInfo pci_bus_info = { .name = "PCI", .size = sizeof(PCIBus), .print_dev = pcibus_dev_print, + .props = (Property[]) { + { + .name = "devfn", + .info = &qdev_prop_uint32, + .offset = offsetof(PCIDevice, devfn), + .defval = (uint32_t[]) { -1 }, + }, + {/* end of list */} + } }; static void pci_update_mappings(PCIDevice *d); @@ -123,7 +137,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name, bus->irq_opaque = pic; bus->devfn_min = devfn_min; bus->nirq = nirq; - bus->irq_count = qemu_malloc(nirq * sizeof(bus->irq_count[0])); + bus->irq_count = qemu_mallocz(nirq * sizeof(bus->irq_count[0])); bus->next = first_bus; first_bus = bus; register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus); @@ -135,7 +149,7 @@ static PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq { PCIBus *bus; - bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, NULL)); + bus = qemu_mallocz(sizeof(PCIBus)); bus->map_irq = map_irq; bus->parent_dev = dev; bus->next = dev->bus->next; @@ -548,9 +562,9 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len) PCIDevice *pci_dev; int config_addr, bus_num; -#if defined(DEBUG_PCI) && 0 - printf("pci_data_write: addr=%08x val=%08x len=%d\n", - addr, val, len); +#if 0 + PCI_DPRINTF("pci_data_write: addr=%08x val=%08x len=%d\n", + addr, val, len); #endif bus_num = (addr >> 16) & 0xff; while (s && s->bus_num != bus_num) @@ -561,10 +575,8 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len) if (!pci_dev) return; config_addr = addr & 0xff; -#if defined(DEBUG_PCI) - printf("pci_config_write: %s: addr=%02x val=%08x len=%d\n", - pci_dev->name, config_addr, val, len); -#endif + PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n", + pci_dev->name, config_addr, val, len); pci_dev->config_write(pci_dev, config_addr, val, len); } @@ -599,14 +611,12 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len) } config_addr = addr & 0xff; val = pci_dev->config_read(pci_dev, config_addr, len); -#if defined(DEBUG_PCI) - printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n", - pci_dev->name, config_addr, val, len); -#endif + PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x len=%d\n", + pci_dev->name, config_addr, val, len); the_end: -#if defined(DEBUG_PCI) && 0 - printf("pci_data_read: addr=%08x val=%08x len=%d\n", - addr, val, len); +#if 0 + PCI_DPRINTF("pci_data_read: addr=%08x val=%08x len=%d\n", + addr, val, len); #endif return val; } @@ -728,6 +738,7 @@ static void pci_info_device(PCIDevice *d) } } } + monitor_printf(mon, " id \"%s\"\n", d->qdev.id ? d->qdev.id : ""); if (class == 0x0604 && d->config[0x19] != 0) { pci_for_each_device(d->config[0x19], pci_info_device); } @@ -769,7 +780,7 @@ PCIDevice *pci_create(const char *name, const char *devaddr) } dev = qdev_create(&bus->qbus, name); - qdev_set_prop_int(dev, "devfn", devfn); + qdev_prop_set_uint32(dev, "devfn", devfn); return (PCIDevice *)dev; } @@ -812,7 +823,9 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, if (strcmp(nd->model, pci_nic_models[i]) == 0) { pci_dev = pci_create(pci_nic_names[i], devaddr); dev = &pci_dev->qdev; - qdev_set_netdev(dev, nd); + if (nd->id) + dev->id = qemu_strdup(nd->id); + dev->nd = nd; qdev_init(dev); nd->private = dev; return pci_dev; @@ -890,7 +903,7 @@ static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base) int devfn; bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev)); - devfn = qdev_get_prop_int(qdev, "devfn", -1); + devfn = pci_dev->devfn; pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn, info->config_read, info->config_write); assert(pci_dev); @@ -917,7 +930,7 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) DeviceState *dev; dev = qdev_create(&bus->qbus, name); - qdev_set_prop_int(dev, "devfn", devfn); + qdev_prop_set_uint32(dev, "devfn", devfn); qdev_init(dev); return (PCIDevice *)dev; diff --git a/qemu/hw/pci_ids.h b/qemu/hw/pci_ids.h index 3afe6748..2fe60eeb 100644 --- a/qemu/hw/pci_ids.h +++ b/qemu/hw/pci_ids.h @@ -35,6 +35,9 @@ #define PCI_CLASS_BRIDGE_PCI 0x0604 #define PCI_CLASS_BRIDGE_OTHER 0x0680 +#define PCI_CLASS_SERIAL_OTHER 0x0780 + +#define PCI_CLASS_PROCESSOR_CO 0x0b40 #define PCI_CLASS_COMMUNICATION_OTHER 0x0780 #define PCI_CLASS_PROCESSOR_CO 0x0b40 diff --git a/qemu/hw/pcnet.c b/qemu/hw/pcnet.c index e3365f59..b313b432 100644 --- a/qemu/hw/pcnet.c +++ b/qemu/hw/pcnet.c @@ -2128,8 +2128,6 @@ static void lance_init(SysBusDevice *dev) s->mmio_index = cpu_register_io_memory(lance_mem_read, lance_mem_write, d); - s->dma_opaque = qdev_get_prop_ptr(&dev->qdev, "dma"); - qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1); sysbus_init_mmio(dev, 4, s->mmio_index); @@ -2141,6 +2139,21 @@ static void lance_init(SysBusDevice *dev) pcnet_common_init(&dev->qdev, s, lance_cleanup); } + +static SysBusDeviceInfo lance_info = { + .init = lance_init, + .qdev.name = "lance", + .qdev.size = sizeof(SysBusPCNetState), + .qdev.props = (Property[]) { + { + .name = "dma", + .info = &qdev_prop_ptr, + .offset = offsetof(SysBusPCNetState, state.dma_opaque), + }, + {/* end of list */} + } +}; + #endif /* TARGET_SPARC */ static PCIDeviceInfo pcnet_info = { @@ -2153,7 +2166,7 @@ static void pcnet_register_devices(void) { pci_qdev_register(&pcnet_info); #if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) - sysbus_register_dev("lance", sizeof(SysBusPCNetState), lance_init); + sysbus_register_withprop(&lance_info); #endif } diff --git a/qemu/hw/ppc.c b/qemu/hw/ppc.c index e9f1724c..c23a02d2 100644 --- a/qemu/hw/ppc.c +++ b/qemu/hw/ppc.c @@ -551,13 +551,13 @@ static void cpu_ppc_tb_start (CPUState *env) } static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env, - uint64_t *next) + uint64_t next) { ppc_tb_t *tb_env = env->tb_env; uint32_t decr; int64_t diff; - diff = tb_env->decr_next - qemu_get_clock(vm_clock); + diff = next - qemu_get_clock(vm_clock); if (diff >= 0) decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec); else @@ -571,14 +571,14 @@ uint32_t cpu_ppc_load_decr (CPUState *env) { ppc_tb_t *tb_env = env->tb_env; - return _cpu_ppc_load_decr(env, &tb_env->decr_next); + return _cpu_ppc_load_decr(env, tb_env->decr_next); } uint32_t cpu_ppc_load_hdecr (CPUState *env) { ppc_tb_t *tb_env = env->tb_env; - return _cpu_ppc_load_decr(env, &tb_env->hdecr_next); + return _cpu_ppc_load_decr(env, tb_env->hdecr_next); } uint64_t cpu_ppc_load_purr (CPUState *env) diff --git a/qemu/hw/ps2.c b/qemu/hw/ps2.c index fb770052..0915b9fa 100644 --- a/qemu/hw/ps2.c +++ b/qemu/hw/ps2.c @@ -488,9 +488,8 @@ void ps2_write_mouse(void *opaque, int val) } } -static void ps2_reset(void *opaque) +static void ps2_common_reset(PS2State *s) { - PS2State *s = (PS2State *)opaque; PS2Queue *q; s->write_cmd = -1; q = &s->queue; @@ -500,6 +499,33 @@ static void ps2_reset(void *opaque) 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 void ps2_common_save (QEMUFile *f, PS2State *s) { qemu_put_be32 (f, s->write_cmd); @@ -590,10 +616,10 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) s->common.update_irq = update_irq; s->common.update_arg = update_arg; s->scancode_set = 2; - ps2_reset(&s->common); + ps2_kbd_reset(s); register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s); qemu_add_kbd_event_handler(ps2_put_keycode, s); - qemu_register_reset(ps2_reset, &s->common); + qemu_register_reset(ps2_kbd_reset, s); return s; } @@ -603,9 +629,9 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) s->common.update_irq = update_irq; s->common.update_arg = update_arg; - ps2_reset(&s->common); + ps2_mouse_reset(s); register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s); qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse"); - qemu_register_reset(ps2_reset, &s->common); + qemu_register_reset(ps2_mouse_reset, s); return s; } diff --git a/qemu/hw/qdev-addr.c b/qemu/hw/qdev-addr.c new file mode 100644 index 00000000..305c2d37 --- /dev/null +++ b/qemu/hw/qdev-addr.c @@ -0,0 +1,32 @@ +#include "qdev.h" +#include "qdev-addr.h" +#include "targphys.h" + +/* --- target physical address --- */ + +static int parse_taddr(DeviceState *dev, Property *prop, const char *str) +{ + target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop); + + *ptr = strtoull(str, NULL, 16); + return 0; +} + +static int print_taddr(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + target_phys_addr_t *ptr = qdev_get_prop_ptr(dev, prop); + return snprintf(dest, len, "0x" TARGET_FMT_plx, *ptr); +} + +PropertyInfo qdev_prop_taddr = { + .name = "taddr", + .type = PROP_TYPE_TADDR, + .size = sizeof(target_phys_addr_t), + .parse = parse_taddr, + .print = print_taddr, +}; + +void qdev_prop_set_taddr(DeviceState *dev, const char *name, target_phys_addr_t value) +{ + qdev_prop_set(dev, name, &value, PROP_TYPE_TADDR); +} diff --git a/qemu/hw/qdev-addr.h b/qemu/hw/qdev-addr.h new file mode 100644 index 00000000..f02bd7af --- /dev/null +++ b/qemu/hw/qdev-addr.h @@ -0,0 +1,2 @@ +extern PropertyInfo qdev_prop_taddr; +void qdev_prop_set_taddr(DeviceState *dev, const char *name, target_phys_addr_t value); diff --git a/qemu/hw/qdev-properties.c b/qemu/hw/qdev-properties.c new file mode 100644 index 00000000..c7a167b6 --- /dev/null +++ b/qemu/hw/qdev-properties.c @@ -0,0 +1,269 @@ +#include "qdev.h" + +void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) +{ + void *ptr = dev; + (char*)ptr += prop->offset; + return ptr; +} + +/* --- 16bit integer --- */ + +static int parse_uint16(DeviceState *dev, Property *prop, const char *str) +{ + uint16_t *ptr = qdev_get_prop_ptr(dev, prop); + const char *fmt; + + /* accept both hex and decimal */ + fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx16 : "%" PRIu16; + if (sscanf(str, fmt, ptr) != 1) + return -1; + return 0; +} + +static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + uint16_t *ptr = qdev_get_prop_ptr(dev, prop); + return snprintf(dest, len, "%" PRIu16, *ptr); +} + +PropertyInfo qdev_prop_uint16 = { + .name = "uint16", + .type = PROP_TYPE_UINT16, + .size = sizeof(uint16_t), + .parse = parse_uint16, + .print = print_uint16, +}; + +/* --- 32bit integer --- */ + +static int parse_uint32(DeviceState *dev, Property *prop, const char *str) +{ + uint32_t *ptr = qdev_get_prop_ptr(dev, prop); + const char *fmt; + + /* accept both hex and decimal */ + fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx32 : "%" PRIu32; + if (sscanf(str, fmt, ptr) != 1) + return -1; + return 0; +} + +static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + uint32_t *ptr = qdev_get_prop_ptr(dev, prop); + return snprintf(dest, len, "%" PRIu32, *ptr); +} + +PropertyInfo qdev_prop_uint32 = { + .name = "uint32", + .type = PROP_TYPE_UINT32, + .size = sizeof(uint32_t), + .parse = parse_uint32, + .print = print_uint32, +}; + +/* --- 32bit hex value --- */ + +static int parse_hex32(DeviceState *dev, Property *prop, const char *str) +{ + uint32_t *ptr = qdev_get_prop_ptr(dev, prop); + + if (sscanf(str, "%" PRIx32, ptr) != 1) + return -1; + return 0; +} + +static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + uint32_t *ptr = qdev_get_prop_ptr(dev, prop); + return snprintf(dest, len, "0x%" PRIx32, *ptr); +} + +PropertyInfo qdev_prop_hex32 = { + .name = "hex32", + .type = PROP_TYPE_UINT32, + .size = sizeof(uint32_t), + .parse = parse_hex32, + .print = print_hex32, +}; + +/* --- pointer --- */ + +static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + void **ptr = qdev_get_prop_ptr(dev, prop); + return snprintf(dest, len, "<%p>", *ptr); +} + +PropertyInfo qdev_prop_ptr = { + .name = "ptr", + .type = PROP_TYPE_PTR, + .size = sizeof(void*), + .print = print_ptr, +}; + +/* --- mac address --- */ + +/* + * accepted syntax versions: + * 01:02:03:04:05:06 + * 01-02-03-04-05-06 + */ +static int parse_mac(DeviceState *dev, Property *prop, const char *str) +{ + uint8_t *mac = qdev_get_prop_ptr(dev, prop); + int i, pos; + char *p; + + for (i = 0, pos = 0; i < 6; i++, pos += 3) { + if (!isxdigit(str[pos])) + return -1; + if (!isxdigit(str[pos+1])) + return -1; + if (i == 5 && str[pos+2] != '\0') + return -1; + if (str[pos+2] != ':' && str[pos+2] != '-') + return -1; + mac[i] = strtol(str+pos, &p, 16); + } + return 0; +} + +static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + uint8_t *mac = qdev_get_prop_ptr(dev, prop); + return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} + +PropertyInfo qdev_prop_macaddr = { + .name = "mac-addr", + .type = PROP_TYPE_MACADDR, + .size = 6, + .parse = parse_mac, + .print = print_mac, +}; + +/* --- public helpers --- */ + +static Property *qdev_prop_walk(Property *props, const char *name) +{ + if (!props) + return NULL; + while (props->name) { + if (strcmp(props->name, name) == 0) + return props; + props++; + } + return NULL; +} + +static Property *qdev_prop_find(DeviceState *dev, const char *name) +{ + Property *prop; + + /* device properties */ + prop = qdev_prop_walk(dev->info->props, name); + if (prop) + return prop; + + /* bus properties */ + prop = qdev_prop_walk(dev->parent_bus->info->props, name); + if (prop) + return prop; + + return NULL; +} + +int qdev_prop_parse(DeviceState *dev, const char *name, const char *value) +{ + Property *prop; + + prop = qdev_prop_find(dev, name); + if (!prop) { + fprintf(stderr, "property \"%s.%s\" not found\n", + dev->info->name, name); + return -1; + } + if (!prop->info->parse) { + fprintf(stderr, "property \"%s.%s\" has no parser\n", + dev->info->name, name); + return -1; + } + return prop->info->parse(dev, prop, value); +} + +void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type) +{ + Property *prop; + void *dst; + + prop = qdev_prop_find(dev, name); + if (!prop) { + fprintf(stderr, "%s: property \"%s.%s\" not found\n", + __FUNCTION__, dev->info->name, name); + abort(); + } + if (prop->info->type != type) { + fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n", + __FUNCTION__, dev->info->name, name); + abort(); + } + dst = qdev_get_prop_ptr(dev, prop); + memcpy(dst, src, prop->info->size); +} + +void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value) +{ + qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16); +} + +void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value) +{ + qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32); +} + +void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) +{ + qdev_prop_set(dev, name, &value, PROP_TYPE_PTR); +} + +void qdev_prop_set_defaults(DeviceState *dev, Property *props) +{ + char *dst; + + if (!props) + return; + while (props->name) { + if (props->defval) { + dst = qdev_get_prop_ptr(dev, props); + memcpy(dst, props->defval, props->info->size); + } + props++; + } +} + +static CompatProperty *compat_props; + +void qdev_prop_register_compat(CompatProperty *props) +{ + compat_props = props; +} + +void qdev_prop_set_compat(DeviceState *dev) +{ + CompatProperty *prop; + + if (!compat_props) { + return; + } + for (prop = compat_props; prop->driver != NULL; prop++) { + if (strcmp(dev->info->name, prop->driver) != 0) { + continue; + } + if (qdev_prop_parse(dev, prop->property, prop->value) != 0) { + abort(); + } + } +} diff --git a/qemu/hw/qdev.c b/qemu/hw/qdev.c index 83e98bf3..001c74ce 100644 --- a/qemu/hw/qdev.c +++ b/qemu/hw/qdev.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 . */ /* The theory here is that it should be possible to create a machine without @@ -31,16 +30,6 @@ #include "sysemu.h" #include "monitor.h" -struct DeviceProperty { - const char *name; - DevicePropType type; - union { - uint64_t i; - void *ptr; - } value; - DeviceProperty *next; -}; - /* This is a nasty hack to allow passing a NULL bus to qdev_create. */ static BusState *main_system_bus; extern struct BusInfo system_bus_info; @@ -57,6 +46,32 @@ void qdev_register(DeviceInfo *info) device_info_list = info; } +static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name) +{ + DeviceInfo *info; + + /* first check device names */ + for (info = device_info_list; info != NULL; info = info->next) { + if (bus_info && info->bus_info != bus_info) + continue; + if (strcmp(info->name, name) != 0) + continue; + return info; + } + + /* failing that check the aliases */ + for (info = device_info_list; info != NULL; info = info->next) { + if (bus_info && info->bus_info != bus_info) + continue; + if (!info->alias) + continue; + if (strcmp(info->alias, name) != 0) + continue; + return info; + } + return NULL; +} + /* Create a new device. This only initializes the device state structure and allows properties to be set. qdev_init should be called to initialize the actual device emulation. */ @@ -72,13 +87,7 @@ DeviceState *qdev_create(BusState *bus, const char *name) bus = main_system_bus; } - for (info = device_info_list; info != NULL; info = info->next) { - if (info->bus_info != bus->info) - continue; - if (strcmp(info->name, name) != 0) - continue; - break; - } + info = qdev_find_info(bus->info, name); if (!info) { hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name); } @@ -86,6 +95,9 @@ DeviceState *qdev_create(BusState *bus, const char *name) dev = qemu_mallocz(info->size); dev->info = info; dev->parent_bus = bus; + qdev_prop_set_defaults(dev, dev->info->props); + qdev_prop_set_defaults(dev, dev->parent_bus->info->props); + qdev_prop_set_compat(dev); LIST_INSERT_HEAD(&bus->children, dev, sibling); return dev; } @@ -102,55 +114,10 @@ void qdev_init(DeviceState *dev) void qdev_free(DeviceState *dev) { LIST_REMOVE(dev, sibling); - free(dev); -} - -static DeviceProperty *create_prop(DeviceState *dev, const char *name, - DevicePropType type) -{ - DeviceProperty *prop; - - /* TODO: Check for duplicate properties. */ - prop = qemu_mallocz(sizeof(*prop)); - prop->name = qemu_strdup(name); - prop->type = type; - prop->next = dev->props; - dev->props = prop; - - return prop; -} - -void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value) -{ - DeviceProperty *prop; - - prop = create_prop(dev, name, PROP_TYPE_INT); - prop->value.i = value; -} - -void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value) -{ - DeviceProperty *prop; - - prop = create_prop(dev, name, PROP_TYPE_DEV); - prop->value.ptr = value; -} - -void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value) -{ - DeviceProperty *prop; - - prop = create_prop(dev, name, PROP_TYPE_PTR); - prop->value.ptr = value; -} - -void qdev_set_netdev(DeviceState *dev, NICInfo *nd) -{ - assert(!dev->nd); - dev->nd = nd; + qemu_free(dev->id); + qemu_free(dev); } - /* Get a character (serial) device interface. */ CharDriverState *qdev_init_chardev(DeviceState *dev) { @@ -169,52 +136,6 @@ BusState *qdev_get_parent_bus(DeviceState *dev) return dev->parent_bus; } -static DeviceProperty *find_prop(DeviceState *dev, const char *name, - DevicePropType type) -{ - DeviceProperty *prop; - - for (prop = dev->props; prop; prop = prop->next) { - if (strcmp(prop->name, name) == 0) { - assert (prop->type == type); - return prop; - } - } - return NULL; -} - -uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def) -{ - DeviceProperty *prop; - - prop = find_prop(dev, name, PROP_TYPE_INT); - if (!prop) { - return def; - } - - return prop->value.i; -} - -void *qdev_get_prop_ptr(DeviceState *dev, const char *name) -{ - DeviceProperty *prop; - - prop = find_prop(dev, name, PROP_TYPE_PTR); - assert(prop); - return prop->value.ptr; -} - -DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name) -{ - DeviceProperty *prop; - - prop = find_prop(dev, name, PROP_TYPE_DEV); - if (!prop) { - return NULL; - } - return prop->value.ptr; -} - void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) { assert(dev->num_gpio_in == 0); @@ -327,11 +248,27 @@ BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name) #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__) static void qbus_print(Monitor *mon, BusState *bus, int indent); +static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props, + const char *prefix, int indent) +{ + char buf[64]; + + if (!props) + return; + while (props->name) { + if (props->info->print) { + props->info->print(dev, props, buf, sizeof(buf)); + qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf); + } + props++; + } +} + static void qdev_print(Monitor *mon, DeviceState *dev, int indent) { - DeviceProperty *prop; BusState *child; - qdev_printf("dev: %s\n", dev->info->name); + qdev_printf("dev: %s, id \"%s\"\n", dev->info->name, + dev->id ? dev->id : ""); indent += 2; if (dev->num_gpio_in) { qdev_printf("gpio-in %d\n", dev->num_gpio_in); @@ -339,24 +276,8 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) if (dev->num_gpio_out) { qdev_printf("gpio-out %d\n", dev->num_gpio_out); } - for (prop = dev->props; prop; prop = prop->next) { - switch (prop->type) { - case PROP_TYPE_INT: - qdev_printf("prop-int %s 0x%" PRIx64 "\n", prop->name, - prop->value.i); - break; - case PROP_TYPE_PTR: - qdev_printf("prop-ptr %s\n", prop->name); - break; - case PROP_TYPE_DEV: - qdev_printf("prop-dev %s %s\n", prop->name, - ((DeviceState *)prop->value.ptr)->info->name); - break; - default: - qdev_printf("prop-unknown%d %s\n", prop->type, prop->name); - break; - } - } + qdev_print_props(mon, dev, dev->info->props, "dev", indent); + qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent); if (dev->parent_bus->info->print_dev) dev->parent_bus->info->print_dev(mon, dev, indent); LIST_FOREACH(child, &dev->child_bus, sibling) { diff --git a/qemu/hw/qdev.h b/qemu/hw/qdev.h index b18dbf91..11744fa5 100644 --- a/qemu/hw/qdev.h +++ b/qemu/hw/qdev.h @@ -4,9 +4,13 @@ #include "hw.h" #include "sys-queue.h" -typedef struct DeviceInfo DeviceInfo; +typedef struct Property Property; + +typedef struct PropertyInfo PropertyInfo; -typedef struct DeviceProperty DeviceProperty; +typedef struct CompatProperty CompatProperty; + +typedef struct DeviceInfo DeviceInfo; typedef struct BusState BusState; @@ -15,9 +19,9 @@ typedef struct BusInfo BusInfo; /* This structure should not be accessed directly. We declare it here so that it can be embedded in individual device state structures. */ struct DeviceState { + char *id; DeviceInfo *info; BusState *parent_bus; - DeviceProperty *props; int num_gpio_out; qemu_irq *gpio_out; int num_gpio_in; @@ -32,6 +36,7 @@ struct BusInfo { const char *name; size_t size; bus_dev_printfn print_dev; + Property *props; }; struct BusState { @@ -42,18 +47,42 @@ struct BusState { LIST_ENTRY(BusState) sibling; }; +struct Property { + const char *name; + PropertyInfo *info; + int offset; + void *defval; +}; + +enum PropertyType { + PROP_TYPE_UNSPEC = 0, + PROP_TYPE_UINT16, + PROP_TYPE_UINT32, + PROP_TYPE_TADDR, + PROP_TYPE_MACADDR, + PROP_TYPE_PTR, +}; + +struct PropertyInfo { + const char *name; + size_t size; + enum PropertyType type; + int (*parse)(DeviceState *dev, Property *prop, const char *str); + int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len); +}; + +struct CompatProperty { + const char *driver; + const char *property; + const char *value; +}; + /*** Board API. This should go away once we have a machine config file. ***/ DeviceState *qdev_create(BusState *bus, const char *name); void qdev_init(DeviceState *dev); void qdev_free(DeviceState *dev); -/* Set properties between creation and init. */ -void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value); -void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value); -void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value); -void qdev_set_netdev(DeviceState *dev, NICInfo *nd); - qemu_irq qdev_get_gpio_in(DeviceState *dev, int n); void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); @@ -61,25 +90,17 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name); /*** Device API. ***/ -typedef enum { - PROP_TYPE_INT, - PROP_TYPE_PTR, - PROP_TYPE_DEV -} DevicePropType; - -typedef struct { - const char *name; - DevicePropType type; -} DevicePropList; - typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info); typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv, int unit); struct DeviceInfo { const char *name; + const char *alias; + const char *desc; size_t size; - DevicePropList *props; + Property *props; + int no_user; /* Private to qdev / bus. */ qdev_initfn init; @@ -99,10 +120,6 @@ void scsi_bus_new(DeviceState *host, SCSIAttachFn attach); CharDriverState *qdev_init_chardev(DeviceState *dev); BusState *qdev_get_parent_bus(DeviceState *dev); -uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def); -DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name); -/* FIXME: Remove opaque pointer properties. */ -void *qdev_get_prop_ptr(DeviceState *dev, const char *name); /* Convery from a base type to a parent type, with compile time checking. */ #ifdef __GNUC__ @@ -124,4 +141,25 @@ BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name); void do_info_qtree(Monitor *mon); +/*** qdev-properties.c ***/ + +extern PropertyInfo qdev_prop_uint16; +extern PropertyInfo qdev_prop_uint32; +extern PropertyInfo qdev_prop_hex32; +extern PropertyInfo qdev_prop_ptr; +extern PropertyInfo qdev_prop_macaddr; + +/* Set properties between creation and init. */ +void *qdev_get_prop_ptr(DeviceState *dev, Property *prop); +int qdev_prop_parse(DeviceState *dev, const char *name, const char *value); +void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type); +void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value); +void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value); +/* FIXME: Remove opaque pointer properties. */ +void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); +void qdev_prop_set_defaults(DeviceState *dev, Property *props); + +void qdev_prop_register_compat(CompatProperty *props); +void qdev_prop_set_compat(DeviceState *dev); + #endif diff --git a/qemu/hw/slavio_intctl.c b/qemu/hw/slavio_intctl.c index a46d926e..39a17854 100644 --- a/qemu/hw/slavio_intctl.c +++ b/qemu/hw/slavio_intctl.c @@ -21,9 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" + #include "sun4m.h" #include "monitor.h" +#include "sysbus.h" //#define DEBUG_IRQ_COUNT //#define DEBUG_IRQ @@ -49,28 +50,30 @@ #define MAX_CPUS 16 #define MAX_PILS 16 -struct SLAVIO_CPUINTCTLState; +struct SLAVIO_INTCTLState; + +typedef struct SLAVIO_CPUINTCTLState { + uint32_t intreg_pending; + struct SLAVIO_INTCTLState *master; + uint32_t cpu; +} SLAVIO_CPUINTCTLState; typedef struct SLAVIO_INTCTLState { + SysBusDevice busdev; uint32_t intregm_pending; uint32_t intregm_disabled; uint32_t target_cpu; #ifdef DEBUG_IRQ_COUNT uint64_t irq_count[32]; #endif - qemu_irq *cpu_irqs[MAX_CPUS]; + qemu_irq cpu_irqs[MAX_CPUS][MAX_PILS]; const uint32_t *intbit_to_level; uint32_t cputimer_lbit, cputimer_mbit; + uint32_t cputimer_bit; uint32_t pil_out[MAX_CPUS]; - struct SLAVIO_CPUINTCTLState *slaves[MAX_CPUS]; + SLAVIO_CPUINTCTLState slaves[MAX_CPUS]; } SLAVIO_INTCTLState; -typedef struct SLAVIO_CPUINTCTLState { - uint32_t intreg_pending; - SLAVIO_INTCTLState *master; - uint32_t cpu; -} SLAVIO_CPUINTCTLState; - #define INTCTL_MAXADDR 0xf #define INTCTL_SIZE (INTCTL_MAXADDR + 1) #define INTCTLM_SIZE 0x14 @@ -225,7 +228,7 @@ void slavio_pic_info(Monitor *mon, void *opaque) for (i = 0; i < MAX_CPUS; i++) { monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i, - s->slaves[i]->intreg_pending); + s->slaves[i].intreg_pending); } monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n", s->intregm_pending, s->intregm_disabled); @@ -266,7 +269,7 @@ static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs) pil_pending |= 1 << s->intbit_to_level[j]; } } - pil_pending |= (s->slaves[i]->intreg_pending & CPU_SOFTIRQ_MASK) >> 16; + pil_pending |= (s->slaves[i].intreg_pending & CPU_SOFTIRQ_MASK) >> 16; if (set_irqs) { for (j = 0; j < MAX_PILS; j++) { @@ -303,10 +306,10 @@ static void slavio_set_irq(void *opaque, int irq, int level) s->irq_count[pil]++; #endif s->intregm_pending |= mask; - s->slaves[s->target_cpu]->intreg_pending |= 1 << pil; + s->slaves[s->target_cpu].intreg_pending |= 1 << pil; } else { s->intregm_pending &= ~mask; - s->slaves[s->target_cpu]->intreg_pending &= ~(1 << pil); + s->slaves[s->target_cpu].intreg_pending &= ~(1 << pil); } slavio_check_interrupts(s, 1); } @@ -320,22 +323,31 @@ static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level) if (level) { s->intregm_pending |= s->cputimer_mbit; - s->slaves[cpu]->intreg_pending |= s->cputimer_lbit; + s->slaves[cpu].intreg_pending |= s->cputimer_lbit; } else { s->intregm_pending &= ~s->cputimer_mbit; - s->slaves[cpu]->intreg_pending &= ~s->cputimer_lbit; + s->slaves[cpu].intreg_pending &= ~s->cputimer_lbit; } slavio_check_interrupts(s, 1); } +static void slavio_set_irq_all(void *opaque, int irq, int level) +{ + if (irq < 32) { + slavio_set_irq(opaque, irq, level); + } else { + slavio_set_timer_irq_cpu(opaque, irq - 32, level); + } +} + static void slavio_intctl_save(QEMUFile *f, void *opaque) { SLAVIO_INTCTLState *s = opaque; int i; for (i = 0; i < MAX_CPUS; i++) { - qemu_put_be32s(f, &s->slaves[i]->intreg_pending); + qemu_put_be32s(f, &s->slaves[i].intreg_pending); } qemu_put_be32s(f, &s->intregm_pending); qemu_put_be32s(f, &s->intregm_disabled); @@ -351,7 +363,7 @@ static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id) return -EINVAL; for (i = 0; i < MAX_CPUS; i++) { - qemu_get_be32s(f, &s->slaves[i]->intreg_pending); + qemu_get_be32s(f, &s->slaves[i].intreg_pending); } qemu_get_be32s(f, &s->intregm_pending); qemu_get_be32s(f, &s->intregm_disabled); @@ -366,7 +378,7 @@ static void slavio_intctl_reset(void *opaque) int i; for (i = 0; i < MAX_CPUS; i++) { - s->slaves[i]->intreg_pending = 0; + s->slaves[i].intreg_pending = 0; } s->intregm_disabled = ~MASTER_IRQ_MASK; s->intregm_pending = 0; @@ -374,47 +386,87 @@ static void slavio_intctl_reset(void *opaque) slavio_check_interrupts(s, 0); } -void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg, - const uint32_t *intbit_to_level, - qemu_irq **irq, qemu_irq **cpu_irq, - qemu_irq **parent_irq, unsigned int cputimer) +static void slavio_intctl_init1(SysBusDevice *dev) { - int slavio_intctl_io_memory, slavio_intctlm_io_memory, i; - SLAVIO_INTCTLState *s; - SLAVIO_CPUINTCTLState *slave; + SLAVIO_INTCTLState *s = FROM_SYSBUS(SLAVIO_INTCTLState, dev); + int io_memory; + unsigned int i, j; - s = qemu_mallocz(sizeof(SLAVIO_INTCTLState)); + qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS); + io_memory = cpu_register_io_memory(slavio_intctlm_mem_read, + slavio_intctlm_mem_write, s); + sysbus_init_mmio(dev, INTCTLM_SIZE, io_memory); + s->cputimer_mbit = 1 << s->cputimer_bit; + s->cputimer_lbit = 1 << s->intbit_to_level[s->cputimer_bit]; - s->intbit_to_level = intbit_to_level; for (i = 0; i < MAX_CPUS; i++) { - slave = qemu_mallocz(sizeof(SLAVIO_CPUINTCTLState)); + for (j = 0; j < MAX_PILS; j++) { + sysbus_init_irq(dev, &s->cpu_irqs[i][j]); + } + io_memory = cpu_register_io_memory(slavio_intctl_mem_read, + slavio_intctl_mem_write, + &s->slaves[i]); + sysbus_init_mmio(dev, INTCTL_SIZE, io_memory); + s->slaves[i].cpu = i; + s->slaves[i].master = s; + } + register_savevm("slavio_intctl", -1, 1, slavio_intctl_save, + slavio_intctl_load, s); + qemu_register_reset(slavio_intctl_reset, s); + slavio_intctl_reset(s); +} + +DeviceState *slavio_intctl_init(target_phys_addr_t addr, + target_phys_addr_t addrg, + const uint32_t *intbit_to_level, + qemu_irq **parent_irq, unsigned int cputimer) +{ + DeviceState *dev; + SysBusDevice *s; + unsigned int i, j; - slave->cpu = i; - slave->master = s; + dev = qdev_create(NULL, "slavio_intctl"); + qdev_prop_set_ptr(dev, "intbit_to_level", (void *)intbit_to_level); + qdev_prop_set_uint32(dev, "cputimer_bit", cputimer); + qdev_init(dev); - slavio_intctl_io_memory = cpu_register_io_memory(slavio_intctl_mem_read, - slavio_intctl_mem_write, - slave); - cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_SIZE, - slavio_intctl_io_memory); + s = sysbus_from_qdev(dev); - s->slaves[i] = slave; - s->cpu_irqs[i] = parent_irq[i]; + for (i = 0; i < MAX_CPUS; i++) { + for (j = 0; j < MAX_PILS; j++) { + sysbus_connect_irq(s, i * MAX_PILS + j, parent_irq[i][j]); + } + } + sysbus_mmio_map(s, 0, addrg); + for (i = 0; i < MAX_CPUS; i++) { + sysbus_mmio_map(s, i + 1, addr + i * TARGET_PAGE_SIZE); } - slavio_intctlm_io_memory = cpu_register_io_memory(slavio_intctlm_mem_read, - slavio_intctlm_mem_write, - s); - cpu_register_physical_memory(addrg, INTCTLM_SIZE, slavio_intctlm_io_memory); + return dev; +} - register_savevm("slavio_intctl", addr, 1, slavio_intctl_save, - slavio_intctl_load, s); - qemu_register_reset(slavio_intctl_reset, s); - *irq = qemu_allocate_irqs(slavio_set_irq, s, 32); +static SysBusDeviceInfo slavio_intctl_info = { + .init = slavio_intctl_init1, + .qdev.name = "slavio_intctl", + .qdev.size = sizeof(SLAVIO_INTCTLState), + .qdev.props = (Property[]) { + { + .name = "intbit_to_level", + .info = &qdev_prop_ptr, + .offset = offsetof(SLAVIO_INTCTLState, intbit_to_level), + }, + { + .name = "cputimer_bit", + .info = &qdev_prop_uint32, + .offset = offsetof(SLAVIO_INTCTLState, cputimer_bit), + }, + {/* end of property list */} + } +}; - *cpu_irq = qemu_allocate_irqs(slavio_set_timer_irq_cpu, s, MAX_CPUS); - s->cputimer_mbit = 1 << cputimer; - s->cputimer_lbit = 1 << intbit_to_level[cputimer]; - slavio_intctl_reset(s); - return s; +static void slavio_intctl_register_devices(void) +{ + sysbus_register_withprop(&slavio_intctl_info); } + +device_init(slavio_intctl_register_devices); diff --git a/qemu/hw/slavio_misc.c b/qemu/hw/slavio_misc.c index 9761290d..9e4ed853 100644 --- a/qemu/hw/slavio_misc.c +++ b/qemu/hw/slavio_misc.c @@ -21,9 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" + #include "sun4m.h" #include "sysemu.h" +#include "sysbus.h" /* debug misc */ //#define DEBUG_MISC @@ -44,16 +45,21 @@ #endif typedef struct MiscState { + SysBusDevice busdev; qemu_irq irq; uint8_t config; uint8_t aux1, aux2; uint8_t diag, mctrl; uint32_t sysctrl; uint16_t leds; - qemu_irq cpu_halt; qemu_irq fdc_tc; } MiscState; +typedef struct APCState { + SysBusDevice busdev; + qemu_irq cpu_halt; +} APCState; + #define MISC_SIZE 1 #define SYSCTRL_SIZE 4 @@ -283,7 +289,7 @@ static CPUWriteMemoryFunc *slavio_aux2_mem_write[3] = { static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { - MiscState *s = opaque; + APCState *s = opaque; MISC_DPRINTF("Write power management %2.2x\n", val & 0xff); qemu_irq_raise(s->cpu_halt); @@ -434,75 +440,142 @@ static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id) return 0; } -void *slavio_misc_init(target_phys_addr_t base, target_phys_addr_t power_base, +void *slavio_misc_init(target_phys_addr_t base, target_phys_addr_t aux1_base, target_phys_addr_t aux2_base, qemu_irq irq, - qemu_irq cpu_halt, qemu_irq **fdc_tc) + qemu_irq fdc_tc) { - int io; - MiscState *s; - - s = qemu_mallocz(sizeof(MiscState)); + DeviceState *dev; + SysBusDevice *s; + MiscState *d; + dev = qdev_create(NULL, "slavio_misc"); + qdev_init(dev); + s = sysbus_from_qdev(dev); if (base) { /* 8 bit registers */ - - // Slavio control - io = cpu_register_io_memory(slavio_cfg_mem_read, - slavio_cfg_mem_write, s); - cpu_register_physical_memory(base + MISC_CFG, MISC_SIZE, io); - - // Diagnostics - io = cpu_register_io_memory(slavio_diag_mem_read, - slavio_diag_mem_write, s); - cpu_register_physical_memory(base + MISC_DIAG, MISC_SIZE, io); - - // Modem control - io = cpu_register_io_memory(slavio_mdm_mem_read, - slavio_mdm_mem_write, s); - cpu_register_physical_memory(base + MISC_MDM, MISC_SIZE, io); - + /* Slavio control */ + sysbus_mmio_map(s, 0, base + MISC_CFG); + /* Diagnostics */ + sysbus_mmio_map(s, 1, base + MISC_DIAG); + /* Modem control */ + sysbus_mmio_map(s, 2, base + MISC_MDM); /* 16 bit registers */ - io = cpu_register_io_memory(slavio_led_mem_read, - slavio_led_mem_write, s); /* ss600mp diag LEDs */ - cpu_register_physical_memory(base + MISC_LEDS, MISC_SIZE, io); - + sysbus_mmio_map(s, 3, base + MISC_LEDS); /* 32 bit registers */ - io = cpu_register_io_memory(slavio_sysctrl_mem_read, - slavio_sysctrl_mem_write, s); - // System control - cpu_register_physical_memory(base + MISC_SYS, SYSCTRL_SIZE, io); + /* System control */ + sysbus_mmio_map(s, 4, base + MISC_SYS); } - - // AUX 1 (Misc System Functions) if (aux1_base) { - io = cpu_register_io_memory(slavio_aux1_mem_read, - slavio_aux1_mem_write, s); - cpu_register_physical_memory(aux1_base, MISC_SIZE, io); + /* AUX 1 (Misc System Functions) */ + sysbus_mmio_map(s, 5, aux1_base); } - - // AUX 2 (Software Powerdown Control) if (aux2_base) { - io = cpu_register_io_memory(slavio_aux2_mem_read, - slavio_aux2_mem_write, s); - cpu_register_physical_memory(aux2_base, MISC_SIZE, io); + /* AUX 2 (Software Powerdown Control) */ + sysbus_mmio_map(s, 6, aux2_base); } + sysbus_connect_irq(s, 0, irq); + sysbus_connect_irq(s, 1, fdc_tc); - // Power management (APC) XXX: not a Slavio device - if (power_base) { - io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s); - cpu_register_physical_memory(power_base, MISC_SIZE, io); - } + d = FROM_SYSBUS(MiscState, s); - s->irq = irq; - s->cpu_halt = cpu_halt; - *fdc_tc = &s->fdc_tc; + return d; +} - register_savevm("slavio_misc", base, 1, slavio_misc_save, slavio_misc_load, +static void apc_init1(SysBusDevice *dev) +{ + APCState *s = FROM_SYSBUS(APCState, dev); + int io; + + sysbus_init_irq(dev, &s->cpu_halt); + + /* Power management (APC) XXX: not a Slavio device */ + io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s); + sysbus_init_mmio(dev, MISC_SIZE, io); +} + +void apc_init(target_phys_addr_t power_base, qemu_irq cpu_halt) +{ + DeviceState *dev; + SysBusDevice *s; + + dev = qdev_create(NULL, "apc"); + qdev_init(dev); + s = sysbus_from_qdev(dev); + /* Power management (APC) XXX: not a Slavio device */ + sysbus_mmio_map(s, 0, power_base); + sysbus_connect_irq(s, 0, cpu_halt); +} + +static void slavio_misc_init1(SysBusDevice *dev) +{ + MiscState *s = FROM_SYSBUS(MiscState, dev); + int io; + + sysbus_init_irq(dev, &s->irq); + sysbus_init_irq(dev, &s->fdc_tc); + + /* 8 bit registers */ + /* Slavio control */ + io = cpu_register_io_memory(slavio_cfg_mem_read, + slavio_cfg_mem_write, s); + sysbus_init_mmio(dev, MISC_SIZE, io); + + /* Diagnostics */ + io = cpu_register_io_memory(slavio_diag_mem_read, + slavio_diag_mem_write, s); + sysbus_init_mmio(dev, MISC_SIZE, io); + + /* Modem control */ + io = cpu_register_io_memory(slavio_mdm_mem_read, + slavio_mdm_mem_write, s); + sysbus_init_mmio(dev, MISC_SIZE, io); + + /* 16 bit registers */ + /* ss600mp diag LEDs */ + io = cpu_register_io_memory(slavio_led_mem_read, + slavio_led_mem_write, s); + sysbus_init_mmio(dev, MISC_SIZE, io); + + /* 32 bit registers */ + /* System control */ + io = cpu_register_io_memory(slavio_sysctrl_mem_read, + slavio_sysctrl_mem_write, s); + sysbus_init_mmio(dev, SYSCTRL_SIZE, io); + + /* AUX 1 (Misc System Functions) */ + io = cpu_register_io_memory(slavio_aux1_mem_read, + slavio_aux1_mem_write, s); + sysbus_init_mmio(dev, MISC_SIZE, io); + + /* AUX 2 (Software Powerdown Control) */ + io = cpu_register_io_memory(slavio_aux2_mem_read, + slavio_aux2_mem_write, s); + sysbus_init_mmio(dev, MISC_SIZE, io); + + register_savevm("slavio_misc", -1, 1, slavio_misc_save, slavio_misc_load, s); qemu_register_reset(slavio_misc_reset, s); slavio_misc_reset(s); +} + +static SysBusDeviceInfo slavio_misc_info = { + .init = slavio_misc_init1, + .qdev.name = "slavio_misc", + .qdev.size = sizeof(MiscState), +}; - return s; +static SysBusDeviceInfo apc_info = { + .init = apc_init1, + .qdev.name = "apc", + .qdev.size = sizeof(MiscState), +}; + +static void slavio_misc_register_devices(void) +{ + sysbus_register_withprop(&slavio_misc_info); + sysbus_register_withprop(&apc_info); } + +device_init(slavio_misc_register_devices); diff --git a/qemu/hw/slavio_timer.c b/qemu/hw/slavio_timer.c index a938fb65..982ff6ef 100644 --- a/qemu/hw/slavio_timer.c +++ b/qemu/hw/slavio_timer.c @@ -21,9 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" + #include "sun4m.h" #include "qemu-timer.h" +#include "sysbus.h" //#define DEBUG_TIMER @@ -52,6 +53,7 @@ #define MAX_CPUS 16 typedef struct SLAVIO_TIMERState { + SysBusDevice busdev; qemu_irq irq; ptimer_state *timer; uint32_t count, counthigh, reached; @@ -364,36 +366,53 @@ static void slavio_timer_reset(void *opaque) static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr, qemu_irq irq, SLAVIO_TIMERState *master, - uint32_t slave_index) + uint32_t slave_index, + uint32_t num_slaves) { - int slavio_timer_io_memory; - SLAVIO_TIMERState *s; + DeviceState *dev; + SysBusDevice *s; + SLAVIO_TIMERState *d; + + dev = qdev_create(NULL, "slavio_timer"); + qdev_prop_set_uint32(dev, "slave_index", slave_index); + qdev_prop_set_uint32(dev, "num_slaves", num_slaves); + qdev_prop_set_ptr(dev, "master", master); + qdev_init(dev); + s = sysbus_from_qdev(dev); + sysbus_connect_irq(s, 0, irq); + sysbus_mmio_map(s, 0, addr); + + d = FROM_SYSBUS(SLAVIO_TIMERState, s); + + return d; +} + +static void slavio_timer_init1(SysBusDevice *dev) +{ + int io; + SLAVIO_TIMERState *s = FROM_SYSBUS(SLAVIO_TIMERState, dev); QEMUBH *bh; - s = qemu_mallocz(sizeof(SLAVIO_TIMERState)); - s->irq = irq; - s->master = master; - s->slave_index = slave_index; - if (!master || slave_index < master->num_slaves) { + sysbus_init_irq(dev, &s->irq); + + if (!s->master || s->slave_index < s->master->num_slaves) { bh = qemu_bh_new(slavio_timer_irq, s); s->timer = ptimer_init(bh); ptimer_set_period(s->timer, TIMER_PERIOD); } - slavio_timer_io_memory = cpu_register_io_memory(slavio_timer_mem_read, - slavio_timer_mem_write, s); - if (master) - cpu_register_physical_memory(addr, CPU_TIMER_SIZE, - slavio_timer_io_memory); - else - cpu_register_physical_memory(addr, SYS_TIMER_SIZE, - slavio_timer_io_memory); - register_savevm("slavio_timer", addr, 3, slavio_timer_save, + io = cpu_register_io_memory(slavio_timer_mem_read, slavio_timer_mem_write, + s); + if (s->master) { + sysbus_init_mmio(dev, CPU_TIMER_SIZE, io); + } else { + sysbus_init_mmio(dev, SYS_TIMER_SIZE, io); + } + + register_savevm("slavio_timer", -1, 3, slavio_timer_save, slavio_timer_load, s); qemu_register_reset(slavio_timer_reset, s); slavio_timer_reset(s); - - return s; } void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq, @@ -402,13 +421,43 @@ void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq, SLAVIO_TIMERState *master; unsigned int i; - master = slavio_timer_init(base + SYS_TIMER_OFFSET, master_irq, NULL, 0); - - master->num_slaves = num_cpus; + master = slavio_timer_init(base + SYS_TIMER_OFFSET, master_irq, NULL, 0, + num_cpus); for (i = 0; i < MAX_CPUS; i++) { master->slave[i] = slavio_timer_init(base + (target_phys_addr_t) CPU_TIMER_OFFSET(i), - cpu_irqs[i], master, i); + cpu_irqs[i], master, i, 0); } } + +static SysBusDeviceInfo slavio_timer_info = { + .init = slavio_timer_init1, + .qdev.name = "slavio_timer", + .qdev.size = sizeof(SLAVIO_TIMERState), + .qdev.props = (Property[]) { + { + .name = "num_slaves", + .info = &qdev_prop_uint32, + .offset = offsetof(SLAVIO_TIMERState, num_slaves), + }, + { + .name = "slave_index", + .info = &qdev_prop_uint32, + .offset = offsetof(SLAVIO_TIMERState, slave_index), + }, + { + .name = "master", + .info = &qdev_prop_ptr, + .offset = offsetof(SLAVIO_TIMERState, master), + }, + {/* end of property list */} + } +}; + +static void slavio_timer_register_devices(void) +{ + sysbus_register_withprop(&slavio_timer_info); +} + +device_init(slavio_timer_register_devices); diff --git a/qemu/hw/smbus_eeprom.c b/qemu/hw/smbus_eeprom.c index 81e87806..5a5b28d5 100644 --- a/qemu/hw/smbus_eeprom.c +++ b/qemu/hw/smbus_eeprom.c @@ -99,14 +99,20 @@ static void smbus_eeprom_init(SMBusDevice *dev) { SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *)dev; - /* FIXME: Should be a blob rather than a ptr. */ - eeprom->data = qdev_get_prop_ptr(&dev->i2c.qdev, "data"); eeprom->offset = 0; } static SMBusDeviceInfo smbus_eeprom_info = { .i2c.qdev.name = "smbus-eeprom", .i2c.qdev.size = sizeof(SMBusEEPROMDevice), + .i2c.qdev.props = (Property[]) { + { + .name = "data", + .info = &qdev_prop_ptr, + .offset = offsetof(SMBusEEPROMDevice, data), + }, + {/* end of list */} + }, .init = smbus_eeprom_init, .quick_cmd = eeprom_quick_cmd, .send_byte = eeprom_send_byte, diff --git a/qemu/hw/smc91c111.c b/qemu/hw/smc91c111.c index cf8d864e..5f6956a6 100644 --- a/qemu/hw/smc91c111.c +++ b/qemu/hw/smc91c111.c @@ -733,7 +733,7 @@ void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq) qemu_check_nic_model(nd, "smc91c111"); dev = qdev_create(NULL, "smc91c111"); - qdev_set_netdev(dev, nd); + dev->nd = nd; qdev_init(dev); s = sysbus_from_qdev(dev); sysbus_mmio_map(s, 0, base); diff --git a/qemu/hw/sparc32_dma.c b/qemu/hw/sparc32_dma.c index f272b242..04c307be 100644 --- a/qemu/hw/sparc32_dma.c +++ b/qemu/hw/sparc32_dma.c @@ -21,9 +21,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #include "hw.h" #include "sparc32_dma.h" #include "sun4m.h" +#include "sysbus.h" /* debug DMA */ //#define DEBUG_DMA @@ -60,6 +62,7 @@ typedef struct DMAState DMAState; struct DMAState { + SysBusDevice busdev; uint32_t dmaregs[DMA_REGS]; qemu_irq irq; void *iommu; @@ -242,24 +245,59 @@ static int dma_load(QEMUFile *f, void *opaque, int version_id) } void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq parent_irq, - void *iommu, qemu_irq **dev_irq, qemu_irq **reset) + void *iommu, qemu_irq *dev_irq, qemu_irq **reset) { - DMAState *s; - int dma_io_memory; + DeviceState *dev; + SysBusDevice *s; + DMAState *d; + + dev = qdev_create(NULL, "sparc32_dma"); + qdev_prop_set_ptr(dev, "iommu_opaque", iommu); + qdev_init(dev); + s = sysbus_from_qdev(dev); + sysbus_connect_irq(s, 0, parent_irq); + *dev_irq = qdev_get_gpio_in(dev, 0); + sysbus_mmio_map(s, 0, daddr); + + d = FROM_SYSBUS(DMAState, s); + *reset = &d->dev_reset; + + return d; +} - s = qemu_mallocz(sizeof(DMAState)); +static void sparc32_dma_init1(SysBusDevice *dev) +{ + DMAState *s = FROM_SYSBUS(DMAState, dev); + int dma_io_memory; - s->irq = parent_irq; - s->iommu = iommu; + sysbus_init_irq(dev, &s->irq); dma_io_memory = cpu_register_io_memory(dma_mem_read, dma_mem_write, s); - cpu_register_physical_memory(daddr, DMA_SIZE, dma_io_memory); + sysbus_init_mmio(dev, DMA_SIZE, dma_io_memory); - register_savevm("sparc32_dma", daddr, 2, dma_save, dma_load, s); + register_savevm("sparc32_dma", -1, 2, dma_save, dma_load, s); qemu_register_reset(dma_reset, s); - *dev_irq = qemu_allocate_irqs(dma_set_irq, s, 1); - *reset = &s->dev_reset; + qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1); +} - return s; +static SysBusDeviceInfo sparc32_dma_info = { + .init = sparc32_dma_init1, + .qdev.name = "sparc32_dma", + .qdev.size = sizeof(DMAState), + .qdev.props = (Property[]) { + { + .name = "iommu_opaque", + .info = &qdev_prop_ptr, + .offset = offsetof(DMAState, iommu), + }, + {/* end of property list */} + } +}; + +static void sparc32_dma_register_devices(void) +{ + sysbus_register_withprop(&sparc32_dma_info); } + +device_init(sparc32_dma_register_devices); diff --git a/qemu/hw/sparc32_dma.h b/qemu/hw/sparc32_dma.h index 00b89216..048b9a51 100644 --- a/qemu/hw/sparc32_dma.h +++ b/qemu/hw/sparc32_dma.h @@ -3,7 +3,7 @@ /* sparc32_dma.c */ void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq parent_irq, - void *iommu, qemu_irq **dev_irq, qemu_irq **reset); + void *iommu, qemu_irq *dev_irq, qemu_irq **reset); void ledma_memory_read(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int do_bswap); void ledma_memory_write(void *opaque, target_phys_addr_t addr, diff --git a/qemu/hw/stellaris.c b/qemu/hw/stellaris.c index 5f44bff5..d9434ca2 100644 --- a/qemu/hw/stellaris.c +++ b/qemu/hw/stellaris.c @@ -1378,7 +1378,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, qemu_check_nic_model(&nd_table[0], "stellaris"); enet = qdev_create(NULL, "stellaris_enet"); - qdev_set_netdev(enet, &nd_table[0]); + enet->nd = &nd_table[0]; qdev_init(enet); sysbus_mmio_map(sysbus_from_qdev(enet), 0, 0x40048000); sysbus_connect_irq(sysbus_from_qdev(enet), 0, pic[42]); diff --git a/qemu/hw/sun4m.c b/qemu/hw/sun4m.c index c67bf0b1..4954ba37 100644 --- a/qemu/hw/sun4m.c +++ b/qemu/hw/sun4m.c @@ -373,8 +373,7 @@ static void lance_init(NICInfo *nd, target_phys_addr_t leaddr, qemu_check_nic_model(&nd_table[0], "lance"); dev = qdev_create(NULL, "lance"); - qdev_set_netdev(dev, nd); - qdev_set_prop_ptr(dev, "dma", dma_opaque); + dev->nd = nd; qdev_init(dev); s = sysbus_from_qdev(dev); sysbus_mmio_map(s, 0, leaddr); @@ -382,108 +381,241 @@ static void lance_init(NICInfo *nd, target_phys_addr_t leaddr, *reset = qdev_get_gpio_in(dev, 0); } +/* NCR89C100/MACIO Internal ID register */ +static const uint8_t idreg_data[] = { 0xfe, 0x81, 0x01, 0x03 }; + +static void idreg_init(target_phys_addr_t addr) +{ + DeviceState *dev; + SysBusDevice *s; + + dev = qdev_create(NULL, "macio_idreg"); + qdev_init(dev); + s = sysbus_from_qdev(dev); + + sysbus_mmio_map(s, 0, addr); + cpu_physical_memory_write_rom(addr, idreg_data, sizeof(idreg_data)); +} + +static void idreg_init1(SysBusDevice *dev) +{ + ram_addr_t idreg_offset; + + idreg_offset = qemu_ram_alloc(sizeof(idreg_data)); + sysbus_init_mmio(dev, sizeof(idreg_data), idreg_offset | IO_MEM_ROM); +} + +static SysBusDeviceInfo idreg_info = { + .init = idreg_init1, + .qdev.name = "macio_idreg", + .qdev.size = sizeof(SysBusDevice), +}; + +static void idreg_register_devices(void) +{ + sysbus_register_withprop(&idreg_info); +} + +device_init(idreg_register_devices); + +/* Boot PROM (OpenBIOS) */ +static void prom_init(target_phys_addr_t addr, const char *bios_name) +{ + DeviceState *dev; + SysBusDevice *s; + char *filename; + int ret; + + dev = qdev_create(NULL, "openprom"); + qdev_init(dev); + s = sysbus_from_qdev(dev); + + sysbus_mmio_map(s, 0, addr); + + /* load boot prom */ + if (bios_name == NULL) { + bios_name = PROM_FILENAME; + } + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (filename) { + ret = load_elf(filename, addr - PROM_VADDR, NULL, NULL, NULL); + if (ret < 0 || ret > PROM_SIZE_MAX) { + ret = load_image_targphys(filename, addr, PROM_SIZE_MAX); + } + qemu_free(filename); + } else { + ret = -1; + } + if (ret < 0 || ret > PROM_SIZE_MAX) { + fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name); + exit(1); + } +} + +static void prom_init1(SysBusDevice *dev) +{ + ram_addr_t prom_offset; + + prom_offset = qemu_ram_alloc(PROM_SIZE_MAX); + sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM); +} + +static SysBusDeviceInfo prom_info = { + .init = prom_init1, + .qdev.name = "openprom", + .qdev.size = sizeof(SysBusDevice), + .qdev.props = (Property[]) { + {/* end of property list */} + } +}; + +static void prom_register_devices(void) +{ + sysbus_register_withprop(&prom_info); +} + +device_init(prom_register_devices); + +typedef struct RamDevice +{ + SysBusDevice busdev; + uint32_t size; +} RamDevice; + +/* System RAM */ +static void ram_init1(SysBusDevice *dev) +{ + ram_addr_t RAM_size, ram_offset; + RamDevice *d = FROM_SYSBUS(RamDevice, dev); + + RAM_size = d->size; + + ram_offset = qemu_ram_alloc(RAM_size); + sysbus_init_mmio(dev, RAM_size, ram_offset); +} + +static void ram_init(target_phys_addr_t addr, ram_addr_t RAM_size, + uint64_t max_mem) +{ + DeviceState *dev; + SysBusDevice *s; + RamDevice *d; + + /* allocate RAM */ + if ((uint64_t)RAM_size > max_mem) { + fprintf(stderr, + "qemu: Too much memory for this machine: %d, maximum %d\n", + (unsigned int)(RAM_size / (1024 * 1024)), + (unsigned int)(max_mem / (1024 * 1024))); + exit(1); + } + dev = qdev_create(NULL, "memory"); + qdev_init(dev); + s = sysbus_from_qdev(dev); + + d = FROM_SYSBUS(RamDevice, s); + d->size = RAM_size; + + sysbus_mmio_map(s, 0, addr); +} + +static SysBusDeviceInfo ram_info = { + .init = ram_init1, + .qdev.name = "memory", + .qdev.size = sizeof(RamDevice), + .qdev.props = (Property[]) { + { + .name = "size", + .info = &qdev_prop_uint32, + .offset = offsetof(RamDevice, size), + }, + {/* end of property list */} + } +}; + +static void ram_register_devices(void) +{ + sysbus_register_withprop(&ram_info); +} + +device_init(ram_register_devices); + +static CPUState *cpu_devinit(const char *cpu_model, unsigned int id, + uint64_t prom_addr, qemu_irq **cpu_irqs) +{ + CPUState *env; + + env = cpu_init(cpu_model); + if (!env) { + fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n"); + exit(1); + } + + cpu_sparc_set_id(env, id); + if (id == 0) { + qemu_register_reset(main_cpu_reset, env); + } else { + qemu_register_reset(secondary_cpu_reset, env); + env->halted = 1; + } + *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); + env->prom_addr = prom_addr; + + return env; +} + static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) - { - CPUState *env, *envs[MAX_CPUS]; + CPUState *envs[MAX_CPUS]; unsigned int i; void *iommu, *espdma, *ledma, *nvram; - qemu_irq *cpu_irqs[MAX_CPUS], *slavio_irq, *slavio_cpu_irq, - *espdma_irq, *ledma_irq; + qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS], + espdma_irq, ledma_irq; qemu_irq *esp_reset, *le_reset; - qemu_irq *fdc_tc; + qemu_irq fdc_tc; qemu_irq *cpu_halt; - ram_addr_t ram_offset, prom_offset, idreg_offset; unsigned long kernel_size; - int ret; - char *filename; BlockDriverState *fd[MAX_FD]; int drive_index; void *fw_cfg; + DeviceState *dev; /* init CPUs */ if (!cpu_model) cpu_model = hwdef->default_cpu_model; for(i = 0; i < smp_cpus; i++) { - env = cpu_init(cpu_model); - if (!env) { - fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n"); - exit(1); - } - cpu_sparc_set_id(env, i); - envs[i] = env; - if (i == 0) { - qemu_register_reset(main_cpu_reset, env); - } else { - qemu_register_reset(secondary_cpu_reset, env); - env->halted = 1; - } - cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS); - env->prom_addr = hwdef->slavio_base; + envs[i] = cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]); } for (i = smp_cpus; i < MAX_CPUS; i++) cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS); - /* allocate RAM */ - if ((uint64_t)RAM_size > hwdef->max_mem) { - fprintf(stderr, - "qemu: Too much memory for this machine: %d, maximum %d\n", - (unsigned int)(RAM_size / (1024 * 1024)), - (unsigned int)(hwdef->max_mem / (1024 * 1024))); - exit(1); - } - ram_offset = qemu_ram_alloc(RAM_size); - cpu_register_physical_memory(0, RAM_size, ram_offset); + /* set up devices */ + ram_init(0, RAM_size, hwdef->max_mem); - /* load boot prom */ - prom_offset = qemu_ram_alloc(PROM_SIZE_MAX); - cpu_register_physical_memory(hwdef->slavio_base, - (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & - TARGET_PAGE_MASK, - prom_offset | IO_MEM_ROM); + prom_init(hwdef->slavio_base, bios_name); - if (bios_name == NULL) - bios_name = PROM_FILENAME; - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - if (filename) { - ret = load_elf(filename, hwdef->slavio_base - PROM_VADDR, - NULL, NULL, NULL); - if (ret < 0 || ret > PROM_SIZE_MAX) - ret = load_image_targphys(filename, hwdef->slavio_base, - PROM_SIZE_MAX); - qemu_free(filename); - } else { - ret = -1; + dev = slavio_intctl_init(hwdef->intctl_base, + hwdef->intctl_base + 0x10000ULL, + &hwdef->intbit_to_level[0], + cpu_irqs, + hwdef->clock_irq); + + for (i = 0; i < 32; i++) { + slavio_irq[i] = qdev_get_gpio_in(dev, i); } - if (ret < 0 || ret > PROM_SIZE_MAX) { - fprintf(stderr, "qemu: could not load prom '%s'\n", - bios_name); - exit(1); + for (i = 0; i < MAX_CPUS; i++) { + slavio_cpu_irq[i] = qdev_get_gpio_in(dev, 32 + i); } - /* set up devices */ - slavio_intctl = slavio_intctl_init(hwdef->intctl_base, - hwdef->intctl_base + 0x10000ULL, - &hwdef->intbit_to_level[0], - &slavio_irq, &slavio_cpu_irq, - cpu_irqs, - hwdef->clock_irq); - if (hwdef->idreg_base) { - static const uint8_t idreg_data[] = { 0xfe, 0x81, 0x01, 0x03 }; - - idreg_offset = qemu_ram_alloc(sizeof(idreg_data)); - cpu_register_physical_memory(hwdef->idreg_base, sizeof(idreg_data), - idreg_offset | IO_MEM_ROM); - cpu_physical_memory_write_rom(hwdef->idreg_base, idreg_data, - sizeof(idreg_data)); + idreg_init(hwdef->idreg_base); } iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version, @@ -503,7 +635,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, tcx_init(hwdef->tcx_base, hwdef->vram_size, graphic_width, graphic_height, graphic_depth); - lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset); + lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq, le_reset); nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, hwdef->nvram_size, 8); @@ -519,10 +651,12 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, serial_hds[0], serial_hds[1], ESCC_CLOCK, 1); cpu_halt = qemu_allocate_irqs(cpu_halt_signal, NULL, 1); - slavio_misc = slavio_misc_init(hwdef->slavio_base, hwdef->apc_base, + slavio_misc = slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base, - slavio_irq[hwdef->me_irq], cpu_halt[0], - &fdc_tc); + slavio_irq[hwdef->me_irq], fdc_tc); + if (hwdef->apc_base) { + apc_init(hwdef->apc_base, cpu_halt[0]); + } if (hwdef->fd_base) { /* there is zero or one floppy drive */ @@ -532,7 +666,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, fd[0] = drives_table[drive_index].bdrv; sun4m_fdctrl_init(slavio_irq[hwdef->fd_irq], hwdef->fd_base, fd, - fdc_tc); + &fdc_tc); } if (drive_get_max_bus(IF_SCSI) > 0) { @@ -542,10 +676,12 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, esp_init(hwdef->esp_base, 2, espdma_memory_read, espdma_memory_write, - espdma, *espdma_irq, esp_reset); + espdma, espdma_irq, esp_reset); - if (hwdef->cs_base) - cs_init(hwdef->cs_base, hwdef->cs_irq, slavio_intctl); + if (hwdef->cs_base) { + sysbus_create_simple("SUNW,CS4231", hwdef->cs_base, + slavio_irq[hwdef->cs_irq]); + } kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename, RAM_size); @@ -1183,81 +1319,31 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - CPUState *env, *envs[MAX_CPUS]; + CPUState *envs[MAX_CPUS]; unsigned int i; void *iounits[MAX_IOUNITS], *espdma, *ledma, *nvram, *sbi; qemu_irq *cpu_irqs[MAX_CPUS], *sbi_irq, *sbi_cpu_irq, - *espdma_irq, *ledma_irq; + espdma_irq, ledma_irq; qemu_irq *esp_reset, *le_reset; - ram_addr_t ram_offset, prom_offset; unsigned long kernel_size; - int ret; - char *filename; void *fw_cfg; /* init CPUs */ if (!cpu_model) cpu_model = hwdef->default_cpu_model; - for (i = 0; i < smp_cpus; i++) { - env = cpu_init(cpu_model); - if (!env) { - fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n"); - exit(1); - } - cpu_sparc_set_id(env, i); - envs[i] = env; - if (i == 0) { - qemu_register_reset(main_cpu_reset, env); - } else { - qemu_register_reset(secondary_cpu_reset, env); - env->halted = 1; - } - cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS); - env->prom_addr = hwdef->slavio_base; + for(i = 0; i < smp_cpus; i++) { + envs[i] = cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]); } for (i = smp_cpus; i < MAX_CPUS; i++) cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS); - /* allocate RAM */ - if ((uint64_t)RAM_size > hwdef->max_mem) { - fprintf(stderr, - "qemu: Too much memory for this machine: %d, maximum %d\n", - (unsigned int)(RAM_size / (1024 * 1024)), - (unsigned int)(hwdef->max_mem / (1024 * 1024))); - exit(1); - } - ram_offset = qemu_ram_alloc(RAM_size); - cpu_register_physical_memory(0, RAM_size, ram_offset); - - /* load boot prom */ - prom_offset = qemu_ram_alloc(PROM_SIZE_MAX); - cpu_register_physical_memory(hwdef->slavio_base, - (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & - TARGET_PAGE_MASK, - prom_offset | IO_MEM_ROM); + /* set up devices */ + ram_init(0, RAM_size, hwdef->max_mem); - if (bios_name == NULL) - bios_name = PROM_FILENAME; - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - if (filename) { - ret = load_elf(filename, hwdef->slavio_base - PROM_VADDR, - NULL, NULL, NULL); - if (ret < 0 || ret > PROM_SIZE_MAX) - ret = load_image_targphys(filename, hwdef->slavio_base, - PROM_SIZE_MAX); - qemu_free(filename); - } else { - ret = -1; - } - if (ret < 0 || ret > PROM_SIZE_MAX) { - fprintf(stderr, "qemu: could not load prom '%s'\n", - bios_name); - exit(1); - } + prom_init(hwdef->slavio_base, bios_name); - /* set up devices */ sbi = sbi_init(hwdef->sbi_base, &sbi_irq, &sbi_cpu_irq, cpu_irqs); for (i = 0; i < MAX_IOUNITS; i++) @@ -1279,7 +1365,7 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, tcx_init(hwdef->tcx_base, hwdef->vram_size, graphic_width, graphic_height, graphic_depth); - lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset); + lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq, le_reset); nvram = m48t59_init(sbi_irq[0], hwdef->nvram_base, 0, hwdef->nvram_size, 8); @@ -1301,7 +1387,7 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, esp_init(hwdef->esp_base, 2, espdma_memory_read, espdma_memory_write, - espdma, *espdma_irq, esp_reset); + espdma, espdma_irq, esp_reset); kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename, RAM_size); @@ -1407,13 +1493,10 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, { CPUState *env; void *iommu, *espdma, *ledma, *nvram; - qemu_irq *cpu_irqs, *slavio_irq, *espdma_irq, *ledma_irq; + qemu_irq *cpu_irqs, *slavio_irq, espdma_irq, ledma_irq; qemu_irq *esp_reset, *le_reset; - qemu_irq *fdc_tc; - ram_addr_t ram_offset, prom_offset; + qemu_irq fdc_tc; unsigned long kernel_size; - int ret; - char *filename; BlockDriverState *fd[MAX_FD]; int drive_index; void *fw_cfg; @@ -1422,56 +1505,13 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, if (!cpu_model) cpu_model = hwdef->default_cpu_model; - env = cpu_init(cpu_model); - if (!env) { - fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n"); - exit(1); - } - - cpu_sparc_set_id(env, 0); - - qemu_register_reset(main_cpu_reset, env); - cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); - env->prom_addr = hwdef->slavio_base; - - /* allocate RAM */ - if ((uint64_t)RAM_size > hwdef->max_mem) { - fprintf(stderr, - "qemu: Too much memory for this machine: %d, maximum %d\n", - (unsigned int)(RAM_size / (1024 * 1024)), - (unsigned int)(hwdef->max_mem / (1024 * 1024))); - exit(1); - } - ram_offset = qemu_ram_alloc(RAM_size); - cpu_register_physical_memory(0, RAM_size, ram_offset); + env = cpu_devinit(cpu_model, 0, hwdef->slavio_base, &cpu_irqs); - /* load boot prom */ - prom_offset = qemu_ram_alloc(PROM_SIZE_MAX); - cpu_register_physical_memory(hwdef->slavio_base, - (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & - TARGET_PAGE_MASK, - prom_offset | IO_MEM_ROM); + /* set up devices */ + ram_init(0, RAM_size, hwdef->max_mem); - if (bios_name == NULL) - bios_name = PROM_FILENAME; - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - if (filename) { - ret = load_elf(filename, hwdef->slavio_base - PROM_VADDR, - NULL, NULL, NULL); - if (ret < 0 || ret > PROM_SIZE_MAX) - ret = load_image_targphys(filename, hwdef->slavio_base, - PROM_SIZE_MAX); - qemu_free(filename); - } else { - ret = -1; - } - if (ret < 0 || ret > PROM_SIZE_MAX) { - fprintf(stderr, "qemu: could not load prom '%s'\n", - filename); - exit(1); - } + prom_init(hwdef->slavio_base, bios_name); - /* set up devices */ slavio_intctl = sun4c_intctl_init(hwdef->intctl_base, &slavio_irq, cpu_irqs); @@ -1492,7 +1532,7 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, tcx_init(hwdef->tcx_base, hwdef->vram_size, graphic_width, graphic_height, graphic_depth); - lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset); + lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq, le_reset); nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, hwdef->nvram_size, 2); @@ -1505,8 +1545,8 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, slavio_irq[hwdef->ser_irq], serial_hds[0], serial_hds[1], ESCC_CLOCK, 1); - slavio_misc = slavio_misc_init(0, 0, hwdef->aux1_base, 0, - slavio_irq[hwdef->me_irq], NULL, &fdc_tc); + slavio_misc = slavio_misc_init(0, hwdef->aux1_base, 0, + slavio_irq[hwdef->me_irq], fdc_tc); if (hwdef->fd_base != (target_phys_addr_t)-1) { /* there is zero or one floppy drive */ @@ -1516,7 +1556,7 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, fd[0] = drives_table[drive_index].bdrv; sun4m_fdctrl_init(slavio_irq[hwdef->fd_irq], hwdef->fd_base, fd, - fdc_tc); + &fdc_tc); } if (drive_get_max_bus(IF_SCSI) > 0) { @@ -1526,7 +1566,7 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, esp_init(hwdef->esp_base, 2, espdma_memory_read, espdma_memory_write, - espdma, *espdma_irq, esp_reset); + espdma, espdma_irq, esp_reset); kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename, RAM_size); diff --git a/qemu/hw/sun4m.h b/qemu/hw/sun4m.h index c5605f48..d818fb18 100644 --- a/qemu/hw/sun4m.h +++ b/qemu/hw/sun4m.h @@ -28,10 +28,10 @@ void tcx_init(target_phys_addr_t addr, int vram_size, int width, int height, int depth); /* slavio_intctl.c */ -void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg, - const uint32_t *intbit_to_level, - qemu_irq **irq, qemu_irq **cpu_irq, - qemu_irq **parent_irq, unsigned int cputimer); +DeviceState *slavio_intctl_init(target_phys_addr_t addr, + target_phys_addr_t addrg, + const uint32_t *intbit_to_level, + qemu_irq **parent_irq, unsigned int cputimer); void slavio_pic_info(Monitor *mon, void *opaque); void slavio_irq_info(Monitor *mon, void *opaque); @@ -50,19 +50,17 @@ void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq, qemu_irq *cpu_irqs, unsigned int num_cpus); /* slavio_misc.c */ -void *slavio_misc_init(target_phys_addr_t base, target_phys_addr_t power_base, +void *slavio_misc_init(target_phys_addr_t base, target_phys_addr_t aux1_base, target_phys_addr_t aux2_base, qemu_irq irq, - qemu_irq cpu_halt, qemu_irq **fdc_tc); + qemu_irq fdc_tc); void slavio_set_power_fail(void *opaque, int power_failing); - -/* cs4231.c */ -void cs_init(target_phys_addr_t base, int irq, void *intctl); +void apc_init(target_phys_addr_t power_base, qemu_irq cpu_halt); /* sparc32_dma.c */ #include "sparc32_dma.h" /* eccmemctl.c */ -void *ecc_init(target_phys_addr_t base, qemu_irq irq, uint32_t version); +void ecc_init(target_phys_addr_t base, qemu_irq irq, uint32_t version); #endif diff --git a/qemu/hw/sun4u.c b/qemu/hw/sun4u.c index 40f0c593..9d2a7f59 100644 --- a/qemu/hw/sun4u.c +++ b/qemu/hw/sun4u.c @@ -305,9 +305,12 @@ static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num, static void pci_ebus_init(PCIBus *bus, int devfn) { - PCIDevice *s; + pci_create_simple(bus, devfn, "ebus"); +} - s = pci_register_device(bus, "EBUS", sizeof(*s), devfn, NULL, NULL); +static void +pci_ebus_init1(PCIDevice *s) +{ pci_config_set_vendor_id(s->config, PCI_VENDOR_ID_SUN); pci_config_set_device_id(s->config, PCI_DEVICE_ID_SUN_EBUS); s->config[0x04] = 0x06; // command = bus master, pci mem @@ -326,6 +329,19 @@ pci_ebus_init(PCIBus *bus, int devfn) ebus_mmio_mapfunc); } +static PCIDeviceInfo ebus_info = { + .qdev.name = "ebus", + .qdev.size = sizeof(PCIDevice), + .init = pci_ebus_init1, +}; + +static void pci_ebus_register(void) +{ + pci_qdev_register(&ebus_info); +} + +device_init(pci_ebus_register); + static void sun4uv_init(ram_addr_t RAM_size, const char *boot_devices, const char *kernel_filename, const char *kernel_cmdline, @@ -450,7 +466,9 @@ static void sun4uv_init(ram_addr_t RAM_size, } } } - pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, NULL, &pci_bus2, + + irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); + pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &pci_bus2, &pci_bus3); isa_mem_base = VGA_BASE; pci_vga_init(pci_bus, 0, 0); @@ -481,7 +499,6 @@ static void sun4uv_init(ram_addr_t RAM_size, for(i = 0; i < nb_nics; i++) pci_nic_init(&nd_table[i], "ne2k_pci", NULL); - irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { fprintf(stderr, "qemu: too many IDE bus\n"); exit(1); diff --git a/qemu/hw/syborg.c b/qemu/hw/syborg.c index 5ca9977b..d8d38d48 100644 --- a/qemu/hw/syborg.c +++ b/qemu/hw/syborg.c @@ -64,7 +64,7 @@ static void syborg_init(ram_addr_t ram_size, sysbus_create_simple("syborg,rtc", 0xC0001000, NULL); dev = qdev_create(NULL, "syborg,timer"); - qdev_set_prop_int(dev, "frequency", 1000000); + qdev_prop_set_uint32(dev, "frequency", 1000000); qdev_init(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xC0002000); sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[1]); @@ -83,7 +83,7 @@ static void syborg_init(ram_addr_t ram_size, qemu_check_nic_model(&nd_table[0], "virtio"); dev = qdev_create(NULL, "syborg,virtio-net"); - qdev_set_netdev(dev, &nd_table[0]); + dev->nd = &nd_table[0]; qdev_init(dev); s = sysbus_from_qdev(dev); sysbus_mmio_map(s, 0, 0xc000c000); diff --git a/qemu/hw/syborg_fb.c b/qemu/hw/syborg_fb.c index 42c62744..2929ffd0 100644 --- a/qemu/hw/syborg_fb.c +++ b/qemu/hw/syborg_fb.c @@ -76,8 +76,8 @@ typedef struct { uint32_t base; uint32_t pitch; - int rows; - int cols; + uint32_t rows; + uint32_t cols; int blank; int bpp; int rgb; /* 0 = BGR, 1 = RGB */ @@ -507,41 +507,50 @@ static void syborg_fb_init(SysBusDevice *dev) { SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev); int iomemtype; - int width; - int height; sysbus_init_irq(dev, &s->irq); iomemtype = cpu_register_io_memory(syborg_fb_readfn, syborg_fb_writefn, s); sysbus_init_mmio(dev, 0x1000, iomemtype); - width = qdev_get_prop_int(&dev->qdev, "width", 0); - height = qdev_get_prop_int(&dev->qdev, "height", 0); - s->ds = graphic_console_init(syborg_fb_update_display, syborg_fb_invalidate_display, NULL, NULL, s); - if (width != 0 && height != 0) { - qemu_console_resize(s->ds, width, height); + if (s->cols != 0 && s->rows != 0) { + qemu_console_resize(s->ds, s->cols, s->rows); } - if (!width) - width = ds_get_width(s->ds); - if (!height) - height = ds_get_height(s->ds); - - s->cols = width; - s->rows = height; + if (!s->cols) + s->cols = ds_get_width(s->ds); + if (!s->rows) + s->rows = ds_get_height(s->ds); register_savevm("syborg_framebuffer", -1, 1, syborg_fb_save, syborg_fb_load, s); } +static SysBusDeviceInfo syborg_fb_info = { + .init = syborg_fb_init, + .qdev.name = "syborg,framebuffer", + .qdev.size = sizeof(SyborgFBState), + .qdev.props = (Property[]) { + { + .name = "width", + .info = &qdev_prop_uint32, + .offset = offsetof(SyborgFBState, cols), + },{ + .name = "height", + .info = &qdev_prop_uint32, + .offset = offsetof(SyborgFBState, rows), + }, + {/* end of list */} + } +}; + static void syborg_fb_register_devices(void) { - sysbus_register_dev("syborg,framebuffer", sizeof(SyborgFBState), - syborg_fb_init); + sysbus_register_withprop(&syborg_fb_info); } device_init(syborg_fb_register_devices) diff --git a/qemu/hw/syborg_interrupt.c b/qemu/hw/syborg_interrupt.c index 569c7f61..a372ec1d 100644 --- a/qemu/hw/syborg_interrupt.c +++ b/qemu/hw/syborg_interrupt.c @@ -56,7 +56,7 @@ typedef struct { typedef struct { SysBusDevice busdev; int pending_count; - int num_irqs; + uint32_t num_irqs; syborg_int_flags *flags; qemu_irq parent_irq; } SyborgIntState; @@ -208,7 +208,6 @@ static void syborg_int_init(SysBusDevice *dev) int iomemtype; sysbus_init_irq(dev, &s->parent_irq); - s->num_irqs = qdev_get_prop_int(&dev->qdev, "num-interrupts", 64); qdev_init_gpio_in(&dev->qdev, syborg_int_set_irq, s->num_irqs); iomemtype = cpu_register_io_memory(syborg_int_readfn, syborg_int_writefn, s); @@ -218,10 +217,24 @@ static void syborg_int_init(SysBusDevice *dev) register_savevm("syborg_int", -1, 1, syborg_int_save, syborg_int_load, s); } +static SysBusDeviceInfo syborg_int_info = { + .init = syborg_int_init, + .qdev.name = "syborg,interrupt", + .qdev.size = sizeof(SyborgIntState), + .qdev.props = (Property[]) { + { + .name = "num-interrupts", + .info = &qdev_prop_uint32, + .offset = offsetof(SyborgIntState, num_irqs), + .defval = (uint32_t[]) { 64 }, + }, + {/* end of list */} + } +}; + static void syborg_interrupt_register_devices(void) { - sysbus_register_dev("syborg,interrupt", sizeof(SyborgIntState), - syborg_int_init); + sysbus_register_withprop(&syborg_int_info); } device_init(syborg_interrupt_register_devices) diff --git a/qemu/hw/syborg_keyboard.c b/qemu/hw/syborg_keyboard.c index 84a099ed..ffc85a56 100644 --- a/qemu/hw/syborg_keyboard.c +++ b/qemu/hw/syborg_keyboard.c @@ -53,7 +53,7 @@ typedef struct { SysBusDevice busdev; int int_enabled; int extension_bit; - int fifo_size; + uint32_t fifo_size; uint32_t *key_fifo; int read_pos, read_count; qemu_irq irq; @@ -212,7 +212,6 @@ static void syborg_keyboard_init(SysBusDevice *dev) iomemtype = cpu_register_io_memory(syborg_keyboard_readfn, syborg_keyboard_writefn, s); sysbus_init_mmio(dev, 0x1000, iomemtype); - s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16); if (s->fifo_size <= 0) { fprintf(stderr, "syborg_keyboard: fifo too small\n"); s->fifo_size = 16; @@ -225,10 +224,24 @@ static void syborg_keyboard_init(SysBusDevice *dev) syborg_keyboard_save, syborg_keyboard_load, s); } +static SysBusDeviceInfo syborg_keyboard_info = { + .init = syborg_keyboard_init, + .qdev.name = "syborg,keyboard", + .qdev.size = sizeof(SyborgKeyboardState), + .qdev.props = (Property[]) { + { + .name = "fifo-size", + .info = &qdev_prop_uint32, + .offset = offsetof(SyborgKeyboardState, fifo_size), + .defval = (uint32_t[]) { 16 }, + }, + {/* end of list */} + } +}; + static void syborg_keyboard_register_devices(void) { - sysbus_register_dev("syborg,keyboard", sizeof(SyborgKeyboardState), - syborg_keyboard_init); + sysbus_register_withprop(&syborg_keyboard_info); } device_init(syborg_keyboard_register_devices) diff --git a/qemu/hw/syborg_pointer.c b/qemu/hw/syborg_pointer.c index e0a892d0..edd1f222 100644 --- a/qemu/hw/syborg_pointer.c +++ b/qemu/hw/syborg_pointer.c @@ -45,11 +45,11 @@ typedef struct { typedef struct { SysBusDevice busdev; int int_enabled; - int fifo_size; + uint32_t fifo_size; event_data *event_fifo; int read_pos, read_count; qemu_irq irq; - int absolute; + uint32_t absolute; } SyborgPointerState; static void syborg_pointer_update(SyborgPointerState *s) @@ -209,8 +209,6 @@ static void syborg_pointer_init(SysBusDevice *dev) syborg_pointer_writefn, s); sysbus_init_mmio(dev, 0x1000, iomemtype); - s->absolute = qdev_get_prop_int(&dev->qdev, "absolute", 1); - s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16); if (s->fifo_size <= 0) { fprintf(stderr, "syborg_pointer: fifo too small\n"); s->fifo_size = 16; @@ -224,10 +222,29 @@ static void syborg_pointer_init(SysBusDevice *dev) syborg_pointer_save, syborg_pointer_load, s); } +static SysBusDeviceInfo syborg_pointer_info = { + .init = syborg_pointer_init, + .qdev.name = "syborg,pointer", + .qdev.size = sizeof(SyborgPointerState), + .qdev.props = (Property[]) { + { + .name = "fifo-size", + .info = &qdev_prop_uint32, + .offset = offsetof(SyborgPointerState, fifo_size), + .defval = (uint32_t[]) { 16 }, + },{ + .name = "absolute", + .info = &qdev_prop_uint32, + .offset = offsetof(SyborgPointerState, absolute), + .defval = (uint32_t[]) { 1 }, + }, + {/* end of list */} + } +}; + static void syborg_pointer_register_devices(void) { - sysbus_register_dev("syborg,pointer", sizeof(SyborgPointerState), - syborg_pointer_init); + sysbus_register_withprop(&syborg_pointer_info); } device_init(syborg_pointer_register_devices) diff --git a/qemu/hw/syborg_serial.c b/qemu/hw/syborg_serial.c index f4305080..f6934215 100644 --- a/qemu/hw/syborg_serial.c +++ b/qemu/hw/syborg_serial.c @@ -59,7 +59,7 @@ enum { typedef struct { SysBusDevice busdev; uint32_t int_enable; - int fifo_size; + uint32_t fifo_size; uint32_t *read_fifo; int read_pos; int read_count; @@ -329,7 +329,6 @@ static void syborg_serial_init(SysBusDevice *dev) qemu_chr_add_handlers(s->chr, syborg_serial_can_receive, syborg_serial_receive, syborg_serial_event, s); } - s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16); if (s->fifo_size <= 0) { fprintf(stderr, "syborg_serial: fifo too small\n"); s->fifo_size = 16; @@ -340,10 +339,24 @@ static void syborg_serial_init(SysBusDevice *dev) syborg_serial_save, syborg_serial_load, s); } +static SysBusDeviceInfo syborg_serial_info = { + .init = syborg_serial_init, + .qdev.name = "syborg,serial", + .qdev.size = sizeof(SyborgSerialState), + .qdev.props = (Property[]) { + { + .name = "fifo-size", + .info = &qdev_prop_uint32, + .offset = offsetof(SyborgSerialState, fifo_size), + .defval = (uint32_t[]) { 16 }, + }, + {/* end of list */} + } +}; + static void syborg_serial_register_devices(void) { - sysbus_register_dev("syborg,serial", sizeof(SyborgSerialState), - syborg_serial_init); + sysbus_register_withprop(&syborg_serial_info); } device_init(syborg_serial_register_devices) diff --git a/qemu/hw/syborg_timer.c b/qemu/hw/syborg_timer.c index 4f5e3a17..cf96c5ff 100644 --- a/qemu/hw/syborg_timer.c +++ b/qemu/hw/syborg_timer.c @@ -209,7 +209,6 @@ static void syborg_timer_init(SysBusDevice *dev) QEMUBH *bh; int iomemtype; - s->freq = qdev_get_prop_int(&dev->qdev, "frequency", 0); if (s->freq == 0) { fprintf(stderr, "syborg_timer: Zero/unset frequency\n"); exit(1); @@ -230,9 +229,13 @@ static SysBusDeviceInfo syborg_timer_info = { .init = syborg_timer_init, .qdev.name = "syborg,timer", .qdev.size = sizeof(SyborgTimerState), - .qdev.props = (DevicePropList[]) { - {.name = "frequency", .type = PROP_TYPE_INT}, - {.name = NULL} + .qdev.props = (Property[]) { + { + .name = "frequency", + .info = &qdev_prop_uint32, + .offset = offsetof(SyborgTimerState, freq), + }, + {/* end of list */} } }; diff --git a/qemu/hw/sysbus.c b/qemu/hw/sysbus.c index 08f15e42..814d3470 100644 --- a/qemu/hw/sysbus.c +++ b/qemu/hw/sysbus.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 . */ #include "sysbus.h" diff --git a/qemu/hw/sysbus.h b/qemu/hw/sysbus.h index 7c20808f..d48ca8ca 100644 --- a/qemu/hw/sysbus.h +++ b/qemu/hw/sysbus.h @@ -5,8 +5,8 @@ #include "qdev.h" -#define QDEV_MAX_MMIO 5 -#define QDEV_MAX_IRQ 32 +#define QDEV_MAX_MMIO 32 +#define QDEV_MAX_IRQ 256 typedef struct SysBusDevice SysBusDevice; typedef void (*mmio_mapfunc)(SysBusDevice *dev, target_phys_addr_t addr); diff --git a/qemu/hw/tcx.c b/qemu/hw/tcx.c index 10bc9813..c5925240 100644 --- a/qemu/hw/tcx.c +++ b/qemu/hw/tcx.c @@ -21,10 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" + #include "sun4m.h" #include "console.h" #include "pixel_ops.h" +#include "sysbus.h" +#include "qdev-addr.h" #define MAXX 1024 #define MAXY 768 @@ -34,11 +36,13 @@ #define TCX_TEC_NREGS 0x1000 typedef struct TCXState { + SysBusDevice busdev; target_phys_addr_t addr; DisplayState *ds; uint8_t *vram; uint32_t *vram24, *cplane; ram_addr_t vram_offset, vram24_offset, cplane_offset; + uint32_t vram_size; uint16_t width, height, depth; uint8_t r[256], g[256], b[256]; uint32_t palette[256]; @@ -47,8 +51,25 @@ typedef struct TCXState { static void tcx_screen_dump(void *opaque, const char *filename); static void tcx24_screen_dump(void *opaque, const char *filename); -static void tcx_invalidate_display(void *opaque); -static void tcx24_invalidate_display(void *opaque); + +static void tcx_set_dirty(TCXState *s) +{ + unsigned int i; + + for (i = 0; i < MAXX * MAXY; i += TARGET_PAGE_SIZE) { + cpu_physical_memory_set_dirty(s->vram_offset + i); + } +} + +static void tcx24_set_dirty(TCXState *s) +{ + unsigned int i; + + for (i = 0; i < MAXX * MAXY * 4; i += TARGET_PAGE_SIZE) { + cpu_physical_memory_set_dirty(s->vram24_offset + i); + cpu_physical_memory_set_dirty(s->cplane_offset + i); + } +} static void update_palette_entries(TCXState *s, int start, int end) { @@ -73,10 +94,11 @@ static void update_palette_entries(TCXState *s, int start, int end) break; } } - if (s->depth == 24) - tcx24_invalidate_display(s); - else - tcx_invalidate_display(s); + if (s->depth == 24) { + tcx24_set_dirty(s); + } else { + tcx_set_dirty(s); + } } static void tcx_draw_line32(TCXState *s1, uint8_t *d, @@ -342,23 +364,18 @@ static void tcx24_update_display(void *opaque) static void tcx_invalidate_display(void *opaque) { TCXState *s = opaque; - int i; - for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) { - cpu_physical_memory_set_dirty(s->vram_offset + i); - } + tcx_set_dirty(s); + qemu_console_resize(s->ds, s->width, s->height); } static void tcx24_invalidate_display(void *opaque) { TCXState *s = opaque; - int i; - tcx_invalidate_display(s); - for (i = 0; i < MAXX*MAXY * 4; i += TARGET_PAGE_SIZE) { - cpu_physical_memory_set_dirty(s->vram24_offset + i); - cpu_physical_memory_set_dirty(s->cplane_offset + i); - } + tcx_set_dirty(s); + tcx24_set_dirty(s); + qemu_console_resize(s->ds, s->width, s->height); } static void tcx_save(QEMUFile *f, void *opaque) @@ -397,10 +414,11 @@ static int tcx_load(QEMUFile *f, void *opaque, int version_id) qemu_get_8s(f, &s->dac_index); qemu_get_8s(f, &s->dac_state); update_palette_entries(s, 0, 256); - if (s->depth == 24) - tcx24_invalidate_display(s); - else - tcx_invalidate_display(s); + if (s->depth == 24) { + tcx24_set_dirty(s); + } else { + tcx_set_dirty(s); + } return 0; } @@ -500,69 +518,97 @@ static CPUWriteMemoryFunc *tcx_dummy_write[3] = { void tcx_init(target_phys_addr_t addr, int vram_size, int width, int height, int depth) { - TCXState *s; + DeviceState *dev; + SysBusDevice *s; + + dev = qdev_create(NULL, "SUNW,tcx"); + qdev_prop_set_taddr(dev, "addr", addr); + qdev_prop_set_uint32(dev, "vram_size", vram_size); + qdev_prop_set_uint16(dev, "width", width); + qdev_prop_set_uint16(dev, "height", height); + qdev_prop_set_uint16(dev, "depth", depth); + qdev_init(dev); + s = sysbus_from_qdev(dev); + /* 8-bit plane */ + sysbus_mmio_map(s, 0, addr + 0x00800000ULL); + /* DAC */ + sysbus_mmio_map(s, 1, addr + 0x00200000ULL); + /* TEC (dummy) */ + sysbus_mmio_map(s, 2, addr + 0x00700000ULL); + /* THC 24 bit: NetBSD writes here even with 8-bit display: dummy */ + sysbus_mmio_map(s, 3, addr + 0x00301000ULL); + if (depth == 24) { + /* 24-bit plane */ + sysbus_mmio_map(s, 4, addr + 0x02000000ULL); + /* Control plane */ + sysbus_mmio_map(s, 5, addr + 0x0a000000ULL); + } else { + /* THC 8 bit (dummy) */ + sysbus_mmio_map(s, 4, addr + 0x00300000ULL); + } +} + +static void tcx_init1(SysBusDevice *dev) +{ + TCXState *s = FROM_SYSBUS(TCXState, dev); int io_memory, dummy_memory; ram_addr_t vram_offset; int size; uint8_t *vram_base; - vram_offset = qemu_ram_alloc(vram_size * (1 + 4 + 4)); + vram_offset = qemu_ram_alloc(s->vram_size * (1 + 4 + 4)); vram_base = qemu_get_ram_ptr(vram_offset); - - s = qemu_mallocz(sizeof(TCXState)); - s->addr = addr; s->vram_offset = vram_offset; - s->width = width; - s->height = height; - s->depth = depth; - // 8-bit plane + /* 8-bit plane */ s->vram = vram_base; - size = vram_size; - cpu_register_physical_memory(addr + 0x00800000ULL, size, vram_offset); + size = s->vram_size; + sysbus_init_mmio(dev, size, s->vram_offset); vram_offset += size; vram_base += size; + /* DAC */ io_memory = cpu_register_io_memory(tcx_dac_read, tcx_dac_write, s); - cpu_register_physical_memory(addr + 0x00200000ULL, TCX_DAC_NREGS, - io_memory); + sysbus_init_mmio(dev, TCX_DAC_NREGS, io_memory); + /* TEC (dummy) */ dummy_memory = cpu_register_io_memory(tcx_dummy_read, tcx_dummy_write, s); - cpu_register_physical_memory(addr + 0x00700000ULL, TCX_TEC_NREGS, - dummy_memory); - if (depth == 24) { - // 24-bit plane - size = vram_size * 4; + sysbus_init_mmio(dev, TCX_TEC_NREGS, dummy_memory); + /* THC: NetBSD writes here even with 8-bit display: dummy */ + sysbus_init_mmio(dev, TCX_THC_NREGS_24, dummy_memory); + + if (s->depth == 24) { + /* 24-bit plane */ + size = s->vram_size * 4; s->vram24 = (uint32_t *)vram_base; s->vram24_offset = vram_offset; - cpu_register_physical_memory(addr + 0x02000000ULL, size, vram_offset); + sysbus_init_mmio(dev, size, vram_offset); vram_offset += size; vram_base += size; - // Control plane - size = vram_size * 4; + /* Control plane */ + size = s->vram_size * 4; s->cplane = (uint32_t *)vram_base; s->cplane_offset = vram_offset; - cpu_register_physical_memory(addr + 0x0a000000ULL, size, vram_offset); + sysbus_init_mmio(dev, size, vram_offset); + s->ds = graphic_console_init(tcx24_update_display, tcx24_invalidate_display, tcx24_screen_dump, NULL, s); } else { - cpu_register_physical_memory(addr + 0x00300000ULL, TCX_THC_NREGS_8, - dummy_memory); + /* THC 8 bit (dummy) */ + sysbus_init_mmio(dev, TCX_THC_NREGS_8, dummy_memory); + s->ds = graphic_console_init(tcx_update_display, tcx_invalidate_display, tcx_screen_dump, NULL, s); } - // NetBSD writes here even with 8-bit display - cpu_register_physical_memory(addr + 0x00301000ULL, TCX_THC_NREGS_24, - dummy_memory); - register_savevm("tcx", addr, 4, tcx_save, tcx_load, s); + register_savevm("tcx", -1, 4, tcx_save, tcx_load, s); qemu_register_reset(tcx_reset, s); tcx_reset(s); - qemu_console_resize(s->ds, width, height); + qemu_console_resize(s->ds, s->width, s->height); } static void tcx_screen_dump(void *opaque, const char *filename) @@ -627,3 +673,45 @@ static void tcx24_screen_dump(void *opaque, const char *filename) fclose(f); return; } + +static SysBusDeviceInfo tcx_info = { + .init = tcx_init1, + .qdev.name = "SUNW,tcx", + .qdev.size = sizeof(TCXState), + .qdev.props = (Property[]) { + { + .name = "addr", + .info = &qdev_prop_taddr, + .offset = offsetof(TCXState, addr), + .defval = (target_phys_addr_t[]) { -1 }, + },{ + .name = "vram_size", + .info = &qdev_prop_hex32, + .offset = offsetof(TCXState, vram_size), + .defval = (uint32_t[]) { -1 }, + },{ + .name = "width", + .info = &qdev_prop_uint16, + .offset = offsetof(TCXState, width), + .defval = (uint16_t[]) { -1 }, + },{ + .name = "height", + .info = &qdev_prop_uint16, + .offset = offsetof(TCXState, height), + .defval = (uint16_t[]) { -1 }, + },{ + .name = "depth", + .info = &qdev_prop_uint16, + .offset = offsetof(TCXState, depth), + .defval = (uint16_t[]) { -1 }, + }, + {/* end of list */} + } +}; + +static void tcx_register_devices(void) +{ + sysbus_register_withprop(&tcx_info); +} + +device_init(tcx_register_devices) diff --git a/qemu/hw/usb-ohci.c b/qemu/hw/usb-ohci.c index 23b5e214..28ab3a91 100644 --- a/qemu/hw/usb-ohci.c +++ b/qemu/hw/usb-ohci.c @@ -15,8 +15,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 . * * TODO: * o Isochronous transfers @@ -1150,9 +1149,9 @@ static void ohci_frame_boundary(void *opaque) /* Frame boundary, so do EOF stuf here */ ohci->frt = ohci->fit; - /* XXX: endianness */ + /* Increment frame number and take care of endianness. */ ohci->frame_number = (ohci->frame_number + 1) & 0xffff; - hcca.frame = cpu_to_le32(ohci->frame_number); + hcca.frame = cpu_to_le16(ohci->frame_number); if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) { if (!ohci->done) diff --git a/qemu/hw/virtio-pci.c b/qemu/hw/virtio-pci.c index e2cc036f..579e5bc7 100644 --- a/qemu/hw/virtio-pci.c +++ b/qemu/hw/virtio-pci.c @@ -86,12 +86,7 @@ typedef struct { PCIDevice pci_dev; VirtIODevice *vdev; uint32_t addr; - - uint16_t vendor; - uint16_t device; - uint16_t subvendor; - uint16_t class_code; - uint8_t pif; + uint32_t class_code; } VirtIOPCIProxy; /* virtio device */ @@ -126,11 +121,18 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f) VirtIOPCIProxy *proxy = opaque; int ret; ret = pci_device_load(&proxy->pci_dev, f); - if (ret) + if (ret) { return ret; + } msix_load(&proxy->pci_dev, f); - if (msix_present(&proxy->pci_dev)) + if (msix_present(&proxy->pci_dev)) { qemu_get_be16s(f, &proxy->vdev->config_vector); + } else { + proxy->vdev->config_vector = VIRTIO_NO_VECTOR; + } + if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) { + return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector); + } return 0; } @@ -138,10 +140,15 @@ static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f) { VirtIOPCIProxy *proxy = opaque; uint16_t vector; - if (!msix_present(&proxy->pci_dev)) - return 0; - qemu_get_be16s(f, &vector); + if (msix_present(&proxy->pci_dev)) { + qemu_get_be16s(f, &vector); + } else { + vector = VIRTIO_NO_VECTOR; + } virtio_queue_set_vector(proxy->vdev, n, vector); + if (vector != VIRTIO_NO_VECTOR) { + return msix_vector_use(&proxy->pci_dev, vector); + } return 0; } @@ -414,7 +421,8 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev, virtio_bind_device(vdev, &virtio_pci_bindings, proxy); } -static void virtio_blk_init_pci(PCIDevice *pci_dev) +static void virtio_blk_init_pci_with_class(PCIDevice *pci_dev, + uint16_t class_code) { VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); VirtIODevice *vdev; @@ -423,11 +431,27 @@ static void virtio_blk_init_pci(PCIDevice *pci_dev) virtio_init_pci(proxy, vdev, PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_BLOCK, - PCI_CLASS_STORAGE_OTHER, - 0x00); + class_code, 0x00); } -static void virtio_console_init_pci(PCIDevice *pci_dev) +static void virtio_blk_init_pci(PCIDevice *pci_dev) +{ + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); + + if (proxy->class_code != PCI_CLASS_STORAGE_SCSI && + proxy->class_code != PCI_CLASS_STORAGE_OTHER) + proxy->class_code = PCI_CLASS_STORAGE_SCSI; + + virtio_blk_init_pci_with_class(pci_dev, proxy->class_code); +} + +static void virtio_blk_init_pci_0_10(PCIDevice *pci_dev) +{ + virtio_blk_init_pci_with_class(pci_dev, PCI_CLASS_STORAGE_OTHER); +} + +static void virtio_console_init_pci_with_class(PCIDevice *pci_dev, + uint16_t class_code) { VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); VirtIODevice *vdev; @@ -436,8 +460,24 @@ static void virtio_console_init_pci(PCIDevice *pci_dev) virtio_init_pci(proxy, vdev, PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_CONSOLE, - PCI_CLASS_DISPLAY_OTHER, - 0x00); + class_code, 0x00); +} + +static void virtio_console_init_pci(PCIDevice *pci_dev) +{ + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); + + if (proxy->class_code != PCI_CLASS_COMMUNICATION_OTHER && + proxy->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */ + proxy->class_code != PCI_CLASS_OTHERS) /* qemu-kvm */ + proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER; + + virtio_console_init_pci_with_class(pci_dev, proxy->class_code); +} + +static void virtio_console_init_pci_0_10(PCIDevice *pci_dev) +{ + virtio_console_init_pci_with_class(pci_dev, PCI_CLASS_DISPLAY_OTHER); } static void virtio_net_init_pci(PCIDevice *pci_dev) @@ -471,6 +511,14 @@ static PCIDeviceInfo virtio_info[] = { .qdev.name = "virtio-blk-pci", .qdev.size = sizeof(VirtIOPCIProxy), .init = virtio_blk_init_pci, + .qdev.props = (Property[]) { + { + .name = "class", + .info = &qdev_prop_hex32, + .offset = offsetof(VirtIOPCIProxy, class_code), + }, + {/* end of list */} + }, },{ .qdev.name = "virtio-net-pci", .qdev.size = sizeof(VirtIOPCIProxy), @@ -479,10 +527,27 @@ static PCIDeviceInfo virtio_info[] = { .qdev.name = "virtio-console-pci", .qdev.size = sizeof(VirtIOPCIProxy), .init = virtio_console_init_pci, + .qdev.props = (Property[]) { + { + .name = "class", + .info = &qdev_prop_hex32, + .offset = offsetof(VirtIOPCIProxy, class_code), + }, + {/* end of list */} + }, },{ .qdev.name = "virtio-balloon-pci", .qdev.size = sizeof(VirtIOPCIProxy), .init = virtio_balloon_init_pci, + },{ + /* For compatibility with 0.10 */ + .qdev.name = "virtio-blk-pci-0-10", + .qdev.size = sizeof(VirtIOPCIProxy), + .init = virtio_blk_init_pci_0_10, + },{ + .qdev.name = "virtio-console-pci-0-10", + .qdev.size = sizeof(VirtIOPCIProxy), + .init = virtio_console_init_pci_0_10, },{ /* end of list */ } diff --git a/qemu/hw/xilinx.h b/qemu/hw/xilinx.h index 9707a0e0..070679c2 100644 --- a/qemu/hw/xilinx.h +++ b/qemu/hw/xilinx.h @@ -8,7 +8,7 @@ xilinx_intc_create(target_phys_addr_t base, qemu_irq irq, int kind_of_intr) DeviceState *dev; dev = qdev_create(NULL, "xilinx,intc"); - qdev_set_prop_int(dev, "kind-of-intr", kind_of_intr); + qdev_prop_set_uint32(dev, "kind-of-intr", kind_of_intr); qdev_init(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); @@ -22,8 +22,8 @@ xilinx_timer_create(target_phys_addr_t base, qemu_irq irq, int nr, int freq) DeviceState *dev; dev = qdev_create(NULL, "xilinx,timer"); - qdev_set_prop_int(dev, "nr-timers", nr); - qdev_set_prop_int(dev, "frequency", freq); + qdev_prop_set_uint32(dev, "nr-timers", nr); + qdev_prop_set_uint32(dev, "frequency", freq); qdev_init(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); @@ -40,9 +40,9 @@ xilinx_ethlite_create(NICInfo *nd, target_phys_addr_t base, qemu_irq irq, qemu_check_nic_model(nd, "xilinx-ethlite"); dev = qdev_create(NULL, "xilinx,ethlite"); - qdev_set_netdev(dev, nd); - qdev_set_prop_int(dev, "txpingpong", txpingpong); - qdev_set_prop_int(dev, "rxpingpong", rxpingpong); + dev->nd = nd; + qdev_prop_set_uint32(dev, "txpingpong", txpingpong); + qdev_prop_set_uint32(dev, "rxpingpong", rxpingpong); qdev_init(dev); sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); diff --git a/qemu/hw/xilinx_ethlite.c b/qemu/hw/xilinx_ethlite.c index f4b40c7b..b3fd25bb 100644 --- a/qemu/hw/xilinx_ethlite.c +++ b/qemu/hw/xilinx_ethlite.c @@ -53,8 +53,8 @@ struct xlx_ethlite qemu_irq irq; VLANClientState *vc; - unsigned int c_tx_pingpong; - unsigned int c_rx_pingpong; + uint32_t c_tx_pingpong; + uint32_t c_rx_pingpong; unsigned int txbuf; unsigned int rxbuf; @@ -213,8 +213,6 @@ static void xilinx_ethlite_init(SysBusDevice *dev) int regs; sysbus_init_irq(dev, &s->irq); - s->c_tx_pingpong = qdev_get_prop_int(&dev->qdev, "txpingpong", 1); - s->c_rx_pingpong = qdev_get_prop_int(&dev->qdev, "rxpingpong", 1); s->rxbuf = 0; regs = cpu_register_io_memory(eth_read, eth_write, s); @@ -225,10 +223,29 @@ static void xilinx_ethlite_init(SysBusDevice *dev) eth_can_rx, eth_rx, NULL, eth_cleanup, s); } +static SysBusDeviceInfo xilinx_ethlite_info = { + .init = xilinx_ethlite_init, + .qdev.name = "xilinx,ethlite", + .qdev.size = sizeof(struct xlx_ethlite), + .qdev.props = (Property[]) { + { + .name = "txpingpong", + .info = &qdev_prop_uint32, + .offset = offsetof(struct xlx_ethlite, c_tx_pingpong), + .defval = (uint32_t[]) { 1 }, + },{ + .name = "rxpingpong", + .info = &qdev_prop_uint32, + .offset = offsetof(struct xlx_ethlite, c_rx_pingpong), + .defval = (uint32_t[]) { 1 }, + }, + {/* end of list */} + } +}; + static void xilinx_ethlite_register(void) { - sysbus_register_dev("xilinx,ethlite", sizeof (struct xlx_ethlite), - xilinx_ethlite_init); + sysbus_register_withprop(&xilinx_ethlite_info); } device_init(xilinx_ethlite_register) diff --git a/qemu/hw/xilinx_intc.c b/qemu/hw/xilinx_intc.c index 0540f52d..3f08bf81 100644 --- a/qemu/hw/xilinx_intc.c +++ b/qemu/hw/xilinx_intc.c @@ -150,7 +150,6 @@ static void xilinx_intc_init(SysBusDevice *dev) struct xlx_pic *p = FROM_SYSBUS(typeof (*p), dev); int pic_regs; - p->c_kind_of_intr = qdev_get_prop_int(&dev->qdev, "kind-of-intr", 0); qdev_init_gpio_in(&dev->qdev, irq_handler, 32); sysbus_init_irq(dev, &p->parent_irq); @@ -158,10 +157,23 @@ static void xilinx_intc_init(SysBusDevice *dev) sysbus_init_mmio(dev, R_MAX * 4, pic_regs); } +static SysBusDeviceInfo xilinx_intc_info = { + .init = xilinx_intc_init, + .qdev.name = "xilinx,intc", + .qdev.size = sizeof(struct xlx_pic), + .qdev.props = (Property[]) { + { + .name = "kind-of-intr", + .info = &qdev_prop_uint32, + .offset = offsetof(struct xlx_pic, c_kind_of_intr), + }, + {/* end of list */} + } +}; + static void xilinx_intc_register(void) { - sysbus_register_dev("xilinx,intc", sizeof (struct xlx_pic), - xilinx_intc_init); + sysbus_register_withprop(&xilinx_intc_info); } device_init(xilinx_intc_register) diff --git a/qemu/hw/xilinx_timer.c b/qemu/hw/xilinx_timer.c index a64ad2d8..efb6a04f 100644 --- a/qemu/hw/xilinx_timer.c +++ b/qemu/hw/xilinx_timer.c @@ -61,7 +61,8 @@ struct timerblock { SysBusDevice busdev; qemu_irq irq; - unsigned int nr_timers; + uint32_t nr_timers; + uint32_t freq_hz; struct xlx_timer *timers; }; @@ -192,14 +193,12 @@ static void xilinx_timer_init(SysBusDevice *dev) { struct timerblock *t = FROM_SYSBUS(typeof (*t), dev); unsigned int i; - int timer_regs, freq_hz; + int timer_regs; /* All timers share a single irq line. */ sysbus_init_irq(dev, &t->irq); /* Init all the ptimers. */ - freq_hz = qdev_get_prop_int(&dev->qdev, "frequency", 2); - t->nr_timers = qdev_get_prop_int(&dev->qdev, "nr-timers", 2); t->timers = qemu_mallocz(sizeof t->timers[0] * t->nr_timers); for (i = 0; i < t->nr_timers; i++) { struct xlx_timer *xt = &t->timers[i]; @@ -208,17 +207,36 @@ static void xilinx_timer_init(SysBusDevice *dev) xt->nr = i; xt->bh = qemu_bh_new(timer_hit, xt); xt->ptimer = ptimer_init(xt->bh); - ptimer_set_freq(xt->ptimer, freq_hz); + ptimer_set_freq(xt->ptimer, t->freq_hz); } timer_regs = cpu_register_io_memory(timer_read, timer_write, t); sysbus_init_mmio(dev, R_MAX * 4 * t->nr_timers, timer_regs); } +static SysBusDeviceInfo xilinx_timer_info = { + .init = xilinx_timer_init, + .qdev.name = "xilinx,timer", + .qdev.size = sizeof(struct timerblock), + .qdev.props = (Property[]) { + { + .name = "frequency", + .info = &qdev_prop_uint32, + .offset = offsetof(struct timerblock, freq_hz), + .defval = (uint32_t[]) { 2 }, + },{ + .name = "nr-timers", + .info = &qdev_prop_uint32, + .offset = offsetof(struct timerblock, nr_timers), + .defval = (uint32_t[]) { 2 }, + }, + {/* end of list */} + } +}; + static void xilinx_timer_register(void) { - sysbus_register_dev("xilinx,timer", sizeof (struct timerblock), - xilinx_timer_init); + sysbus_register_withprop(&xilinx_timer_info); } device_init(xilinx_timer_register) diff --git a/qemu/ioport-user.c b/qemu/ioport-user.c index fe8567f4..11c76c76 100644 --- a/qemu/ioport-user.c +++ b/qemu/ioport-user.c @@ -14,9 +14,7 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - * MA 02110-1301, USA. + * along with this program; if not, see . */ #include @@ -25,35 +23,38 @@ #include "qemu-common.h" #include "ioport.h" -void cpu_outb(CPUState *env, int addr, int val) +void cpu_outb(CPUState *env, pio_addr_t addr, uint8_t val) { - fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val); + fprintf(stderr, "outb: port=0x%04"FMT_pioaddr", data=%02"PRIx8"\n", + addr, val); } -void cpu_outw(CPUState *env, int addr, int val) +void cpu_outw(CPUState *env, pio_addr_t addr, uint16_t val) { - fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val); + fprintf(stderr, "outw: port=0x%04"FMT_pioaddr", data=%04"PRIx16"\n", + addr, val); } -void cpu_outl(CPUState *env, int addr, int val) +void cpu_outl(CPUState *env, pio_addr_t addr, uint32_t val) { - fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val); + fprintf(stderr, "outl: port=0x%04"FMT_pioaddr", data=%08"PRIx32"\n", + addr, val); } -int cpu_inb(CPUState *env, int addr) +uint8_t cpu_inb(CPUState *env, pio_addr_t addr) { - fprintf(stderr, "inb: port=0x%04x\n", addr); + fprintf(stderr, "inb: port=0x%04"FMT_pioaddr"\n", addr); return 0; } -int cpu_inw(CPUState *env, int addr) +uint16_t cpu_inw(CPUState *env, pio_addr_t addr) { - fprintf(stderr, "inw: port=0x%04x\n", addr); + fprintf(stderr, "inw: port=0x%04"FMT_pioaddr"\n", addr); return 0; } -int cpu_inl(CPUState *env, int addr) +uint32_t cpu_inl(CPUState *env, pio_addr_t addr) { - fprintf(stderr, "inl: port=0x%04x\n", addr); + fprintf(stderr, "inl: port=0x%04"FMT_pioaddr"\n", addr); return 0; } diff --git a/qemu/ioport.c b/qemu/ioport.c index 01cfaf70..13183a2f 100644 --- a/qemu/ioport.c +++ b/qemu/ioport.c @@ -33,6 +33,12 @@ //#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 @@ -76,17 +82,14 @@ static void ioport_write(int index, uint32_t address, uint32_t data) static uint32_t default_ioport_readb(void *opaque, uint32_t address) { -#ifdef DEBUG_UNUSED_IOPORT - fprintf(stderr, "unused inb: port=0x%04x\n", address); -#endif + 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) { -#ifdef DEBUG_UNUSED_IOPORT - fprintf(stderr, "unused outb: port=0x%04x data=0x%02x\n", address, data); -#endif + LOG_UNUSED_IOPORT("unused outb: port=0x%04"PRIx32" data=0x%02"PRIx32"\n", + address, data); } /* default is to make two byte accesses */ @@ -108,17 +111,14 @@ static void default_ioport_writew(void *opaque, uint32_t address, uint32_t data) static uint32_t default_ioport_readl(void *opaque, uint32_t address) { -#ifdef DEBUG_UNUSED_IOPORT - fprintf(stderr, "unused inl: port=0x%04x\n", address); -#endif + 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) { -#ifdef DEBUG_UNUSED_IOPORT - fprintf(stderr, "unused outl: port=0x%04x data=0x%02x\n", address, data); -#endif + LOG_UNUSED_IOPORT("unused outl: port=0x%04"PRIx32" data=0x%02"PRIx32"\n", + address, data); } static int ioport_bsize(int size, int *bsize) @@ -136,7 +136,7 @@ static int ioport_bsize(int size, int *bsize) } /* size is the word size in byte */ -int register_ioport_read(int start, int length, int size, +int register_ioport_read(pio_addr_t start, int length, int size, IOPortReadFunc *func, void *opaque) { int i, bsize; @@ -155,7 +155,7 @@ int register_ioport_read(int start, int length, int size, } /* size is the word size in byte */ -int register_ioport_write(int start, int length, int size, +int register_ioport_write(pio_addr_t start, int length, int size, IOPortWriteFunc *func, void *opaque) { int i, bsize; @@ -173,7 +173,7 @@ int register_ioport_write(int start, int length, int size, return 0; } -void isa_unassign_ioport(int start, int length) +void isa_unassign_ioport(pio_addr_t start, int length) { int i; @@ -192,9 +192,9 @@ void isa_unassign_ioport(int start, int length) /***********************************************************/ -void cpu_outb(CPUState *env, int addr, int val) +void cpu_outb(CPUState *env, pio_addr_t addr, uint8_t val) { - LOG_IOPORT("outb: %04x %02x\n", addr, val); + LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); ioport_write(0, addr, val); #ifdef CONFIG_KQEMU if (env) @@ -202,9 +202,9 @@ void cpu_outb(CPUState *env, int addr, int val) #endif } -void cpu_outw(CPUState *env, int addr, int val) +void cpu_outw(CPUState *env, pio_addr_t addr, uint16_t val) { - LOG_IOPORT("outw: %04x %04x\n", addr, val); + LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); ioport_write(1, addr, val); #ifdef CONFIG_KQEMU if (env) @@ -212,9 +212,9 @@ void cpu_outw(CPUState *env, int addr, int val) #endif } -void cpu_outl(CPUState *env, int addr, int val) +void cpu_outl(CPUState *env, pio_addr_t addr, uint32_t val) { - LOG_IOPORT("outl: %04x %08x\n", addr, val); + LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); ioport_write(2, addr, val); #ifdef CONFIG_KQEMU if (env) @@ -222,11 +222,11 @@ void cpu_outl(CPUState *env, int addr, int val) #endif } -int cpu_inb(CPUState *env, int addr) +uint8_t cpu_inb(CPUState *env, pio_addr_t addr) { - int val; + uint8_t val; val = ioport_read(0, addr); - LOG_IOPORT("inb : %04x %02x\n", addr, val); + LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); #ifdef CONFIG_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); @@ -234,11 +234,11 @@ int cpu_inb(CPUState *env, int addr) return val; } -int cpu_inw(CPUState *env, int addr) +uint16_t cpu_inw(CPUState *env, pio_addr_t addr) { - int val; + uint16_t val; val = ioport_read(1, addr); - LOG_IOPORT("inw : %04x %04x\n", addr, val); + LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); #ifdef CONFIG_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); @@ -246,15 +246,14 @@ int cpu_inw(CPUState *env, int addr) return val; } -int cpu_inl(CPUState *env, int addr) +uint32_t cpu_inl(CPUState *env, pio_addr_t addr) { - int val; + uint32_t val; val = ioport_read(2, addr); - LOG_IOPORT("inl : %04x %08x\n", addr, val); + LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); #ifdef CONFIG_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); #endif return val; } - diff --git a/qemu/ioport.h b/qemu/ioport.h index 4cb59e95..f981e8c4 100644 --- a/qemu/ioport.h +++ b/qemu/ioport.h @@ -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 . */ /************************************************************************** @@ -27,6 +26,9 @@ #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) @@ -34,22 +36,22 @@ typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); -int register_ioport_read(int start, int length, int size, +int register_ioport_read(pio_addr_t start, int length, int size, IOPortReadFunc *func, void *opaque); -int register_ioport_write(int start, int length, int size, +int register_ioport_write(pio_addr_t start, int length, int size, IOPortWriteFunc *func, void *opaque); -void isa_unassign_ioport(int start, int length); +void isa_unassign_ioport(pio_addr_t start, int length); /* NOTE: as these functions may be even used when there is an isa brige on non x86 targets, we always defined them */ #if !defined(NO_CPU_IO_DEFS) && defined(NEED_CPU_H) -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); +void cpu_outb(CPUState *env, pio_addr_t addr, uint8_t val); +void cpu_outw(CPUState *env, pio_addr_t addr, uint16_t val); +void cpu_outl(CPUState *env, pio_addr_t addr, uint32_t val); +uint8_t cpu_inb(CPUState *env, pio_addr_t addr); +uint16_t cpu_inw(CPUState *env, pio_addr_t addr); +uint32_t cpu_inl(CPUState *env, pio_addr_t addr); #endif #endif /* IOPORT_H */ diff --git a/qemu/linux-user/flatload.c b/qemu/linux-user/flatload.c index 8eba5a81..6a2c3f95 100644 --- a/qemu/linux-user/flatload.c +++ b/qemu/linux-user/flatload.c @@ -13,9 +13,7 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - * MA 02110-1301, USA. + * along with this program; if not, see . * * Copyright (C) 2006 CodeSourcery. * Copyright (C) 2000-2003 David McCullough diff --git a/qemu/linux-user/m68k-sim.c b/qemu/linux-user/m68k-sim.c index 8a2b1d87..64d3b23d 100644 --- a/qemu/linux-user/m68k-sim.c +++ b/qemu/linux-user/m68k-sim.c @@ -14,9 +14,7 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - * MA 02110-1301, USA. + * along with this program; if not, see . */ #include diff --git a/qemu/linux-user/main.c b/qemu/linux-user/main.c index e331d658..9038b58e 100644 --- a/qemu/linux-user/main.c +++ b/qemu/linux-user/main.c @@ -14,9 +14,7 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - * MA 02110-1301, USA. + * along with this program; if not, see . */ #include #include @@ -1053,7 +1051,8 @@ do { \ fprintf(stderr, fmt , ## __VA_ARGS__); \ cpu_dump_state(env, stderr, fprintf, 0); \ qemu_log(fmt, ## __VA_ARGS__); \ - log_cpu_state(env, 0); \ + if (logfile) \ + log_cpu_state(env, 0); \ } while (0) void cpu_loop(CPUPPCState *env) diff --git a/qemu/linux-user/mmap.c b/qemu/linux-user/mmap.c index aa22006f..79cb4e60 100644 --- a/qemu/linux-user/mmap.c +++ b/qemu/linux-user/mmap.c @@ -14,9 +14,7 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - * MA 02110-1301, USA. + * along with this program; if not, see . */ #include #include diff --git a/qemu/linux-user/ppc/syscall.h b/qemu/linux-user/ppc/syscall.h index d789911e..481047b2 100644 --- a/qemu/linux-user/ppc/syscall.h +++ b/qemu/linux-user/ppc/syscall.h @@ -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 . */ /* XXX: ABSOLUTELY BUGGY: diff --git a/qemu/linux-user/signal.c b/qemu/linux-user/signal.c index 6ee61a91..93c2ebe1 100644 --- a/qemu/linux-user/signal.c +++ b/qemu/linux-user/signal.c @@ -14,9 +14,7 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - * MA 02110-1301, USA. + * along with this program; if not, see . */ #include #include diff --git a/qemu/linux-user/syscall.c b/qemu/linux-user/syscall.c index 00096232..8b0a5fa3 100644 --- a/qemu/linux-user/syscall.c +++ b/qemu/linux-user/syscall.c @@ -14,9 +14,7 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - * MA 02110-1301, USA. + * along with this program; if not, see . */ #define _ATFILE_SOURCE #include diff --git a/qemu/linux-user/vm86.c b/qemu/linux-user/vm86.c index cc6c8c99..0b2439df 100644 --- a/qemu/linux-user/vm86.c +++ b/qemu/linux-user/vm86.c @@ -14,9 +14,7 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - * MA 02110-1301, USA. + * along with this program; if not, see . */ #include #include diff --git a/qemu/migration-exec.c b/qemu/migration-exec.c index 6ed322a9..e472979d 100644 --- a/qemu/migration-exec.c +++ b/qemu/migration-exec.c @@ -18,7 +18,6 @@ #include "migration.h" #include "qemu-char.h" #include "sysemu.h" -#include "console.h" #include "buffered_file.h" #include "block.h" @@ -55,7 +54,7 @@ static int exec_close(FdMigrationState *s) MigrationState *exec_start_outgoing_migration(const char *command, int64_t bandwidth_limit, - int async) + int detach) { FdMigrationState *s; FILE *f; @@ -89,14 +88,11 @@ MigrationState *exec_start_outgoing_migration(const char *command, s->mig_state.release = migrate_fd_release; s->state = MIG_STATE_ACTIVE; - s->detach = !async; + s->mon_resume = NULL; s->bandwidth_limit = bandwidth_limit; - if (s->detach == 1) { - dprintf("detaching from monitor\n"); - monitor_suspend(); - s->detach = 2; - } + if (!detach) + migrate_fd_monitor_suspend(s); migrate_fd_connect(s); return &s->mig_state; @@ -108,18 +104,11 @@ MigrationState *exec_start_outgoing_migration(const char *command, return NULL; } -int exec_start_incoming_migration(const char *command) +static void exec_accept_incoming_migration(void *opaque) { + QEMUFile *f = opaque; int ret; - QEMUFile *f; - dprintf("Attempting to start an incoming migration\n"); - f = qemu_popen_cmd(command, "r"); - if(f == NULL) { - dprintf("Unable to apply qemu wrapper to popen file\n"); - return -errno; - } - vm_stop(0); /* just in case */ ret = qemu_loadvm_state(f); if (ret < 0) { fprintf(stderr, "load of migration failed\n"); @@ -127,11 +116,27 @@ int exec_start_incoming_migration(const char *command) } qemu_announce_self(); dprintf("successfully loaded vm state\n"); - vm_start(); - qemu_fclose(f); - return 0; + /* we've successfully migrated, close the fd */ + qemu_set_fd_handler2(qemu_popen_fd(f), NULL, NULL, NULL, NULL); err: qemu_fclose(f); - return -errno; +} + +int exec_start_incoming_migration(const char *command) +{ + QEMUFile *f; + + dprintf("Attempting to start an incoming migration\n"); + f = qemu_popen_cmd(command, "r"); + if(f == NULL) { + dprintf("Unable to apply qemu wrapper to popen file\n"); + return -errno; + } + + qemu_set_fd_handler2(qemu_popen_fd(f), NULL, + exec_accept_incoming_migration, NULL, + (void *)(unsigned long)f); + + return 0; } diff --git a/qemu/migration-tcp.c b/qemu/migration-tcp.c index 1f4358ee..7a87a1ed 100644 --- a/qemu/migration-tcp.c +++ b/qemu/migration-tcp.c @@ -155,7 +155,6 @@ static void tcp_accept_incoming_migration(void *opaque) goto out; } - vm_stop(0); /* just in case */ ret = qemu_loadvm_state(f); if (ret < 0) { fprintf(stderr, "load of migration failed\n"); @@ -168,8 +167,6 @@ static void tcp_accept_incoming_migration(void *opaque) qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL); close(s); - vm_start(); - out_fopen: qemu_fclose(f); out: diff --git a/qemu/migration.c b/qemu/migration.c index e6c8b16a..ee64d410 100644 --- a/qemu/migration.c +++ b/qemu/migration.c @@ -266,6 +266,7 @@ void migrate_fd_put_ready(void *opaque) dprintf("done iterating\n"); vm_stop(0); + qemu_aio_flush(); bdrv_flush_all(); if ((qemu_savevm_state_complete(s->file)) < 0) { if (old_vm_running) { diff --git a/qemu/monitor.c b/qemu/monitor.c index b1bdbdb2..e3028352 100644 --- a/qemu/monitor.c +++ b/qemu/monitor.c @@ -1185,28 +1185,34 @@ static void do_ioport_read(Monitor *mon, int count, int format, int size, suffix, addr, size * 2, val); } -/* boot_set handler */ -static QEMUBootSetHandler *qemu_boot_set_handler = NULL; -static void *boot_opaque; - -void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque) +static void do_ioport_write(Monitor *mon, int count, int format, int size, + int addr, int val) { - qemu_boot_set_handler = func; - boot_opaque = opaque; + addr &= IOPORTS_MASK; + + switch (size) { + default: + case 1: + cpu_outb(NULL, addr, val); + break; + case 2: + cpu_outw(NULL, addr, val); + break; + case 4: + cpu_outl(NULL, addr, val); + break; + } } static void do_boot_set(Monitor *mon, const char *bootdevice) { int res; - if (qemu_boot_set_handler) { - res = qemu_boot_set_handler(boot_opaque, bootdevice); - if (res == 0) - monitor_printf(mon, "boot device list now set to %s\n", - bootdevice); - else - monitor_printf(mon, "setting boot device list failed with " - "error %i\n", res); + res = qemu_boot_set(bootdevice); + if (res == 0) { + monitor_printf(mon, "boot device list now set to %s\n", bootdevice); + } else if (res > 0) { + monitor_printf(mon, "setting boot device list failed\n"); } else { monitor_printf(mon, "no function defined to set boot device list for " "this architecture\n"); diff --git a/qemu/net.c b/qemu/net.c index b407c453..0054b1ef 100644 --- a/qemu/net.c +++ b/qemu/net.c @@ -783,8 +783,8 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model, const char *vsmbserver) { /* default settings according to historic slirp */ - struct in_addr net = { .s_addr = htonl(0x0a000000) }; /* 10.0.0.0 */ - struct in_addr mask = { .s_addr = htonl(0xff000000) }; /* 255.0.0.0 */ + struct in_addr net = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */ + struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */ struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */ struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */ struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */ @@ -2429,7 +2429,7 @@ int net_client_init(Monitor *mon, const char *device, const char *p) } if (!strcmp(device, "nic")) { static const char * const nic_params[] = { - "vlan", "name", "macaddr", "model", "addr", "vectors", NULL + "vlan", "name", "macaddr", "model", "addr", "id", "vectors", NULL }; NICInfo *nd; uint8_t *macaddr; @@ -2467,6 +2467,9 @@ int net_client_init(Monitor *mon, const char *device, const char *p) if (get_param_value(buf, sizeof(buf), "addr", p)) { nd->devaddr = strdup(buf); } + if (get_param_value(buf, sizeof(buf), "id", p)) { + nd->id = strdup(buf); + } nd->nvectors = NIC_NVECTORS_UNSPECIFIED; if (get_param_value(buf, sizeof(buf), "vectors", p)) { char *endptr; diff --git a/qemu/net.h b/qemu/net.h index 6026e103..188fa395 100644 --- a/qemu/net.h +++ b/qemu/net.h @@ -95,6 +95,7 @@ struct NICInfo { const char *model; const char *name; const char *devaddr; + const char *id; VLANState *vlan; VLANClientState *vc; void *private; diff --git a/qemu/pc-bios/bios-pq/0013_fix-non-acpi-timer-interrupt-routing.patch b/qemu/pc-bios/bios-pq/0013_fix-non-acpi-timer-interrupt-routing.patch index c9d74e83..80e7716c 100644 --- a/qemu/pc-bios/bios-pq/0013_fix-non-acpi-timer-interrupt-routing.patch +++ b/qemu/pc-bios/bios-pq/0013_fix-non-acpi-timer-interrupt-routing.patch @@ -1,30 +1,49 @@ -Fix non-ACPI Timer Interrupt Routing (Beth Kon) +From c09142004a409bf27070939f470c5e0b37595a5a Mon Sep 17 00:00:00 2001 +From: Beth Kon +Date: Fri, 19 Jun 2009 14:22:00 -0400 +Subject: [PATCH] Fix non-ACPI Timer Interrupt Routing - v3 Replicate ACPI irq0->inti2 override in mp table for non-acpi case. v1 -> v2 adds comment suggested by Ryan. +v2 -> v3 clarifies comment and corrects entry count Signed-off-by: Beth Kon Signed-off-by: Anthony Liguori +--- + bios/rombios32.c | 14 ++++++++++++++ + 1 files changed, 14 insertions(+), 0 deletions(-) diff --git a/bios/rombios32.c b/bios/rombios32.c -index 7be4216..dc7b5f3 100644 +index 1a1ed64..d789e20 100644 --- a/bios/rombios32.c +++ b/bios/rombios32.c -@@ -1168,6 +1168,12 @@ static void mptable_init(void) +@@ -1124,7 +1124,11 @@ static void mptable_init(void) + putstr(&q, "0.1 "); /* vendor id */ + putle32(&q, 0); /* OEM table ptr */ + putle16(&q, 0); /* OEM table size */ ++#ifdef BX_QEMU ++ putle16(&q, smp_cpus + 17); /* entry count */ ++#else + putle16(&q, smp_cpus + 18); /* entry count */ ++#endif + putle32(&q, 0xfee00000); /* local APIC addr */ + putle16(&q, 0); /* ext table length */ + putb(&q, 0); /* ext table checksum */ +@@ -1166,6 +1170,12 @@ static void mptable_init(void) /* irqs */ for(i = 0; i < 16; i++) { +#ifdef BX_QEMU -+ /* One entry per ioapic input. Input 2 is covered by -+ irq0->inti2 override (i == 0). irq 2 is unused */ ++ /* One entry per ioapic interrupt destination. Destination 2 is covered ++ by irq0->inti2 override (i == 0). Source IRQ 2 is unused */ + if (i == 2) + continue; -+#endif ++#endif putb(&q, 3); /* entry type = I/O interrupt */ putb(&q, 0); /* interrupt type = vectored interrupt */ putb(&q, 0); /* flags: po=0, el=0 */ -@@ -1175,7 +1181,11 @@ static void mptable_init(void) +@@ -1173,7 +1183,11 @@ static void mptable_init(void) putb(&q, 0); /* source bus ID = ISA */ putb(&q, i); /* source bus IRQ */ putb(&q, ioapic_id); /* dest I/O APIC ID */ @@ -32,7 +51,10 @@ index 7be4216..dc7b5f3 100644 + putb(&q, i == 0 ? 2 : i); /* dest I/O APIC interrupt in */ +#else putb(&q, i); /* dest I/O APIC interrupt in */ -+#endif ++#endif } /* patch length */ len = q - mp_config_table; +-- +1.6.2.5 + diff --git a/qemu/pc-bios/bios-pq/0017-bochs-bios-Move-QEMU_CFG-constants-to-rombios.h.patch b/qemu/pc-bios/bios-pq/0017-bochs-bios-Move-QEMU_CFG-constants-to-rombios.h.patch new file mode 100644 index 00000000..f6a1788a --- /dev/null +++ b/qemu/pc-bios/bios-pq/0017-bochs-bios-Move-QEMU_CFG-constants-to-rombios.h.patch @@ -0,0 +1,59 @@ +From f371c480cb93f3516f34af5e3a4524ee6ba43c24 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka +Date: Thu, 2 Jul 2009 00:11:38 +0200 +Subject: [PATCH 1/2] bochs-bios: Move QEMU_CFG constants to rombios.h + +We will need them outside of rombios32.c. + +Signed-off-by: Jan Kiszka +Signed-off-by: Anthony Liguori +--- + bios/rombios.h | 10 ++++++++++ + bios/rombios32.c | 10 ---------- + 2 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/bios/rombios.h b/bios/rombios.h +index 6f9cbb1..59ce19d 100644 +--- a/bios/rombios.h ++++ b/bios/rombios.h +@@ -58,6 +58,16 @@ + #define SMB_IO_BASE 0xb100 + #define SMP_MSR_ADDR 0x0510 + ++#define QEMU_CFG_CTL_PORT 0x510 ++#define QEMU_CFG_DATA_PORT 0x511 ++#define QEMU_CFG_SIGNATURE 0x00 ++#define QEMU_CFG_ID 0x01 ++#define QEMU_CFG_UUID 0x02 ++#define QEMU_CFG_NUMA 0x0d ++#define QEMU_CFG_ARCH_LOCAL 0x8000 ++#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0) ++#define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1) ++ + // Define the application NAME + #if defined(BX_QEMU) + # define BX_APPNAME "QEMU" +diff --git a/bios/rombios32.c b/bios/rombios32.c +index f861f81..3fe4e48 100644 +--- a/bios/rombios32.c ++++ b/bios/rombios32.c +@@ -468,16 +468,6 @@ void wrmsr_smp(uint32_t index, uint64_t val) + } + + #ifdef BX_QEMU +-#define QEMU_CFG_CTL_PORT 0x510 +-#define QEMU_CFG_DATA_PORT 0x511 +-#define QEMU_CFG_SIGNATURE 0x00 +-#define QEMU_CFG_ID 0x01 +-#define QEMU_CFG_UUID 0x02 +-#define QEMU_CFG_NUMA 0x0D +-#define QEMU_CFG_ARCH_LOCAL 0x8000 +-#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0) +-#define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1) +- + int qemu_cfg_port; + + void qemu_cfg_select(int f) +-- +1.6.2.5 + diff --git a/qemu/pc-bios/bios-pq/0018-bochs-bios-Make-boot-prompt-optional.patch b/qemu/pc-bios/bios-pq/0018-bochs-bios-Make-boot-prompt-optional.patch new file mode 100644 index 00000000..cda97572 --- /dev/null +++ b/qemu/pc-bios/bios-pq/0018-bochs-bios-Make-boot-prompt-optional.patch @@ -0,0 +1,68 @@ +From fff8ffe1c92474ee58ebd6da82fede0ab7929214 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka +Date: Thu, 2 Jul 2009 00:11:44 +0200 +Subject: [PATCH 2/2] bochs-bios: Make boot prompt optional + +Check via QEMU's firmware configuration interface if the boot prompt +should be given. This allows to disable the prompt with its several +seconds long delay, speeding up the common boot case. + +Signed-off-by: Jan Kiszka +Signed-off-by: Anthony Liguori +--- + bios/rombios.c | 19 +++++++++++++++++++ + bios/rombios.h | 1 + + 2 files changed, 20 insertions(+), 0 deletions(-) + +diff --git a/bios/rombios.c b/bios/rombios.c +index 0f13b53..560e6d5 100644 +--- a/bios/rombios.c ++++ b/bios/rombios.c +@@ -2015,6 +2015,21 @@ Bit16u i; ipl_entry_t *e; + } + + #if BX_ELTORITO_BOOT ++#ifdef BX_QEMU ++int ++qemu_cfg_probe_bootkey() ++{ ++ outw(QEMU_CFG_CTL_PORT, QEMU_CFG_SIGNATURE); ++ if (inb(QEMU_CFG_DATA_PORT) != 'Q' || ++ inb(QEMU_CFG_DATA_PORT) != 'E' || ++ inb(QEMU_CFG_DATA_PORT) != 'M' || ++ inb(QEMU_CFG_DATA_PORT) != 'U') return 1; ++ ++ outw(QEMU_CFG_CTL_PORT, QEMU_CFG_BOOT_MENU); ++ return inb(QEMU_CFG_DATA_PORT); ++} ++#endif // BX_QEMU ++ + void + interactive_bootkey() + { +@@ -2026,6 +2041,10 @@ interactive_bootkey() + Bit16u ss = get_SS(); + Bit16u valid_choice = 0; + ++#ifdef BX_QEMU ++ if (!qemu_cfg_probe_bootkey()) return; ++#endif ++ + while (check_for_keystroke()) + get_keystroke(); + +diff --git a/bios/rombios.h b/bios/rombios.h +index 59ce19d..8ece2ee 100644 +--- a/bios/rombios.h ++++ b/bios/rombios.h +@@ -64,6 +64,7 @@ + #define QEMU_CFG_ID 0x01 + #define QEMU_CFG_UUID 0x02 + #define QEMU_CFG_NUMA 0x0d ++#define QEMU_CFG_BOOT_MENU 0x0e + #define QEMU_CFG_ARCH_LOCAL 0x8000 + #define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0) + #define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1) +-- +1.6.2.5 + diff --git a/qemu/pc-bios/bios-pq/0019-bios-fix-multiple-calls.patch b/qemu/pc-bios/bios-pq/0019-bios-fix-multiple-calls.patch new file mode 100644 index 00000000..cfa4c130 --- /dev/null +++ b/qemu/pc-bios/bios-pq/0019-bios-fix-multiple-calls.patch @@ -0,0 +1,35 @@ +bios: Fix multiple calls into smbios_load_ex + +We're marking the used entry bitmap in smbios_load_external() for each +type we check, regardless of whether we loaded anything. This makes +subsequent calls behave as if we've already loaded the tables from qemu +and can result in missing tables (ex. multiple type4 entries on an SMP +guest). Only mark the bitmap if we actually load something. + +Signed-off-by: Alex Williamson +Signed-off-by: Anthony Liguori + +diff --git a/bios/rombios32.c b/bios/rombios32.c +index f861f81..c869798 100644 +--- a/bios/rombios32.c ++++ b/bios/rombios32.c +@@ -2554,13 +2554,14 @@ smbios_load_external(int type, char **p, unsigned *nr_structs, + *max_struct_size = *p - (char *)header; + } + +- /* Mark that we've reported on this type */ +- used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f)); ++ if (start != *p) { ++ /* Mark that we've reported on this type */ ++ used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f)); ++ return 1; ++ } + +- return (start != *p); +-#else /* !BX_QEMU */ ++#endif /* !BX_QEMU */ + return 0; +-#endif + } + + void smbios_init(void) diff --git a/qemu/pc-bios/bios-pq/series b/qemu/pc-bios/bios-pq/series index c7c7f67e..695b148a 100644 --- a/qemu/pc-bios/bios-pq/series +++ b/qemu/pc-bios/bios-pq/series @@ -14,3 +14,6 @@ 0014_add-srat-acpi-table-support.patch 0015_enable-power-button-even-generation.patch 0016-use-correct-mask-to-size-pci-option-rom-bar.patch +0017-bochs-bios-Move-QEMU_CFG-constants-to-rombios.h.patch +0018-bochs-bios-Make-boot-prompt-optional.patch +0019-bios-fix-multiple-calls.patch diff --git a/qemu/pc-bios/bios.bin b/qemu/pc-bios/bios.bin index 6c8bc9f6..e4323c05 100644 Binary files a/qemu/pc-bios/bios.bin and b/qemu/pc-bios/bios.bin differ diff --git a/qemu/pc-bios/optionrom/Makefile b/qemu/pc-bios/optionrom/Makefile index 7f987d89..88fbc4c9 100644 --- a/qemu/pc-bios/optionrom/Makefile +++ b/qemu/pc-bios/optionrom/Makefile @@ -3,7 +3,6 @@ all: build-all include ../../config-host.mak VPATH=$(SRC_PATH)/pc-bios/optionrom -OBJCOPY=objcopy # from kernel sources - scripts/Kbuild.include # try-run @@ -35,11 +34,13 @@ build-all: multiboot.bin $(CC) $(CFLAGS) -o $@ -c $< %.img: %.o - $(LD) --oformat binary -Ttext 0 -o $@ $< + $(LD) -Ttext 0 -e _start -s -o $@ $< -%.bin: %.img +%.raw: %.img + $(OBJCOPY) -O binary -j .text $< $@ + +%.bin: %.raw $(SRC_PATH)/pc-bios/optionrom/signrom.sh $< $@ - cp $@ $(SRC_PATH)/pc-bios/ clean: $(RM) *.o *.img *.bin *~ diff --git a/qemu/pc-bios/optionrom/multiboot.S b/qemu/pc-bios/optionrom/multiboot.S index e04cd033..93beb51b 100644 --- a/qemu/pc-bios/optionrom/multiboot.S +++ b/qemu/pc-bios/optionrom/multiboot.S @@ -12,8 +12,7 @@ * 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, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * along with this program; if not, see . * * Copyright Novell Inc, 2009 * Authors: Alexander Graf diff --git a/qemu/pc-bios/optionrom/signrom.sh b/qemu/pc-bios/optionrom/signrom.sh index 4273d1f0..263ba5ff 100644 --- a/qemu/pc-bios/optionrom/signrom.sh +++ b/qemu/pc-bios/optionrom/signrom.sh @@ -13,8 +13,7 @@ # 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, write to the Free Software -# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# along with this program; if not, see . # # Copyright Novell Inc, 2009 # Authors: Alexander Graf diff --git a/qemu/qemu-io.c b/qemu/qemu-io.c index 566ca79f..6c35a071 100644 --- a/qemu/qemu-io.c +++ b/qemu/qemu-io.c @@ -98,6 +98,57 @@ print_report(const char *op, struct timeval *t, int64_t offset, } } +/* + * Parse multiple length statements for vectored I/O, and construct an I/O + * vector matching it. + */ +static void * +create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern) +{ + size_t *sizes = calloc(nr_iov, sizeof(size_t)); + size_t count = 0; + void *buf, *p; + int i; + + for (i = 0; i < nr_iov; i++) { + char *arg = argv[i]; + long long len; + + len = cvtnum(arg); + if (len < 0) { + printf("non-numeric length argument -- %s\n", arg); + return NULL; + } + + /* should be SIZE_T_MAX, but that doesn't exist */ + if (len > UINT_MAX) { + printf("too large length argument -- %s\n", arg); + return NULL; + } + + if (len & 0x1ff) { + printf("length argument %lld is not sector aligned\n", + len); + return NULL; + } + + sizes[i] = len; + count += len; + } + + qemu_iovec_init(qiov, nr_iov); + + buf = p = qemu_io_alloc(count, pattern); + + for (i = 0; i < nr_iov; i++) { + qemu_iovec_add(qiov, p, sizes[i]); + p += sizes[i]; + } + + free(sizes); + return buf; +} + static int do_read(char *buf, int64_t offset, int count, int *total) { int ret; @@ -136,6 +187,22 @@ static int do_pwrite(char *buf, int64_t offset, int count, int *total) return 1; } +static int do_load_vmstate(char *buf, int64_t offset, int count, int *total) +{ + *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count); + if (*total < 0) + return *total; + return 1; +} + +static int do_save_vmstate(char *buf, int64_t offset, int count, int *total) +{ + *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count); + if (*total < 0) + return *total; + return 1; +} + #define NOT_DONE 0x7fffffff static void aio_rw_done(void *opaque, int ret) { @@ -191,6 +258,7 @@ read_help(void) "\n" " Reads a segment of the currently open file, optionally dumping it to the\n" " standard output stream (with -v option) for subsequent inspection.\n" +" -b, -- read from the VM state rather than the virtual disk\n" " -C, -- report statistics in a machine parsable format\n" " -l, -- length for pattern verification (only with -P)\n" " -p, -- use bdrv_pread to read the file\n" @@ -206,7 +274,7 @@ read_f(int argc, char **argv) { struct timeval t1, t2; int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; - int Pflag = 0, sflag = 0, lflag = 0; + int Pflag = 0, sflag = 0, lflag = 0, bflag = 0; int c, cnt; char *buf; int64_t offset; @@ -215,8 +283,11 @@ read_f(int argc, char **argv) int total = 0; int pattern = 0, pattern_offset = 0, pattern_count = 0; - while ((c = getopt(argc, argv, "Cl:pP:qs:v")) != EOF) { + while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) { switch (c) { + case 'b': + bflag = 1; + break; case 'C': Cflag = 1; break; @@ -257,6 +328,11 @@ read_f(int argc, char **argv) if (optind != argc - 2) return command_usage(&read_cmd); + if (bflag && pflag) { + printf("-b and -p cannot be specified at the same time\n"); + return 0; + } + offset = cvtnum(argv[optind]); if (offset < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); @@ -301,13 +377,15 @@ read_f(int argc, char **argv) gettimeofday(&t1, NULL); if (pflag) cnt = do_pread(buf, offset, count, &total); + else if (bflag) + cnt = do_load_vmstate(buf, offset, count, &total); else cnt = do_read(buf, offset, count, &total); gettimeofday(&t2, NULL); if (cnt < 0) { printf("read failed: %s\n", strerror(-cnt)); - return 0; + goto out; } if (Pflag) { @@ -322,7 +400,7 @@ read_f(int argc, char **argv) } if (qflag) - return 0; + goto out; if (vflag) dump_buffer(buf, offset, count); @@ -331,6 +409,7 @@ read_f(int argc, char **argv) t2 = tsub(t2, t1); print_report("read", &t2, offset, count, total, cnt, Cflag); +out: qemu_io_free(buf); return 0; @@ -342,7 +421,7 @@ static const cmdinfo_t read_cmd = { .cfunc = read_f, .argmin = 2, .argmax = -1, - .args = "[-aCpqv] [-P pattern [-s off] [-l len]] off len", + .args = "[-abCpqv] [-P pattern [-s off] [-l len]] off len", .oneline = "reads a number of bytes at a specified offset", .help = read_help, }; @@ -375,10 +454,10 @@ readv_f(int argc, char **argv) struct timeval t1, t2; int Cflag = 0, qflag = 0, vflag = 0; int c, cnt; - char *buf, *p; + char *buf; int64_t offset; - int count = 0, total; - int nr_iov, i; + int total; + int nr_iov; QEMUIOVector qiov; int pattern = 0; int Pflag = 0; @@ -420,40 +499,8 @@ readv_f(int argc, char **argv) return 0; } - if (count & 0x1ff) { - printf("count %d is not sector aligned\n", - count); - return 0; - } - - for (i = optind; i < argc; i++) { - size_t len; - - len = cvtnum(argv[i]); - if (len < 0) { - printf("non-numeric length argument -- %s\n", argv[i]); - return 0; - } - count += len; - } - nr_iov = argc - optind; - qemu_iovec_init(&qiov, nr_iov); - buf = p = qemu_io_alloc(count, 0xab); - for (i = 0; i < nr_iov; i++) { - size_t len; - - len = cvtnum(argv[optind]); - if (len < 0) { - printf("non-numeric length argument -- %s\n", - argv[optind]); - return 0; - } - - qemu_iovec_add(&qiov, p, len); - p += len; - optind++; - } + buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab); gettimeofday(&t1, NULL); cnt = do_aio_readv(&qiov, offset, &total); @@ -461,22 +508,22 @@ readv_f(int argc, char **argv) if (cnt < 0) { printf("readv failed: %s\n", strerror(-cnt)); - return 0; + goto out; } if (Pflag) { - void* cmp_buf = malloc(count); - memset(cmp_buf, pattern, count); - if (memcmp(buf, cmp_buf, count)) { + void* cmp_buf = malloc(qiov.size); + memset(cmp_buf, pattern, qiov.size); + if (memcmp(buf, cmp_buf, qiov.size)) { printf("Pattern verification failed at offset %lld, " - "%d bytes\n", - (long long) offset, count); + "%zd bytes\n", + (long long) offset, qiov.size); } free(cmp_buf); } if (qflag) - return 0; + goto out; if (vflag) dump_buffer(buf, offset, qiov.size); @@ -485,8 +532,8 @@ readv_f(int argc, char **argv) t2 = tsub(t2, t1); print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); +out: qemu_io_free(buf); - return 0; } @@ -514,6 +561,7 @@ write_help(void) "\n" " Writes into a segment of the currently open file, using a buffer\n" " filled with a set pattern (0xcdcdcdcd).\n" +" -b, -- write to the VM state rather than the virtual disk\n" " -p, -- use bdrv_pwrite to write the file\n" " -P, -- use different pattern to fill file\n" " -C, -- report statistics in a machine parsable format\n" @@ -525,7 +573,7 @@ static int write_f(int argc, char **argv) { struct timeval t1, t2; - int Cflag = 0, pflag = 0, qflag = 0; + int Cflag = 0, pflag = 0, qflag = 0, bflag = 0; int c, cnt; char *buf; int64_t offset; @@ -534,8 +582,11 @@ write_f(int argc, char **argv) int total = 0; int pattern = 0xcd; - while ((c = getopt(argc, argv, "CpP:q")) != EOF) { + while ((c = getopt(argc, argv, "bCpP:q")) != EOF) { switch (c) { + case 'b': + bflag = 1; + break; case 'C': Cflag = 1; break; @@ -556,6 +607,11 @@ write_f(int argc, char **argv) if (optind != argc - 2) return command_usage(&write_cmd); + if (bflag && pflag) { + printf("-b and -p cannot be specified at the same time\n"); + return 0; + } + offset = cvtnum(argv[optind]); if (offset < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); @@ -588,22 +644,25 @@ write_f(int argc, char **argv) gettimeofday(&t1, NULL); if (pflag) cnt = do_pwrite(buf, offset, count, &total); + else if (bflag) + cnt = do_save_vmstate(buf, offset, count, &total); else cnt = do_write(buf, offset, count, &total); gettimeofday(&t2, NULL); if (cnt < 0) { printf("write failed: %s\n", strerror(-cnt)); - return 0; + goto out; } if (qflag) - return 0; + goto out; /* Finally, report back -- -C gives a parsable format */ t2 = tsub(t2, t1); print_report("wrote", &t2, offset, count, total, cnt, Cflag); +out: qemu_io_free(buf); return 0; @@ -615,7 +674,7 @@ static const cmdinfo_t write_cmd = { .cfunc = write_f, .argmin = 2, .argmax = -1, - .args = "[-aCpq] [-P pattern ] off len", + .args = "[-abCpq] [-P pattern ] off len", .oneline = "writes a number of bytes at a specified offset", .help = write_help, }; @@ -646,10 +705,10 @@ writev_f(int argc, char **argv) struct timeval t1, t2; int Cflag = 0, qflag = 0; int c, cnt; - char *buf, *p; + char *buf; int64_t offset; - int count = 0, total; - int nr_iov, i; + int total; + int nr_iov; int pattern = 0xcd; QEMUIOVector qiov; @@ -685,41 +744,8 @@ writev_f(int argc, char **argv) return 0; } - if (count & 0x1ff) { - printf("count %d is not sector aligned\n", - count); - return 0; - } - - - for (i = optind; i < argc; i++) { - size_t len; - - len = cvtnum(argv[optind]); - if (len < 0) { - printf("non-numeric length argument -- %s\n", argv[i]); - return 0; - } - count += len; - } - nr_iov = argc - optind; - qemu_iovec_init(&qiov, nr_iov); - buf = p = qemu_io_alloc(count, pattern); - for (i = 0; i < nr_iov; i++) { - size_t len; - - len = cvtnum(argv[optind]); - if (len < 0) { - printf("non-numeric length argument -- %s\n", - argv[optind]); - return 0; - } - - qemu_iovec_add(&qiov, p, len); - p += len; - optind++; - } + buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern); gettimeofday(&t1, NULL); cnt = do_aio_writev(&qiov, offset, &total); @@ -727,18 +753,17 @@ writev_f(int argc, char **argv) if (cnt < 0) { printf("writev failed: %s\n", strerror(-cnt)); - return 0; + goto out; } if (qflag) - return 0; + goto out; /* Finally, report back -- -C gives a parsable format */ t2 = tsub(t2, t1); print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); - +out: qemu_io_free(buf); - return 0; } @@ -769,26 +794,24 @@ aio_write_done(void *opaque, int ret) { struct aio_ctx *ctx = opaque; struct timeval t2; - int total; - int cnt = 1; gettimeofday(&t2, NULL); - total = ctx->qiov.size; if (ret < 0) { printf("aio_write failed: %s\n", strerror(-ret)); - return; + goto out; } - if (ctx->qflag) - return; + if (ctx->qflag) { + goto out; + } /* Finally, report back -- -C gives a parsable format */ t2 = tsub(t2, ctx->t1); - print_report("wrote", &t2, ctx->offset, ctx->qiov.size, total, cnt, - ctx->Cflag); - + print_report("wrote", &t2, ctx->offset, ctx->qiov.size, + ctx->qiov.size, 1, ctx->Cflag); +out: qemu_io_free(ctx->buf); free(ctx); } @@ -800,44 +823,41 @@ aio_read_done(void *opaque, int ret) { struct aio_ctx *ctx = opaque; struct timeval t2; - int total; - int cnt = 1; gettimeofday(&t2, NULL); - total = ctx->qiov.size; - if (ret < 0) { printf("readv failed: %s\n", strerror(-ret)); - return; + goto out; } if (ctx->Pflag) { - void *cmp_buf = malloc(total); + void *cmp_buf = malloc(ctx->qiov.size); - memset(cmp_buf, ctx->pattern, total); - if (memcmp(ctx->buf, cmp_buf, total)) { + memset(cmp_buf, ctx->pattern, ctx->qiov.size); + if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) { printf("Pattern verification failed at offset %lld, " - "%d bytes\n", - (long long) ctx->offset, total); + "%zd bytes\n", + (long long) ctx->offset, ctx->qiov.size); } free(cmp_buf); } - if (ctx->qflag) - return; + if (ctx->qflag) { + goto out; + } - if (ctx->vflag) - dump_buffer(ctx->buf, ctx->offset, total); + if (ctx->vflag) { + dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size); + } /* Finally, report back -- -C gives a parsable format */ t2 = tsub(t2, ctx->t1); - print_report("read", &t2, ctx->offset, ctx->qiov.size, total, cnt, - ctx->Cflag); - + print_report("read", &t2, ctx->offset, ctx->qiov.size, + ctx->qiov.size, 1, ctx->Cflag); +out: qemu_io_free(ctx->buf); free(ctx); - } static void @@ -864,14 +884,10 @@ aio_read_help(void) static int aio_read_f(int argc, char **argv) { - char *p; - int count = 0; - int nr_iov, i, c; + int nr_iov, c; struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); BlockDriverAIOCB *acb; - ctx->pattern = 0xcd; - while ((c = getopt(argc, argv, "CP:qv")) != EOF) { switch (c) { case 'C': @@ -888,17 +904,20 @@ aio_read_f(int argc, char **argv) ctx->vflag = 1; break; default: + free(ctx); return command_usage(&aio_read_cmd); } } - if (optind > argc - 2) + if (optind > argc - 2) { + free(ctx); return command_usage(&aio_read_cmd); - + } ctx->offset = cvtnum(argv[optind]); if (ctx->offset < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); + free(ctx); return 0; } optind++; @@ -906,49 +925,21 @@ aio_read_f(int argc, char **argv) if (ctx->offset & 0x1ff) { printf("offset %lld is not sector aligned\n", (long long)ctx->offset); + free(ctx); return 0; } - if (count & 0x1ff) { - printf("count %d is not sector aligned\n", - count); - return 0; - } - - for (i = optind; i < argc; i++) { - size_t len; - - len = cvtnum(argv[i]); - if (len < 0) { - printf("non-numeric length argument -- %s\n", argv[i]); - return 0; - } - count += len; - } - nr_iov = argc - optind; - qemu_iovec_init(&ctx->qiov, nr_iov); - ctx->buf = p = qemu_io_alloc(count, 0xab); - for (i = 0; i < nr_iov; i++) { - size_t len; - - len = cvtnum(argv[optind]); - if (len < 0) { - printf("non-numeric length argument -- %s\n", - argv[optind]); - return 0; - } - - qemu_iovec_add(&ctx->qiov, p, len); - p += len; - optind++; - } + ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab); gettimeofday(&ctx->t1, NULL); acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, ctx->qiov.size >> 9, aio_read_done, ctx); - if (!acb) + if (!acb) { + free(ctx->buf); + free(ctx); return -EIO; + } return 0; } @@ -990,9 +981,7 @@ aio_write_help(void) static int aio_write_f(int argc, char **argv) { - char *p; - int count = 0; - int nr_iov, i, c; + int nr_iov, c; int pattern = 0xcd; struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx)); BlockDriverAIOCB *acb; @@ -1009,16 +998,20 @@ aio_write_f(int argc, char **argv) pattern = atoi(optarg); break; default: + free(ctx); return command_usage(&aio_write_cmd); } } - if (optind > argc - 2) + if (optind > argc - 2) { + free(ctx); return command_usage(&aio_write_cmd); + } ctx->offset = cvtnum(argv[optind]); if (ctx->offset < 0) { printf("non-numeric length argument -- %s\n", argv[optind]); + free(ctx); return 0; } optind++; @@ -1026,50 +1019,21 @@ aio_write_f(int argc, char **argv) if (ctx->offset & 0x1ff) { printf("offset %lld is not sector aligned\n", (long long)ctx->offset); + free(ctx); return 0; } - if (count & 0x1ff) { - printf("count %d is not sector aligned\n", - count); - return 0; - } - - - for (i = optind; i < argc; i++) { - size_t len; - - len = cvtnum(argv[optind]); - if (len < 0) { - printf("non-numeric length argument -- %s\n", argv[i]); - return 0; - } - count += len; - } - nr_iov = argc - optind; - qemu_iovec_init(&ctx->qiov, nr_iov); - ctx->buf = p = qemu_io_alloc(count, pattern); - for (i = 0; i < nr_iov; i++) { - size_t len; - - len = cvtnum(argv[optind]); - if (len < 0) { - printf("non-numeric length argument -- %s\n", - argv[optind]); - return 0; - } - - qemu_iovec_add(&ctx->qiov, p, len); - p += len; - optind++; - } + ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern); gettimeofday(&ctx->t1, NULL); acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, ctx->qiov.size >> 9, aio_write_done, ctx); - if (!acb) + if (!acb) { + free(ctx->buf); + free(ctx); return -EIO; + } return 0; } @@ -1262,7 +1226,7 @@ static const cmdinfo_t close_cmd = { .oneline = "close the current open file", }; -static int openfile(char *name, int flags) +static int openfile(char *name, int flags, int growable) { if (bs) { fprintf(stderr, "file open already, try 'help close'\n"); @@ -1273,12 +1237,19 @@ static int openfile(char *name, int flags) if (!bs) return 1; + if (growable) { + flags |= BDRV_O_FILE; + } + if (bdrv_open(bs, name, flags) == -1) { fprintf(stderr, "%s: can't open device %s\n", progname, name); bs = NULL; return 1; } + if (growable) { + bs->growable = 1; + } return 0; } @@ -1297,6 +1268,7 @@ open_help(void) " -r, -- open file read-only\n" " -s, -- use snapshot file\n" " -n, -- disable host cache\n" +" -g, -- allow file to grow (only applies to protocols)" "\n"); } @@ -1307,9 +1279,10 @@ open_f(int argc, char **argv) { int flags = 0; int readonly = 0; + int growable = 0; int c; - while ((c = getopt(argc, argv, "snCr")) != EOF) { + while ((c = getopt(argc, argv, "snCrg")) != EOF) { switch (c) { case 's': flags |= BDRV_O_SNAPSHOT; @@ -1323,6 +1296,9 @@ open_f(int argc, char **argv) case 'r': readonly = 1; break; + case 'g': + growable = 1; + break; default: return command_usage(&open_cmd); } @@ -1336,7 +1312,7 @@ open_f(int argc, char **argv) if (optind != argc - 1) return command_usage(&open_cmd); - return openfile(argv[optind], flags); + return openfile(argv[optind], flags, growable); } static const cmdinfo_t open_cmd = { @@ -1385,6 +1361,7 @@ static void usage(const char *name) " -r, --read-only export read-only\n" " -s, --snapshot use snapshot file\n" " -n, --nocache disable host cache\n" +" -g, --growable allow file to grow (only applies to protocols)\n" " -m, --misalign misalign allocations for O_DIRECT\n" " -h, --help display this help and exit\n" " -V, --version output version information and exit\n" @@ -1396,7 +1373,8 @@ static void usage(const char *name) int main(int argc, char **argv) { int readonly = 0; - const char *sopt = "hVc:Crsnm"; + int growable = 0; + const char *sopt = "hVc:Crsnmg"; struct option lopt[] = { { "help", 0, 0, 'h' }, { "version", 0, 0, 'V' }, @@ -1407,6 +1385,7 @@ int main(int argc, char **argv) { "snapshot", 0, 0, 's' }, { "nocache", 0, 0, 'n' }, { "misalign", 0, 0, 'm' }, + { "growable", 0, 0, 'g' }, { NULL, 0, 0, 0 } }; int c; @@ -1435,6 +1414,9 @@ int main(int argc, char **argv) case 'm': misalign = 1; break; + case 'g': + growable = 1; + break; case 'V': printf("%s version %s\n", progname, VERSION); exit(0); @@ -1482,7 +1464,7 @@ int main(int argc, char **argv) flags |= BDRV_O_RDWR; if ((argc - optind) == 1) - openfile(argv[optind], flags); + openfile(argv[optind], flags, growable); command_loop(); /* diff --git a/qemu/qemu-monitor.hx b/qemu/qemu-monitor.hx index 62edbcde..70e24758 100644 --- a/qemu/qemu-monitor.hx +++ b/qemu/qemu-monitor.hx @@ -306,6 +306,11 @@ STEXI Read I/O port. ETEXI + { "o", "/ii", do_ioport_write, + "/fmt addr value", "I/O port write" }, +STEXI +Write to I/O port. +ETEXI { "sendkey", "si?", do_sendkey, "keys [hold_ms]", "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)" }, diff --git a/qemu/qemu-options.hx b/qemu/qemu-options.hx index 3f699659..a58287cb 100644 --- a/qemu/qemu-options.hx +++ b/qemu/qemu-options.hx @@ -219,11 +219,30 @@ Use 'file' as a parallel flash image. ETEXI DEF("boot", HAS_ARG, QEMU_OPTION_boot, - "-boot [a|c|d|n] boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n") + "-boot [order=drives][,once=drives][,menu=on|off]\n" + " 'drives': floppy (a), hard disk (c), CD-ROM (d), network (n)\n") STEXI -@item -boot [a|c|d|n] -Boot on floppy (a), hard disk (c), CD-ROM (d), or Etherboot (n). Hard disk boot -is the default. +@item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off] + +Specify boot order @var{drives} as a string of drive letters. Valid +drive letters depend on the target achitecture. The x86 PC uses: a, b +(floppy 1 and 2), c (first hard disk), d (first CD-ROM), n-p (Etherboot +from network adapter 1-4), hard disk boot is the default. To apply a +particular boot order only on the first startup, specify it via +@option{once}. + +Interactive boot menus/prompts can be enabled via @option{menu=on} as far +as firmware/BIOS supports them. The default is non-interactive boot. + +@example +# try to boot from network first, then from hard disk +qemu -boot order=nc +# boot from CD-ROM first, switch back to default order after reboot +qemu -boot once=d +@end example + +Note: The legacy format '-boot @var{drives}' is still supported but its +use is discouraged as it may be removed from future versions. ETEXI DEF("snapshot", 0, QEMU_OPTION_snapshot, diff --git a/qemu/savevm.c b/qemu/savevm.c index 4cdb55b8..dc32f945 100644 --- a/qemu/savevm.c +++ b/qemu/savevm.c @@ -338,46 +338,28 @@ QEMUFile *qemu_fopen(const char *filename, const char *mode) return NULL; } -typedef struct QEMUFileBdrv -{ - BlockDriverState *bs; - int64_t base_offset; -} QEMUFileBdrv; - static int block_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size) { - QEMUFileBdrv *s = opaque; - bdrv_put_buffer(s->bs, buf, s->base_offset + pos, size); + bdrv_save_vmstate(opaque, buf, pos, size); return size; } static int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) { - QEMUFileBdrv *s = opaque; - return bdrv_get_buffer(s->bs, buf, s->base_offset + pos, size); + return bdrv_load_vmstate(opaque, buf, pos, size); } static int bdrv_fclose(void *opaque) { - QEMUFileBdrv *s = opaque; - qemu_free(s); return 0; } -static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_writable) +static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable) { - QEMUFileBdrv *s; - - s = qemu_mallocz(sizeof(QEMUFileBdrv)); - - s->bs = bs; - s->base_offset = offset; - if (is_writable) - return qemu_fopen_ops(s, block_put_buffer, NULL, bdrv_fclose, NULL, NULL); - - return qemu_fopen_ops(s, NULL, block_get_buffer, bdrv_fclose, NULL, NULL); + return qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose, NULL, NULL); + return qemu_fopen_ops(bs, NULL, block_get_buffer, bdrv_fclose, NULL, NULL); } QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, @@ -575,7 +557,9 @@ int qemu_file_rate_limit(QEMUFile *f) size_t qemu_file_set_rate_limit(QEMUFile *f, size_t new_rate) { - if (f->set_rate_limit) + /* any failed or completed migration keeps its state to allow probing of + * migration data, but has no associated file anymore */ + if (f && f->set_rate_limit) return f->set_rate_limit(f->opaque, new_rate); return 0; @@ -1070,7 +1054,6 @@ void do_savevm(Monitor *mon, const char *name) BlockDriverState *bs, *bs1; QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1; int must_delete, ret, i; - BlockDriverInfo bdi1, *bdi = &bdi1; QEMUFile *f; int saved_vm_running; uint32_t vm_state_size; @@ -1120,14 +1103,8 @@ void do_savevm(Monitor *mon, const char *name) #endif sn->vm_clock_nsec = qemu_get_clock(vm_clock); - if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) { - monitor_printf(mon, "Device %s does not support VM state snapshots\n", - bdrv_get_device_name(bs)); - goto the_end; - } - /* save the VM state */ - f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1); + f = qemu_fopen_bdrv(bs, 1); if (!f) { monitor_printf(mon, "Could not open VM state file\n"); goto the_end; @@ -1171,7 +1148,6 @@ void do_savevm(Monitor *mon, const char *name) void do_loadvm(Monitor *mon, const char *name) { BlockDriverState *bs, *bs1; - BlockDriverInfo bdi1, *bdi = &bdi1; QEMUSnapshotInfo sn; QEMUFile *f; int i, ret; @@ -1219,19 +1195,13 @@ void do_loadvm(Monitor *mon, const char *name) } } - if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) { - monitor_printf(mon, "Device %s does not support VM state snapshots\n", - bdrv_get_device_name(bs)); - return; - } - /* Don't even try to load empty VM states */ ret = bdrv_snapshot_find(bs, &sn, name); if ((ret >= 0) && (sn.vm_state_size == 0)) goto the_end; /* restore the VM state */ - f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0); + f = qemu_fopen_bdrv(bs, 0); if (!f) { monitor_printf(mon, "Could not open VM state file\n"); goto the_end; diff --git a/qemu/softmmu_header.h b/qemu/softmmu_header.h index 6e9297d5..4202baac 100644 --- a/qemu/softmmu_header.h +++ b/qemu/softmmu_header.h @@ -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 . */ /* @@ -81,150 +80,6 @@ #define ADDR_READ addr_read #endif -#if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \ - (ACCESS_TYPE < NB_MMU_MODES) && defined(ASM_SOFTMMU) - -static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr) -{ - int res; - - asm volatile ("movl %1, %%edx\n" - "movl %1, %%eax\n" - "shrl %3, %%edx\n" - "andl %4, %%eax\n" - "andl %2, %%edx\n" - "leal %5(%%edx, %%ebp), %%edx\n" - "cmpl (%%edx), %%eax\n" - "movl %1, %%eax\n" - "je 1f\n" - "movl %6, %%edx\n" - "call %7\n" - "movl %%eax, %0\n" - "jmp 2f\n" - "1:\n" - "addl 12(%%edx), %%eax\n" -#if DATA_SIZE == 1 - "movzbl (%%eax), %0\n" -#elif DATA_SIZE == 2 - "movzwl (%%eax), %0\n" -#elif DATA_SIZE == 4 - "movl (%%eax), %0\n" -#else -#error unsupported size -#endif - "2:\n" - : "=r" (res) - : "r" (ptr), - "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), - "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), - "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)), - "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)), - "i" (CPU_MMU_INDEX), - "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX)) - : "%eax", "%ecx", "%edx", "memory", "cc"); - return res; -} - -#if DATA_SIZE <= 2 -static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr) -{ - int res; - - asm volatile ("movl %1, %%edx\n" - "movl %1, %%eax\n" - "shrl %3, %%edx\n" - "andl %4, %%eax\n" - "andl %2, %%edx\n" - "leal %5(%%edx, %%ebp), %%edx\n" - "cmpl (%%edx), %%eax\n" - "movl %1, %%eax\n" - "je 1f\n" - "movl %6, %%edx\n" - "call %7\n" -#if DATA_SIZE == 1 - "movsbl %%al, %0\n" -#elif DATA_SIZE == 2 - "movswl %%ax, %0\n" -#else -#error unsupported size -#endif - "jmp 2f\n" - "1:\n" - "addl 12(%%edx), %%eax\n" -#if DATA_SIZE == 1 - "movsbl (%%eax), %0\n" -#elif DATA_SIZE == 2 - "movswl (%%eax), %0\n" -#else -#error unsupported size -#endif - "2:\n" - : "=r" (res) - : "r" (ptr), - "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), - "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), - "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)), - "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)), - "i" (CPU_MMU_INDEX), - "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX)) - : "%eax", "%ecx", "%edx", "memory", "cc"); - return res; -} -#endif - -static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v) -{ - asm volatile ("movl %0, %%edx\n" - "movl %0, %%eax\n" - "shrl %3, %%edx\n" - "andl %4, %%eax\n" - "andl %2, %%edx\n" - "leal %5(%%edx, %%ebp), %%edx\n" - "cmpl (%%edx), %%eax\n" - "movl %0, %%eax\n" - "je 1f\n" -#if DATA_SIZE == 1 - "movzbl %b1, %%edx\n" -#elif DATA_SIZE == 2 - "movzwl %w1, %%edx\n" -#elif DATA_SIZE == 4 - "movl %1, %%edx\n" -#else -#error unsupported size -#endif - "movl %6, %%ecx\n" - "call %7\n" - "jmp 2f\n" - "1:\n" - "addl 8(%%edx), %%eax\n" -#if DATA_SIZE == 1 - "movb %b1, (%%eax)\n" -#elif DATA_SIZE == 2 - "movw %w1, (%%eax)\n" -#elif DATA_SIZE == 4 - "movl %1, (%%eax)\n" -#else -#error unsupported size -#endif - "2:\n" - : - : "r" (ptr), -#if DATA_SIZE == 1 - "q" (v), -#else - "r" (v), -#endif - "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), - "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), - "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)), - "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_write)), - "i" (CPU_MMU_INDEX), - "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX)) - : "%eax", "%ecx", "%edx", "memory", "cc"); -} - -#else - /* generic load/store macros */ #ifdef _MSC_VER DATA_TYPE glue(glue(my__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, @@ -316,8 +171,6 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE #endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */ -#endif /* !asm */ - #if ACCESS_TYPE != (NB_MMU_MODES + 1) #if DATA_SIZE == 8 diff --git a/qemu/sysemu.h b/qemu/sysemu.h index 06dc4c68..df19f028 100644 --- a/qemu/sysemu.h +++ b/qemu/sysemu.h @@ -124,6 +124,7 @@ extern int graphic_rotate; extern int no_quit; extern int semihosting_enabled; extern int old_param; +extern int boot_menu; #ifdef CONFIG_KQEMU extern int kqemu_allowed; diff --git a/qemu/target-i386/cpu.h b/qemu/target-i386/cpu.h index 0f802668..96294010 100644 --- a/qemu/target-i386/cpu.h +++ b/qemu/target-i386/cpu.h @@ -267,11 +267,11 @@ #define MCE_CAP_DEF MCG_CTL_P #define MCE_BANKS_DEF 10 -#define MCG_STATUS_MCIP (1UL<<2) /* machine check in progress */ +#define MCG_STATUS_MCIP (1ULL<<2) /* machine check in progress */ -#define MCI_STATUS_VAL (1UL<<63) /* valid error */ -#define MCI_STATUS_OVER (1UL<<62) /* previous errors lost */ -#define MCI_STATUS_UC (1UL<<61) /* uncorrected error */ +#define MCI_STATUS_VAL (1ULL<<63) /* valid error */ +#define MCI_STATUS_OVER (1ULL<<62) /* previous errors lost */ +#define MCI_STATUS_UC (1ULL<<61) /* uncorrected error */ #define MSR_IA32_TSC 0x10 #define MSR_IA32_APICBASE 0x1b @@ -785,6 +785,10 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env, } } +int cpu_x86_get_descr_debug(CPUX86State* env, unsigned int selector, + target_ulong* base, unsigned int* limit, + unsigned int* flags); + /* wrapper, just in case memory mappings must be changed */ static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl) { diff --git a/qemu/target-i386/helper.c b/qemu/target-i386/helper.c index 48641f3a..ea781963 100644 --- a/qemu/target-i386/helper.c +++ b/qemu/target-i386/helper.c @@ -145,8 +145,7 @@ static x86_def_t x86_defs[] = { CPUID_PSE36, .ext_features = CPUID_EXT_SSE3, .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | - CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | - CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, .ext3_features = CPUID_EXT3_SVM, .xlevel = 0x8000000A, .model_id = "QEMU Virtual CPU version " QEMU_VERSION, @@ -1809,6 +1808,35 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, } } +int cpu_x86_get_descr_debug(CPUX86State* env, unsigned int selector, + target_ulong* base, unsigned int* limit, + unsigned int* flags) +{ + SegmentCache* dt; + target_ulong ptr; + uint32_t e1, e2; + int index; + + if (selector & 0x4) + dt = &env->ldt; + else + dt = &env->gdt; + index = selector & ~7; + ptr = dt->base + index; + if ((index + 7) > dt->limit + || cpu_memory_rw_debug(env, ptr, (uint8_t*)&e1, sizeof(e1), 0) != 0 + || cpu_memory_rw_debug(env, ptr + 4, (uint8_t*)&e2, sizeof(e2), 0) != 0) + return 0; + + *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000)); + *limit = (e1 & 0xffff) | (e2 & 0x000f0000); + if (e2 & DESC_G_MASK) + *limit = (*limit << 12) | 0xfff; + *flags = e2; + + return 1; +} + CPUX86State *cpu_x86_init(const char *cpu_model) { CPUX86State *env; diff --git a/qemu/target-i386/kvm.c b/qemu/target-i386/kvm.c index 4a3f598e..cab9fcca 100644 --- a/qemu/target-i386/kvm.c +++ b/qemu/target-i386/kvm.c @@ -239,8 +239,11 @@ static int kvm_has_msr_star(CPUState *env) if (ret < 0) return 0; - kvm_msr_list = qemu_mallocz(sizeof(msr_list) + - msr_list.nmsrs * sizeof(msr_list.indices[0])); + /* Old kernel modules had a bug and could write beyond the provided + memory. Allocate at least a safe amount of 1K. */ + kvm_msr_list = qemu_mallocz(MAX(1024, sizeof(msr_list) + + msr_list.nmsrs * + sizeof(msr_list.indices[0]))); kvm_msr_list->nmsrs = msr_list.nmsrs; ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, kvm_msr_list); diff --git a/qemu/target-mips/helper.c b/qemu/target-mips/helper.c index fecbcb2f..73690257 100644 --- a/qemu/target-mips/helper.c +++ b/qemu/target-mips/helper.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 . */ #include #include diff --git a/qemu/target-mips/op_helper.c b/qemu/target-mips/op_helper.c index b4c98fc0..194414c7 100644 --- a/qemu/target-mips/op_helper.c +++ b/qemu/target-mips/op_helper.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 . */ #include #include "exec.h" diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index cf467f89..6a1273f0 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -16,8 +16,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 . */ #include @@ -1174,19 +1173,18 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, #if defined(TARGET_MIPS64) case OPC_SCD: save_cpu_state(ctx, 0); - op_ldst_scd(t0, t1, t0, ctx); + op_ldst_scd(t1, t0, rt, ctx); opn = "scd"; break; #endif case OPC_SC: save_cpu_state(ctx, 0); - op_ldst_sc(t0, t1, t0, ctx); + op_ldst_sc(t1, t0, rt, ctx); opn = "sc"; break; } MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); tcg_temp_free(t1); - gen_store_gpr(t0, rt); tcg_temp_free(t0); } diff --git a/qemu/target-mips/translate_init.c b/qemu/target-mips/translate_init.c index d7617f60..eb35dbad 100644 --- a/qemu/target-mips/translate_init.c +++ b/qemu/target-mips/translate_init.c @@ -15,8 +15,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 . */ /* CPU / CPU family specific config register values. */ diff --git a/qemu/target-ppc/cpu.h b/qemu/target-ppc/cpu.h index 59d47d2d..69c1d580 100644 --- a/qemu/target-ppc/cpu.h +++ b/qemu/target-ppc/cpu.h @@ -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 . */ #if !defined (__CPU_PPC_H__) #define __CPU_PPC_H__ diff --git a/qemu/target-ppc/exec.h b/qemu/target-ppc/exec.h index f6b9ee6c..0481eb23 100644 --- a/qemu/target-ppc/exec.h +++ b/qemu/target-ppc/exec.h @@ -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 . */ #if !defined (__PPC_H__) #define __PPC_H__ diff --git a/qemu/target-ppc/helper.c b/qemu/target-ppc/helper.c index 5a7a935b..bd9bc8a8 100644 --- a/qemu/target-ppc/helper.c +++ b/qemu/target-ppc/helper.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 . */ #include #include diff --git a/qemu/target-ppc/helper_regs.h b/qemu/target-ppc/helper_regs.h index 15392393..2a1f541d 100644 --- a/qemu/target-ppc/helper_regs.h +++ b/qemu/target-ppc/helper_regs.h @@ -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 . */ #if !defined(__HELPER_REGS_H__) diff --git a/qemu/target-ppc/op_helper.c b/qemu/target-ppc/op_helper.c index 94e53032..c352aa71 100644 --- a/qemu/target-ppc/op_helper.c +++ b/qemu/target-ppc/op_helper.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 . */ #include #include "exec.h" diff --git a/qemu/target-ppc/translate.c b/qemu/target-ppc/translate.c index a14d197e..da3d7de8 100644 --- a/qemu/target-ppc/translate.c +++ b/qemu/target-ppc/translate.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 . */ #include #include @@ -5935,7 +5934,7 @@ static void gen_wrteei(DisasContext *ctx) gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC); return; } - if (ctx->opcode & 0x00010000) { + if (ctx->opcode & 0x00008000) { tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE)); /* Stop translation to have a chance to raise an exception */ gen_stop_exception(ctx); @@ -6908,8 +6907,8 @@ static always_inline void gen_evmergelo (DisasContext *ctx) tcg_temp_free(t0); tcg_temp_free(t1); #else - tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); + tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); #endif } static always_inline void gen_evmergehilo (DisasContext *ctx) @@ -6946,8 +6945,16 @@ static always_inline void gen_evmergelohi (DisasContext *ctx) tcg_temp_free(t0); tcg_temp_free(t1); #else - tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]); - tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); + if (rD(ctx->opcode) == rA(ctx->opcode)) { + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_mov_i32(tmp, cpu_gpr[rA(ctx->opcode)]); + tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]); + tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], tmp); + tcg_temp_free_i32(tmp); + } else { + tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]); + tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); + } #endif } static always_inline void gen_evsplati (DisasContext *ctx) @@ -8150,7 +8157,7 @@ GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE), GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE), GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE), GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE), -GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE), +GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE), GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC), GEN_HANDLER(mbar, 0x1F, 0x16, 0x1a, 0x001FF801, PPC_BOOKE), GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE), diff --git a/qemu/target-ppc/translate_init.c b/qemu/target-ppc/translate_init.c index 04225e55..3b6e2d50 100644 --- a/qemu/target-ppc/translate_init.c +++ b/qemu/target-ppc/translate_init.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 . */ /* A lot of PowerPC definition have been included here. @@ -3381,7 +3380,7 @@ static void init_proc_405 (CPUPPCState *env) PPC_DCR | PPC_WRTEE | PPC_RFMCI | \ PPC_CACHE | PPC_CACHE_ICBI | \ PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \ - PPC_MEM_TLBSYNC | \ + PPC_MEM_TLBSYNC | PPC_MFTB | \ PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \ PPC_440_SPEC) #define POWERPC_MSRM_440EP (0x000000000006D630ULL) @@ -3461,7 +3460,7 @@ static void init_proc_440EP (CPUPPCState *env) PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_MFAPIDI | \ PPC_CACHE | PPC_CACHE_ICBI | \ PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \ - PPC_MEM_TLBSYNC | PPC_TLBIVA | \ + PPC_MEM_TLBSYNC | PPC_TLBIVA | PPC_MFTB | \ PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \ PPC_440_SPEC) #define POWERPC_MSRM_440GP (0x000000000006FF30ULL) @@ -3523,7 +3522,7 @@ static void init_proc_440GP (CPUPPCState *env) PPC_DCR | PPC_WRTEE | \ PPC_CACHE | PPC_CACHE_ICBI | \ PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \ - PPC_MEM_TLBSYNC | \ + PPC_MEM_TLBSYNC | PPC_MFTB | \ PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \ PPC_440_SPEC) #define POWERPC_MSRM_440x4 (0x000000000006FF30ULL) @@ -3585,7 +3584,7 @@ static void init_proc_440x4 (CPUPPCState *env) PPC_DCR | PPC_WRTEE | PPC_RFMCI | \ PPC_CACHE | PPC_CACHE_ICBI | \ PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \ - PPC_MEM_TLBSYNC | \ + PPC_MEM_TLBSYNC | PPC_MFTB | \ PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \ PPC_440_SPEC) #define POWERPC_MSRM_440x5 (0x000000000006FF30ULL) @@ -3663,7 +3662,7 @@ static void init_proc_440x5 (CPUPPCState *env) /* PowerPC 460 (guessed) */ #define POWERPC_INSNS_460 (PPC_INSNS_BASE | PPC_STRING | \ PPC_DCR | PPC_DCRX | PPC_DCRUX | \ - PPC_WRTEE | PPC_MFAPIDI | \ + PPC_WRTEE | PPC_MFAPIDI | PPC_MFTB | \ PPC_CACHE | PPC_CACHE_ICBI | \ PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \ PPC_MEM_TLBSYNC | PPC_TLBIVA | \ @@ -3750,7 +3749,7 @@ static void init_proc_460 (CPUPPCState *env) #define POWERPC_INSNS_460F (PPC_INSNS_BASE | PPC_STRING | \ PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL | \ PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | \ - PPC_FLOAT_STFIWX | \ + PPC_FLOAT_STFIWX | PPC_MFTB | \ PPC_DCR | PPC_DCRX | PPC_DCRUX | \ PPC_WRTEE | PPC_MFAPIDI | \ PPC_CACHE | PPC_CACHE_ICBI | \ diff --git a/qemu/target-sparc/cpu.h b/qemu/target-sparc/cpu.h index d592bea3..76e1e796 100644 --- a/qemu/target-sparc/cpu.h +++ b/qemu/target-sparc/cpu.h @@ -115,15 +115,18 @@ enum { #define TBR_BASE_MASK 0xfffff000 #if defined(TARGET_SPARC64) -#define PS_IG (1<<11) -#define PS_MG (1<<10) +#define PS_TCT (1<<12) /* UA2007, impl.dep. trap on control transfer */ +#define PS_IG (1<<11) /* v9, zero on UA2007 */ +#define PS_MG (1<<10) /* v9, zero on UA2007 */ +#define PS_CLE (1<<9) /* UA2007 */ +#define PS_TLE (1<<8) /* UA2007 */ #define PS_RMO (1<<7) -#define PS_RED (1<<5) -#define PS_PEF (1<<4) -#define PS_AM (1<<3) +#define PS_RED (1<<5) /* v9, zero on UA2007 */ +#define PS_PEF (1<<4) /* enable fpu */ +#define PS_AM (1<<3) /* address mask */ #define PS_PRIV (1<<2) #define PS_IE (1<<1) -#define PS_AG (1<<0) +#define PS_AG (1<<0) /* v9, zero on UA2007 */ #define FPRS_FEF (1<<2) @@ -291,11 +294,15 @@ typedef struct CPUSPARCState { float32 fpr[TARGET_FPREGS]; /* floating point registers */ uint32_t cwp; /* index of current register window (extracted from PSR) */ +#if !defined(TARGET_SPARC64) || defined(TARGET_ABI32) uint32_t wim; /* window invalid mask */ +#endif target_ulong tbr; /* trap base register */ int psrs; /* supervisor mode (extracted from PSR) */ int psrps; /* previous supervisor mode */ +#if !defined(TARGET_SPARC64) int psret; /* enable traps */ +#endif uint32_t psrpil; /* interrupt blocking level */ uint32_t pil_in; /* incoming interrupt level bitmap */ int psref; /* enable fpu */ @@ -378,12 +385,21 @@ void gen_intermediate_code_init(CPUSPARCState *env); /* cpu-exec.c */ int cpu_sparc_exec(CPUSPARCState *s); +#if !defined (TARGET_SPARC64) #define GET_PSR(env) (env->version | (env->psr & PSR_ICC) | \ (env->psref? PSR_EF : 0) | \ (env->psrpil << 8) | \ (env->psrs? PSR_S : 0) | \ (env->psrps? PSR_PS : 0) | \ (env->psret? PSR_ET : 0) | env->cwp) +#else +#define GET_PSR(env) (env->version | (env->psr & PSR_ICC) | \ + (env->psref? PSR_EF : 0) | \ + (env->psrpil << 8) | \ + (env->psrs? PSR_S : 0) | \ + (env->psrps? PSR_PS : 0) | \ + env->cwp) +#endif #ifndef NO_CPU_IO_DEFS static inline void memcpy32(target_ulong *dst, const target_ulong *src) @@ -425,6 +441,7 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp) } #endif +#if !defined (TARGET_SPARC64) #define PUT_PSR(env, val) do { int _tmp = val; \ env->psr = _tmp & PSR_ICC; \ env->psref = (_tmp & PSR_EF)? 1 : 0; \ @@ -435,6 +452,17 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp) cpu_set_cwp(env, _tmp & PSR_CWP); \ CC_OP = CC_OP_FLAGS; \ } while (0) +#else +#define PUT_PSR(env, val) do { int _tmp = val; \ + env->psr = _tmp & PSR_ICC; \ + env->psref = (_tmp & PSR_EF)? 1 : 0; \ + env->psrpil = (_tmp & PSR_PIL) >> 8; \ + env->psrs = (_tmp & PSR_S)? 1 : 0; \ + env->psrps = (_tmp & PSR_PS)? 1 : 0; \ + cpu_set_cwp(env, _tmp & PSR_CWP); \ + CC_OP = CC_OP_FLAGS; \ + } while (0) +#endif #ifdef TARGET_SPARC64 #define GET_CCR(env) (((env->xcc >> 20) << 4) | ((env->psr & PSR_ICC) >> 20)) diff --git a/qemu/target-sparc/exec.h b/qemu/target-sparc/exec.h index f37c8ad9..e120d6fe 100644 --- a/qemu/target-sparc/exec.h +++ b/qemu/target-sparc/exec.h @@ -24,10 +24,23 @@ static inline void regs_to_env(void) /* op_helper.c */ void do_interrupt(CPUState *env); +static inline int cpu_interrupts_enabled(CPUState *env1) +{ +#if !defined (TARGET_SPARC64) + if (env1->psret != 0) + return 1; +#else + if (env1->pstate & PS_IE) + return 1; +#endif + + return 0; +} + static inline int cpu_has_work(CPUState *env1) { return (env1->interrupt_request & CPU_INTERRUPT_HARD) && - (env1->psret != 0); + cpu_interrupts_enabled(env1); } diff --git a/qemu/target-sparc/helper.c b/qemu/target-sparc/helper.c index 2f41418c..04513f82 100644 --- a/qemu/target-sparc/helper.c +++ b/qemu/target-sparc/helper.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 . */ #include #include @@ -369,42 +368,79 @@ void dump_mmu(CPUState *env) #endif /* DEBUG_MMU */ #else /* !TARGET_SPARC64 */ + +// 41 bit physical address space +static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x) +{ + return x & 0x1ffffffffffULL; +} + /* * UltraSparc IIi I/DMMUs */ + +static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask) +{ + return (x & mask) == (y & mask); +} + +// Returns true if TTE tag is valid and matches virtual address value in context +// requires virtual address mask value calculated from TTE entry size +static inline int ultrasparc_tag_match(uint64_t tlb_tag, uint64_t tlb_tte, + uint64_t address, uint64_t context, + target_phys_addr_t *physical) +{ + uint64_t mask; + + switch ((tlb_tte >> 61) & 3) { + default: + case 0x0: // 8k + mask = 0xffffffffffffe000ULL; + break; + case 0x1: // 64k + mask = 0xffffffffffff0000ULL; + break; + case 0x2: // 512k + mask = 0xfffffffffff80000ULL; + break; + case 0x3: // 4M + mask = 0xffffffffffc00000ULL; + break; + } + + // valid, context match, virtual address match? + if ((tlb_tte & 0x8000000000000000ULL) && + compare_masked(context, tlb_tag, 0x1fff) && + compare_masked(address, tlb_tag, mask)) + { + // decode physical address + *physical = ((tlb_tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL; + return 1; + } + + return 0; +} + static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot, target_ulong address, int rw, int is_user) { - target_ulong mask; unsigned int i; + uint64_t context; if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */ - *physical = address; + *physical = ultrasparc_truncate_physical(address); *prot = PAGE_READ | PAGE_WRITE; return 0; } + context = env->dmmuregs[1] & 0x1fff; + for (i = 0; i < 64; i++) { - switch ((env->dtlb_tte[i] >> 61) & 3) { - default: - case 0x0: // 8k - mask = 0xffffffffffffe000ULL; - break; - case 0x1: // 64k - mask = 0xffffffffffff0000ULL; - break; - case 0x2: // 512k - mask = 0xfffffffffff80000ULL; - break; - case 0x3: // 4M - mask = 0xffffffffffc00000ULL; - break; - } // ctx match, vaddr match, valid? - if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) && - (address & mask) == (env->dtlb_tag[i] & mask) && - (env->dtlb_tte[i] & 0x8000000000000000ULL)) { + if (ultrasparc_tag_match(env->dtlb_tag[i], env->dtlb_tte[i], + address, context, physical) + ) { // access ok? if (((env->dtlb_tte[i] & 0x4) && is_user) || (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) { @@ -419,8 +455,6 @@ static int get_physical_address_data(CPUState *env, #endif return 1; } - *physical = ((env->dtlb_tte[i] & mask) | (address & ~mask)) & - 0x1ffffffe000ULL; *prot = PAGE_READ; if (env->dtlb_tte[i] & 0x2) *prot |= PAGE_WRITE; @@ -430,7 +464,7 @@ static int get_physical_address_data(CPUState *env, #ifdef DEBUG_MMU printf("DMISS at 0x%" PRIx64 "\n", address); #endif - env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff); + env->dmmuregs[6] = (address & ~0x1fffULL) | context; env->exception_index = TT_DMISS; return 1; } @@ -439,35 +473,23 @@ static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot, target_ulong address, int is_user) { - target_ulong mask; unsigned int i; + uint64_t context; - if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */ - *physical = address; + if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) { + /* IMMU disabled */ + *physical = ultrasparc_truncate_physical(address); *prot = PAGE_EXEC; return 0; } + context = env->dmmuregs[1] & 0x1fff; + for (i = 0; i < 64; i++) { - switch ((env->itlb_tte[i] >> 61) & 3) { - default: - case 0x0: // 8k - mask = 0xffffffffffffe000ULL; - break; - case 0x1: // 64k - mask = 0xffffffffffff0000ULL; - break; - case 0x2: // 512k - mask = 0xfffffffffff80000ULL; - break; - case 0x3: // 4M - mask = 0xffffffffffc00000ULL; - break; - } // ctx match, vaddr match, valid? - if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) && - (address & mask) == (env->itlb_tag[i] & mask) && - (env->itlb_tte[i] & 0x8000000000000000ULL)) { + if (ultrasparc_tag_match(env->itlb_tag[i], env->itlb_tte[i], + address, context, physical) + ) { // access ok? if ((env->itlb_tte[i] & 0x4) && is_user) { if (env->immuregs[3]) /* Fault status register */ @@ -480,8 +502,6 @@ static int get_physical_address_code(CPUState *env, #endif return 1; } - *physical = ((env->itlb_tte[i] & mask) | (address & ~mask)) & - 0x1ffffffe000ULL; *prot = PAGE_EXEC; return 0; } @@ -490,7 +510,7 @@ static int get_physical_address_code(CPUState *env, printf("TMISS at 0x%" PRIx64 "\n", address); #endif /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */ - env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff); + env->immuregs[6] = (address & ~0x1fffULL) | context; env->exception_index = TT_TMISS; return 1; } @@ -646,7 +666,9 @@ void cpu_reset(CPUSPARCState *env) tlb_flush(env, 1); env->cwp = 0; +#ifndef TARGET_SPARC64 env->wim = 1; +#endif env->regwptr = env->regbase + (env->cwp * 16); #if defined(CONFIG_USER_ONLY) #ifdef TARGET_SPARC64 @@ -656,7 +678,9 @@ void cpu_reset(CPUSPARCState *env) env->asi = 0x82; // Primary no-fault #endif #else +#if !defined(TARGET_SPARC64) env->psret = 0; +#endif env->psrs = 1; env->psrps = 1; CC_OP = CC_OP_FLAGS; diff --git a/qemu/target-sparc/op_helper.c b/qemu/target-sparc/op_helper.c index a1f50549..d25b642c 100644 --- a/qemu/target-sparc/op_helper.c +++ b/qemu/target-sparc/op_helper.c @@ -1949,13 +1949,13 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) case 0x89: // Secondary LE switch(size) { case 2: - addr = bswap16(addr); + val = bswap16(val); break; case 4: - addr = bswap32(addr); + val = bswap32(val); break; case 8: - addr = bswap64(addr); + val = bswap64(val); break; default: break; @@ -2321,13 +2321,13 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) case 0x89: // Secondary LE switch(size) { case 2: - addr = bswap16(addr); + val = bswap16(val); break; case 4: - addr = bswap32(addr); + val = bswap32(val); break; case 8: - addr = bswap64(addr); + val = bswap64(val); break; default: break; @@ -3225,8 +3225,14 @@ static inline void change_pstate(uint64_t new_pstate) uint64_t pstate_regs, new_pstate_regs; uint64_t *src, *dst; + if (env->def->features & CPU_FEATURE_GL) { + // PS_AG is not implemented in this case + new_pstate &= ~PS_AG; + } + pstate_regs = env->pstate & 0xc01; new_pstate_regs = new_pstate & 0xc01; + if (new_pstate_regs != pstate_regs) { // Switch global register bank src = get_gregset(new_pstate_regs); @@ -3239,8 +3245,7 @@ static inline void change_pstate(uint64_t new_pstate) void helper_wrpstate(target_ulong new_state) { - if (!(env->def->features & CPU_FEATURE_GL)) - change_pstate(new_state & 0xf3f); + change_pstate(new_state & 0xf3f); } void helper_done(void) @@ -3392,23 +3397,23 @@ void do_interrupt(CPUState *env) env->tsptr->tpc = env->pc; env->tsptr->tnpc = env->npc; env->tsptr->tt = intno; - if (!(env->def->features & CPU_FEATURE_GL)) { - switch (intno) { - case TT_IVEC: - change_pstate(PS_PEF | PS_PRIV | PS_IG); - break; - case TT_TFAULT: - case TT_TMISS: - case TT_DFAULT: - case TT_DMISS: - case TT_DPROT: - change_pstate(PS_PEF | PS_PRIV | PS_MG); - break; - default: - change_pstate(PS_PEF | PS_PRIV | PS_AG); - break; - } + + switch (intno) { + case TT_IVEC: + change_pstate(PS_PEF | PS_PRIV | PS_IG); + break; + case TT_TFAULT: + case TT_TMISS: + case TT_DFAULT: + case TT_DMISS: + case TT_DPROT: + change_pstate(PS_PEF | PS_PRIV | PS_MG); + break; + default: + change_pstate(PS_PEF | PS_PRIV | PS_AG); + break; } + if (intno == TT_CLRWIN) cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1)); else if ((intno & 0x1c0) == TT_SPILL) diff --git a/qemu/target-sparc/translate.c b/qemu/target-sparc/translate.c index 6de40791..a372ecab 100644 --- a/qemu/target-sparc/translate.c +++ b/qemu/target-sparc/translate.c @@ -15,8 +15,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 . */ #include diff --git a/qemu/usb-linux.c b/qemu/usb-linux.c index 67e4acd5..3c724baf 100644 --- a/qemu/usb-linux.c +++ b/qemu/usb-linux.c @@ -1265,6 +1265,15 @@ static int usb_host_scan(void *opaque, USBScanFunc *func) /* only check the host once */ if (!usb_fs_type) { + dir = opendir(USBSYSBUS_PATH "/devices"); + if (dir) { + /* devices found in /dev/bus/usb/ (yes - not a mistake!) */ + strcpy(devpath, USBDEVBUS_PATH); + usb_fs_type = USB_FS_SYS; + closedir(dir); + dprintf(USBDBG_DEVOPENED, USBSYSBUS_PATH); + goto found_devices; + } f = fopen(USBPROCBUS_PATH "/devices", "r"); if (f) { /* devices found in /proc/bus/usb/ */ @@ -1284,15 +1293,6 @@ static int usb_host_scan(void *opaque, USBScanFunc *func) dprintf(USBDBG_DEVOPENED, USBDEVBUS_PATH); goto found_devices; } - dir = opendir(USBSYSBUS_PATH "/devices"); - if (dir) { - /* devices found in /dev/bus/usb/ (yes - not a mistake!) */ - strcpy(devpath, USBDEVBUS_PATH); - usb_fs_type = USB_FS_SYS; - closedir(dir); - dprintf(USBDBG_DEVOPENED, USBSYSBUS_PATH); - goto found_devices; - } found_devices: if (!usb_fs_type) { monitor_printf(mon, "husb: unable to access USB devices\n"); diff --git a/qemu/vl.c b/qemu/vl.c index b3b2c5e1..dce1f19f 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -265,6 +265,7 @@ const char *prom_envs[MAX_PROM_ENVS]; #endif int nb_drives_opt; struct drive_opt drives_opt[MAX_DRIVES]; +int boot_menu; int nb_numa_nodes; uint64_t node_mem[MAX_NODES]; @@ -285,6 +286,9 @@ static QEMUTimer *nographic_timer; uint8_t qemu_uuid[16]; +static QEMUBootSetHandler *boot_set_handler; +static void *boot_set_opaque; + /***********************************************************/ /* x86 ISA bus support */ @@ -2367,6 +2371,59 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) return drives_table_idx; } +void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque) +{ + boot_set_handler = func; + boot_set_opaque = opaque; +} + +int qemu_boot_set(const char *boot_devices) +{ + if (!boot_set_handler) { + return -EINVAL; + } + return boot_set_handler(boot_set_opaque, boot_devices); +} + +static int parse_bootdevices(char *devices) +{ + /* We just do some generic consistency checks */ + const char *p; + int bitmap = 0; + + for (p = devices; *p != '\0'; p++) { + /* Allowed boot devices are: + * a-b: floppy disk drives + * c-f: IDE disk drives + * g-m: machine implementation dependant drives + * n-p: network devices + * It's up to each machine implementation to check if the given boot + * devices match the actual hardware implementation and firmware + * features. + */ + if (*p < 'a' || *p > 'p') { + fprintf(stderr, "Invalid boot device '%c'\n", *p); + exit(1); + } + if (bitmap & (1 << (*p - 'a'))) { + fprintf(stderr, "Boot device '%c' was given twice\n", *p); + exit(1); + } + bitmap |= 1 << (*p - 'a'); + } + return bitmap; +} + +static void restore_boot_devices(void *opaque) +{ + char *standard_boot_devices = opaque; + + qemu_boot_set(standard_boot_devices); + + qemu_unregister_reset(restore_boot_devices, standard_boot_devices); + qemu_free(standard_boot_devices); +} + static void numa_add(const char *optarg) { char option[128]; @@ -3407,12 +3464,13 @@ void vm_start(void) /* reset/shutdown handler */ typedef struct QEMUResetEntry { + TAILQ_ENTRY(QEMUResetEntry) entry; QEMUResetHandler *func; void *opaque; - struct QEMUResetEntry *next; } QEMUResetEntry; -static QEMUResetEntry *first_reset_entry; +static TAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers = + TAILQ_HEAD_INITIALIZER(reset_handlers); static int reset_requested; static int shutdown_requested; static int powerdown_requested; @@ -3466,24 +3524,32 @@ static void do_vm_stop(int reason) void qemu_register_reset(QEMUResetHandler *func, void *opaque) { - QEMUResetEntry **pre, *re; + QEMUResetEntry *re = qemu_mallocz(sizeof(QEMUResetEntry)); - pre = &first_reset_entry; - while (*pre != NULL) - pre = &(*pre)->next; - re = qemu_mallocz(sizeof(QEMUResetEntry)); re->func = func; re->opaque = opaque; - re->next = NULL; - *pre = re; + TAILQ_INSERT_TAIL(&reset_handlers, re, entry); } -void qemu_system_reset(void) +void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) { QEMUResetEntry *re; + TAILQ_FOREACH(re, &reset_handlers, entry) { + if (re->func == func && re->opaque == opaque) { + TAILQ_REMOVE(&reset_handlers, re, entry); + qemu_free(re); + return; + } + } +} + +void qemu_system_reset(void) +{ + QEMUResetEntry *re, *nre; + /* reset all devices */ - for(re = first_reset_entry; re != NULL; re = re->next) { + TAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) { re->func(re->opaque); } } @@ -4783,7 +4849,7 @@ int __declspec(dllexport) qemu_main(int argc, char** argv, char** envp) int snapshot, linux_boot, net_boot; const char *initrd_filename; const char *kernel_filename, *kernel_cmdline; - const char *boot_devices = ""; + char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */ DisplayState *ds; DisplayChangeListener *dcl; int cyls, heads, secs, translation; @@ -5072,33 +5138,51 @@ int __declspec(dllexport) qemu_main(int argc, char** argv, char** envp) drive_add(optarg, CDROM_ALIAS); break; case QEMU_OPTION_boot: - boot_devices = optarg; - /* We just do some generic consistency checks */ { - /* Could easily be extended to 64 devices if needed */ - const char *p; - - boot_devices_bitmap = 0; - for (p = boot_devices; *p != '\0'; p++) { - /* Allowed boot devices are: - * a b : floppy disk drives - * c ... f : IDE disk drives - * g ... m : machine implementation dependant drives - * n ... p : network devices - * It's up to each machine implementation to check - * if the given boot devices match the actual hardware - * implementation and firmware features. - */ - if (*p < 'a' || *p > 'q') { - fprintf(stderr, "Invalid boot device '%c'\n", *p); - exit(1); + static const char * const params[] = { + "order", "once", "menu", NULL + }; + char buf[sizeof(boot_devices)]; + char *standard_boot_devices; + int legacy = 0; + + if (!strchr(optarg, '=')) { + legacy = 1; + pstrcpy(buf, sizeof(buf), optarg); + } else if (check_params(buf, sizeof(buf), params, optarg) < 0) { + fprintf(stderr, + "qemu: unknown boot parameter '%s' in '%s'\n", + buf, optarg); + exit(1); + } + + if (legacy || + get_param_value(buf, sizeof(buf), "order", optarg)) { + boot_devices_bitmap = parse_bootdevices(buf); + pstrcpy(boot_devices, sizeof(boot_devices), buf); + } + if (!legacy) { + if (get_param_value(buf, sizeof(buf), + "once", optarg)) { + boot_devices_bitmap |= parse_bootdevices(buf); + standard_boot_devices = qemu_strdup(boot_devices); + pstrcpy(boot_devices, sizeof(boot_devices), buf); + qemu_register_reset(restore_boot_devices, + standard_boot_devices); } - if (boot_devices_bitmap & (1 << (*p - 'a'))) { - fprintf(stderr, - "Boot device '%c' was given twice\n",*p); - exit(1); + if (get_param_value(buf, sizeof(buf), + "menu", optarg)) { + if (!strcmp(buf, "on")) { + boot_menu = 1; + } else if (!strcmp(buf, "off")) { + boot_menu = 0; + } else { + fprintf(stderr, + "qemu: invalid option value '%s'\n", + buf); + exit(1); + } } - boot_devices_bitmap |= 1 << (*p - 'a'); } } break; @@ -5667,10 +5751,6 @@ int __declspec(dllexport) qemu_main(int argc, char** argv, char** envp) exit(1); } - /* boot to floppy or the default cd if no hard disk defined yet */ - if (!boot_devices[0]) { - boot_devices = "cad"; - } #ifndef _MSC_VER setvbuf(stdout, NULL, _IOLBF, 0); #else @@ -5888,6 +5968,9 @@ int __declspec(dllexport) qemu_main(int argc, char** argv, char** envp) module_call_init(MODULE_INIT_DEVICE); + if (machine->compat_props) { + qdev_prop_register_compat(machine->compat_props); + } machine->init(ram_size, boot_devices, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); @@ -6012,10 +6095,8 @@ int __declspec(dllexport) qemu_main(int argc, char** argv, char** envp) if (loadvm) do_loadvm(cur_mon, loadvm); - if (incoming) { - autostart = 0; /* fixme how to deal with -daemonize */ + if (incoming) qemu_start_incoming_migration(incoming); - } if (autostart) vm_start();