[Spice-commits] 140 commits - Changelog Makefile Makefile.objs Makefile.target arch_init.c arch_init.h block.c block/qcow2-refcount.c block/sheepdog.c bsd-user/main.c bsd-user/qemu.h configure cpu-all.h cpu-common.h cpu-exec.c darwin-user/syscall.c exec.c hppa-dis.c hw/ac97.c hw/boards.h hw/bt.h hw/cirrus_vga.c hw/eepro100.c hw/eeprom93xx.c hw/ide hw/intel-hda.c hw/lan9118.c hw/lsi53c895a.c hw/msi.c hw/msix.c hw/mst_fpga.c hw/pc.c hw/pc.h hw/pc_piix.c hw/pci.c hw/pci.h hw/pci_regs.h hw/pcie.c hw/pcie.h hw/pcie_aer.c hw/pcnet-pci.c hw/pflash_cfi02.c hw/piix_pci.c hw/pl031.c hw/pl061.c hw/ppc.c hw/ppc4xx_devs.c hw/ppce500.h hw/ppce500_mpc8544ds.c hw/ppce500_pci.c hw/qxl-render.c hw/qxl.c hw/rtl8139.c hw/sh7750_regs.h hw/spapr.c hw/spapr_hcall.c hw/spapr_rtas.c hw/spapr_vio.h hw/ssd0303.c hw/sun4m_iommu.c hw/syborg_serial.c hw/usb-hub.c hw/usb-msd.c hw/usb-musb.c hw/usb-ohci.c hw/usb-uhci.c hw/usb.c hw/usb.h hw/vhost.c hw/wdt_i6300esb.c hw/xen.h hw/xen_backend.c hw/xen_backend.h hw/xen _common.h hw/xen_disk.c hw/xen_domainbuild.c hw/xen_machine_pv.c hw/xen_nic.c hw/xilinx_axidma.c kvm-all.c libcacard/Makefile libcacard/vcard_emul_nss.c libcacard/vscard_common.h linux-user/main.c linux-user/mmap.c linux-user/qemu.h linux-user/signal.c linux-user/syscall.c monitor.c poison.h qemu-common.h qemu-config.c qemu-doc.texi qemu-options.hx qemu-os-win32.h sysemu.h target-arm/cpu.h target-arm/translate.c target-cris/cpu.h target-cris/translate_v10.c target-i386/cpu.h target-lm32/translate.c target-m68k/helper.c target-microblaze/cpu.h target-microblaze/helper.c target-mips/exec.h target-mips/helper.c target-mips/translate_init.c target-ppc/cpu.h target-ppc/helper.c target-ppc/helper.h target-ppc/kvm.c target-ppc/op_helper.c target-ppc/translate.c target-ppc/translate_init.c target-sparc/translate.c tcg/tcg.h tests/test-i386.c tests/test-mmap.c trace-events ui/qemu-spice.h ui/sdl.c ui/spice-display.c ui/spice-display.h usb-linux.c vl.c xen-all.c xen-mapcache-stub.c xe n-mapcache.c xen-mapcache.h xen-stub.c
Gerd Hoffmann
kraxel at kemper.freedesktop.org
Tue May 17 02:22:40 PDT 2011
Changelog | 2
Makefile | 2
Makefile.objs | 9
Makefile.target | 14
arch_init.c | 5
arch_init.h | 1
block.c | 4
block/qcow2-refcount.c | 2
block/sheepdog.c | 4
bsd-user/main.c | 2
bsd-user/qemu.h | 2
configure | 227 +++++++++++-----
cpu-all.h | 60 +++-
cpu-common.h | 23 +
cpu-exec.c | 12
darwin-user/syscall.c | 2
exec.c | 116 +++++++-
hppa-dis.c | 2
hw/ac97.c | 6
hw/boards.h | 1
hw/bt.h | 2
hw/cirrus_vga.c | 30 --
hw/eepro100.c | 344 ++++++++++++++++--------
hw/eeprom93xx.c | 10
hw/ide/ahci.c | 9
hw/ide/ahci.h | 3
hw/ide/ich.c | 12
hw/intel-hda.c | 15 -
hw/lan9118.c | 2
hw/lsi53c895a.c | 30 --
hw/msi.c | 14
hw/msix.c | 2
hw/mst_fpga.c | 2
hw/pc.c | 28 -
hw/pc.h | 11
hw/pc_piix.c | 71 ++++-
hw/pci.c | 33 ++
hw/pci.h | 6
hw/pci_regs.h | 2
hw/pcie.c | 2
hw/pcie.h | 2
hw/pcie_aer.c | 2
hw/pcnet-pci.c | 16 -
hw/pflash_cfi02.c | 2
hw/piix_pci.c | 176 ++++++++++--
hw/pl031.c | 2
hw/pl061.c | 4
hw/ppc.c | 12
hw/ppc4xx_devs.c | 2
hw/ppce500.h | 22 -
hw/ppce500_mpc8544ds.c | 113 ++++++--
hw/ppce500_pci.c | 136 +++++----
hw/qxl-render.c | 25 -
hw/qxl.c | 27 -
hw/rtl8139.c | 55 +--
hw/sh7750_regs.h | 6
hw/spapr.c | 9
hw/spapr_hcall.c | 4
hw/spapr_rtas.c | 3
hw/spapr_vio.h | 2
hw/ssd0303.c | 2
hw/sun4m_iommu.c | 2
hw/syborg_serial.c | 2
hw/usb-hub.c | 14
hw/usb-msd.c | 5
hw/usb-musb.c | 81 +++--
hw/usb-ohci.c | 19 -
hw/usb-uhci.c | 82 +----
hw/usb.c | 6
hw/usb.h | 9
hw/vhost.c | 61 ++++
hw/wdt_i6300esb.c | 42 +-
hw/xen.h | 41 ++
hw/xen_backend.c | 421 ++++++++++++++++-------------
hw/xen_backend.h | 6
hw/xen_common.h | 106 ++++++-
hw/xen_disk.c | 496 ++++++++++++++++++-----------------
hw/xen_domainbuild.c | 3
hw/xen_machine_pv.c | 1
hw/xen_nic.c | 265 ++++++++++--------
hw/xilinx_axidma.c | 4
kvm-all.c | 67 +++-
libcacard/Makefile | 9
libcacard/vcard_emul_nss.c | 2
libcacard/vscard_common.h | 2
linux-user/main.c | 2
linux-user/mmap.c | 2
linux-user/qemu.h | 2
linux-user/signal.c | 2
linux-user/syscall.c | 2
monitor.c | 71 ++++-
poison.h | 13
qemu-common.h | 5
qemu-config.c | 14
qemu-doc.texi | 6
qemu-options.hx | 16 -
qemu-os-win32.h | 3
sysemu.h | 2
target-arm/cpu.h | 4
target-arm/translate.c | 63 +++-
target-cris/cpu.h | 5
target-cris/translate_v10.c | 2
target-i386/cpu.h | 9
target-lm32/translate.c | 6
target-m68k/helper.c | 2
target-microblaze/cpu.h | 3
target-microblaze/helper.c | 2
target-mips/exec.h | 4
target-mips/helper.c | 14
target-mips/translate_init.c | 4
target-ppc/cpu.h | 310 +++++++++++++++++++++-
target-ppc/helper.c | 269 +++++++++++++++----
target-ppc/helper.h | 6
target-ppc/kvm.c | 180 ++++++++++++
target-ppc/op_helper.c | 296 +++++++++++++++++++++
target-ppc/translate.c | 200 +++++++++++++-
target-ppc/translate_init.c | 284 ++++++++++++++------
target-sparc/translate.c | 30 +-
tcg/tcg.h | 4
tests/test-i386.c | 2
tests/test-mmap.c | 4
trace-events | 13
ui/qemu-spice.h | 12
ui/sdl.c | 12
ui/spice-display.c | 61 ++--
ui/spice-display.h | 24 +
usb-linux.c | 395 ++++++++++++++++++++++++----
vl.c | 136 ++++++++-
xen-all.c | 605 +++++++++++++++++++++++++++++++++++++++++++
xen-mapcache-stub.c | 44 +++
xen-mapcache.c | 375 ++++++++++++++++++++++++++
xen-mapcache.h | 37 ++
xen-stub.c | 41 ++
133 files changed, 5442 insertions(+), 1648 deletions(-)
New commits:
commit 96d19bcbf5f679bbaaeab001b572c367fbfb2b03
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun May 8 19:54:52 2011 +0200
ahci: Unbreak bar registration
Fix regression of 667bb59: ahci_init initializes ahci.mem, so we have to
move bar registration after it.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index e44339b..6150ce3 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -93,14 +93,14 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
qemu_register_reset(ahci_reset, d);
- /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
- pci_register_bar_simple(&d->card, 5, 0x1000, 0, d->ahci.mem);
-
msi_init(dev, 0x50, 1, true, false);
ahci_init(&d->ahci, &dev->qdev, 6);
d->ahci.irq = d->card.irq[0];
+ /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
+ pci_register_bar_simple(&d->card, 5, 0x1000, 0, d->ahci.mem);
+
return 0;
}
commit 077030d11e27811749020af744e67e4267ee90e1
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sun May 15 09:51:59 2011 +0200
w32: Fix missing declaration of ffs()
target-ppc/cpu.h now needs ffs(), too, so ffs() must be declared
before this file is included.
Moving the declaration from qemu-common.h to qemu-os-win32.h
(which is included in qemu-common.h early) fixes the compiler
warning for w32.
Cc: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/qemu-common.h b/qemu-common.h
index f9f705d..bba8dfe 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -201,11 +201,6 @@ const char *path(const char *pathname);
#define qemu_isascii(c) isascii((unsigned char)(c))
#define qemu_toascii(c) toascii((unsigned char)(c))
-#ifdef _WIN32
-/* ffs() in oslib-win32.c for WIN32, strings.h for the rest of the world */
-int ffs(int i);
-#endif
-
void *qemu_oom_check(void *ptr);
void *qemu_malloc(size_t size);
void *qemu_realloc(void *ptr, size_t size);
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index ed2753d..8a069d7 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -29,6 +29,9 @@
#include <windows.h>
#include <winsock2.h>
+/* Declaration of ffs() is missing in MinGW's strings.h. */
+int ffs(int i);
+
/* Polling handling */
/* return TRUE if no sleep should be done afterwards */
commit 1de9756b97daec3c15f8048631af866e9cb58562
Author: Michael Tokarev <mjt at tls.msk.ru>
Date: Sun May 8 01:18:30 2011 +0400
set $SDL_VIDEODRIVER=x11 on Linux to prevent sudo kvm from fighting for video card
Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/ui/sdl.c b/ui/sdl.c
index dc5c3a1..14a62d9 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -831,6 +831,18 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
if (!full_screen) {
setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
}
+#ifdef __linux__
+ /* on Linux, SDL may use fbcon|directfb|svgalib when run without
+ * accessible $DISPLAY to open X11 window. This is often the case
+ * when qemu is run using sudo. But in this case, and when actually
+ * run in X11 environment, SDL fights with X11 for the video card,
+ * making current display unavailable, often until reboot.
+ * So make x11 the default SDL video driver if this variable is unset.
+ * This is a bit hackish but saves us from bigger problem.
+ * Maybe it's a good idea to fix this in SDL instead.
+ */
+ setenv("SDL_VIDEODRIVER", "x11", 0);
+#endif
/* Enable normal up/down events for Caps-Lock and Num-Lock keys.
* This requires SDL >= 1.2.14. */
commit 60e0df25e415b00cf35c4d214eaba9dc19aaa9e6
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Tue May 3 14:50:13 2011 +0100
configure: List available targets in --help output
Include the list of available targets in the --help output
for the --target-list= option.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Acked-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index e30575e..d7dba5d 100755
--- a/configure
+++ b/configure
@@ -823,6 +823,72 @@ esac
[ -z "$guest_base" ] && guest_base="$host_guest_base"
+
+default_target_list=""
+
+# these targets are portable
+if [ "$softmmu" = "yes" ] ; then
+ default_target_list="\
+i386-softmmu \
+x86_64-softmmu \
+arm-softmmu \
+cris-softmmu \
+lm32-softmmu \
+m68k-softmmu \
+microblaze-softmmu \
+microblazeel-softmmu \
+mips-softmmu \
+mipsel-softmmu \
+mips64-softmmu \
+mips64el-softmmu \
+ppc-softmmu \
+ppcemb-softmmu \
+ppc64-softmmu \
+sh4-softmmu \
+sh4eb-softmmu \
+sparc-softmmu \
+sparc64-softmmu \
+"
+fi
+# the following are Linux specific
+if [ "$linux_user" = "yes" ] ; then
+ default_target_list="${default_target_list}\
+i386-linux-user \
+x86_64-linux-user \
+alpha-linux-user \
+arm-linux-user \
+armeb-linux-user \
+cris-linux-user \
+m68k-linux-user \
+microblaze-linux-user \
+microblazeel-linux-user \
+mips-linux-user \
+mipsel-linux-user \
+ppc-linux-user \
+ppc64-linux-user \
+ppc64abi32-linux-user \
+sh4-linux-user \
+sh4eb-linux-user \
+sparc-linux-user \
+sparc64-linux-user \
+sparc32plus-linux-user \
+unicore32-linux-user \
+"
+fi
+# the following are Darwin specific
+if [ "$darwin_user" = "yes" ] ; then
+ default_target_list="$default_target_list i386-darwin-user ppc-darwin-user "
+fi
+# the following are BSD specific
+if [ "$bsd_user" = "yes" ] ; then
+ default_target_list="${default_target_list}\
+i386-bsd-user \
+x86_64-bsd-user \
+sparc-bsd-user \
+sparc64-bsd-user \
+"
+fi
+
if test x"$show_help" = x"yes" ; then
cat << EOF
@@ -835,7 +901,9 @@ echo " --help print this message"
echo " --prefix=PREFIX install in PREFIX [$prefix]"
echo " --interp-prefix=PREFIX where to find shared libraries, etc."
echo " use %M for cpu name [$interp_prefix]"
-echo " --target-list=LIST set target list [$target_list]"
+echo " --target-list=LIST set target list (default: build everything)"
+echo "Available targets: $default_target_list" | \
+ fold -s -w 53 | sed -e 's/^/ /'
echo ""
echo "Advanced options (experts only):"
echo " --source-path=PATH path of source code [$source_path]"
@@ -1005,70 +1073,8 @@ if test "$solaris" = "yes" ; then
fi
fi
-
if test -z "$target_list" ; then
-# these targets are portable
- if [ "$softmmu" = "yes" ] ; then
- target_list="\
-i386-softmmu \
-x86_64-softmmu \
-arm-softmmu \
-cris-softmmu \
-lm32-softmmu \
-m68k-softmmu \
-microblaze-softmmu \
-microblazeel-softmmu \
-mips-softmmu \
-mipsel-softmmu \
-mips64-softmmu \
-mips64el-softmmu \
-ppc-softmmu \
-ppcemb-softmmu \
-ppc64-softmmu \
-sh4-softmmu \
-sh4eb-softmmu \
-sparc-softmmu \
-sparc64-softmmu \
-"
- fi
-# the following are Linux specific
- if [ "$linux_user" = "yes" ] ; then
- target_list="${target_list}\
-i386-linux-user \
-x86_64-linux-user \
-alpha-linux-user \
-arm-linux-user \
-armeb-linux-user \
-cris-linux-user \
-m68k-linux-user \
-microblaze-linux-user \
-microblazeel-linux-user \
-mips-linux-user \
-mipsel-linux-user \
-ppc-linux-user \
-ppc64-linux-user \
-ppc64abi32-linux-user \
-sh4-linux-user \
-sh4eb-linux-user \
-sparc-linux-user \
-sparc64-linux-user \
-sparc32plus-linux-user \
-unicore32-linux-user \
-"
- fi
-# the following are Darwin specific
- if [ "$darwin_user" = "yes" ] ; then
- target_list="$target_list i386-darwin-user ppc-darwin-user "
- fi
-# the following are BSD specific
- if [ "$bsd_user" = "yes" ] ; then
- target_list="${target_list}\
-i386-bsd-user \
-x86_64-bsd-user \
-sparc-bsd-user \
-sparc64-bsd-user \
-"
- fi
+ target_list="$default_target_list"
else
target_list=`echo "$target_list" | sed -e 's/,/ /g'`
fi
commit 99e43d366c8f036cd0489aace8d65afa13901676
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Sun May 15 01:00:20 2011 +0200
target-mips: Fix warning caused by unused local variable
Fix compilation with gcc-4.6, based on a patch from Stefan
Weil <weil at mail.berlios.de>.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-mips/helper.c b/target-mips/helper.c
index bdc1e53..0f057c2 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -272,8 +272,8 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
#if !defined(CONFIG_USER_ONLY)
target_phys_addr_t physical;
int prot;
-#endif
int access_type;
+#endif
int ret = 0;
#if 0
@@ -285,21 +285,19 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
rw &= 1;
/* data access */
+#if !defined(CONFIG_USER_ONLY)
/* XXX: put correct access by using cpu_restore_state()
correctly */
access_type = ACCESS_INT;
-#if defined(CONFIG_USER_ONLY)
- ret = TLBRET_NOMATCH;
-#else
ret = get_physical_address(env, &physical, &prot,
address, rw, access_type);
qemu_log("%s address=" TARGET_FMT_lx " ret %d physical " TARGET_FMT_plx " prot %d\n",
__func__, address, ret, physical, prot);
if (ret == TLBRET_MATCH) {
- tlb_set_page(env, address & TARGET_PAGE_MASK,
- physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
- mmu_idx, TARGET_PAGE_SIZE);
- ret = 0;
+ tlb_set_page(env, address & TARGET_PAGE_MASK,
+ physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
+ mmu_idx, TARGET_PAGE_SIZE);
+ ret = 0;
} else if (ret < 0)
#endif
{
commit 7dd319027c26763ad4d0b65c09d1d20105e5c715
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Sun May 15 00:35:13 2011 +0200
configure: quote kvm_ppc_pvr
diff --git a/configure b/configure
index f18499d..e30575e 100755
--- a/configure
+++ b/configure
@@ -3339,7 +3339,7 @@ case "$target_arch2" in
if test $vhost_net = "yes" ; then
echo "CONFIG_VHOST_NET=y" >> $config_target_mak
fi
- if test $kvm_ppc_pvr = "yes" ; then
+ if test "$kvm_ppc_pvr" = "yes" ; then
echo "CONFIG_KVM_PPC_PVR=y" >> $config_target_mak
fi
fi
commit b798068d51ecf173702c91617793989ab843c8fb
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat May 7 22:49:33 2011 +0200
target-lm32: Remove unused local variables
cppcheck report:
target-lm32/translate.c:587: style:
Variable 't0' is assigned a value that is never used
target-lm32/translate.c:588: style:
Variable 'l1' is assigned a value that is never used
Remove both variables. Please check whether that is the correct solution.
Cc: Michael Walle <michael at walle.cc>
Cc: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Acked-by: Michael Walle <michael at walle.cc>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index bcd52fe..eb21158 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -584,9 +584,6 @@ static void dec_orhi(DisasContext *dc)
static void dec_scall(DisasContext *dc)
{
- TCGv t0;
- int l1;
-
if (dc->imm5 == 7) {
LOG_DIS("scall\n");
} else if (dc->imm5 == 2) {
@@ -595,9 +592,6 @@ static void dec_scall(DisasContext *dc)
cpu_abort(dc->env, "invalid opcode\n");
}
- t0 = tcg_temp_new();
- l1 = gen_new_label();
-
if (dc->imm5 == 7) {
tcg_gen_movi_tl(cpu_pc, dc->pc);
t_gen_raise_exception(dc, EXCP_SYSTEMCALL);
commit 605a6aed56963360b744355d0c25da9e26a9bb0a
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu May 5 19:35:35 2011 +0100
target-arm: Fix VMLA, VMLS, VNMLS, VNMLA handling of NaNs
Correct handling of NaNs for VFP VMLA, VMLS, VNMLS and VNMLA requires that
we implement the set of negations and additions specified by the ARM ARM;
plausible looking simplifications like turning (-A + B) into (B - A) or
computing (A + B) rather than (B + A) result in selecting the wrong NaN or
returning a NaN with the wrong sign bit.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 59190f6..a8a3b2c 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -909,6 +909,26 @@ VFP_OP2(div)
#undef VFP_OP2
+static inline void gen_vfp_F1_mul(int dp)
+{
+ /* Like gen_vfp_mul() but put result in F1 */
+ if (dp) {
+ gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, cpu_env);
+ } else {
+ gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, cpu_env);
+ }
+}
+
+static inline void gen_vfp_F1_neg(int dp)
+{
+ /* Like gen_vfp_neg() but put result in F1 */
+ if (dp) {
+ gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
+ } else {
+ gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
+ }
+}
+
static inline void gen_vfp_abs(int dp)
{
if (dp)
@@ -3021,27 +3041,34 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
for (;;) {
/* Perform the calculation. */
switch (op) {
- case 0: /* mac: fd + (fn * fm) */
- gen_vfp_mul(dp);
- gen_mov_F1_vreg(dp, rd);
+ case 0: /* VMLA: fd + (fn * fm) */
+ /* Note that order of inputs to the add matters for NaNs */
+ gen_vfp_F1_mul(dp);
+ gen_mov_F0_vreg(dp, rd);
gen_vfp_add(dp);
break;
- case 1: /* nmac: fd - (fn * fm) */
+ case 1: /* VMLS: fd + -(fn * fm) */
gen_vfp_mul(dp);
- gen_vfp_neg(dp);
- gen_mov_F1_vreg(dp, rd);
+ gen_vfp_F1_neg(dp);
+ gen_mov_F0_vreg(dp, rd);
gen_vfp_add(dp);
break;
- case 2: /* msc: -fd + (fn * fm) */
- gen_vfp_mul(dp);
- gen_mov_F1_vreg(dp, rd);
- gen_vfp_sub(dp);
+ case 2: /* VNMLS: -fd + (fn * fm) */
+ /* Note that it isn't valid to replace (-A + B) with (B - A)
+ * or similar plausible looking simplifications
+ * because this will give wrong results for NaNs.
+ */
+ gen_vfp_F1_mul(dp);
+ gen_mov_F0_vreg(dp, rd);
+ gen_vfp_neg(dp);
+ gen_vfp_add(dp);
break;
- case 3: /* nmsc: -fd - (fn * fm) */
+ case 3: /* VNMLA: -fd + -(fn * fm) */
gen_vfp_mul(dp);
+ gen_vfp_F1_neg(dp);
+ gen_mov_F0_vreg(dp, rd);
gen_vfp_neg(dp);
- gen_mov_F1_vreg(dp, rd);
- gen_vfp_sub(dp);
+ gen_vfp_add(dp);
break;
case 4: /* mul: fn * fm */
gen_vfp_mul(dp);
commit de1db2a172074a9ed7756d21823a70181b9a1dfb
Author: Brad Hards <bradh at frogmouth.net>
Date: Fri Apr 29 21:46:12 2011 +1000
doc: Add explanation that -alt-grab and -ctrl-grab affect special keys
Phillip Merensky reported that the special keys (e.g. Ctrl-Alt-f for full
screen) did not work correctly if -alt-grab is used.
BUG: 696530
Review of ui/sdl.c:sdl_refresh indicates that this is the intended behaviour,
so we should update the documentation to match the actual behaviour, as
suggested by Phillip in the bug report.
Signed-off-by: Brad Hards <bradh at frogmouth.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 86e017c..47e1991 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -278,7 +278,11 @@ targets do not need a disk image.
@c man begin OPTIONS
-During the graphical emulation, you can use the following keys:
+During the graphical emulation, you can use special key combinations to change
+modes. The default key mappings are shown below, but if you use @code{-alt-grab}
+then the modifier is Ctrl-Alt-Shift (instead of Ctrl-Alt) and if you use
+ at code{-ctrl-grab} then the modifier is the right Ctrl key (instead of Ctrl-Alt):
+
@table @key
@item Ctrl-Alt-f
@kindex Ctrl-Alt-f
diff --git a/qemu-options.hx b/qemu-options.hx
index 9f121ad..82e085a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -662,7 +662,8 @@ DEF("alt-grab", 0, QEMU_OPTION_alt_grab,
STEXI
@item -alt-grab
@findex -alt-grab
-Use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt).
+Use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt). Note that this also
+affects the special keys (for fullscreen, monitor-mode switching, etc).
ETEXI
DEF("ctrl-grab", 0, QEMU_OPTION_ctrl_grab,
@@ -671,7 +672,8 @@ DEF("ctrl-grab", 0, QEMU_OPTION_ctrl_grab,
STEXI
@item -ctrl-grab
@findex -ctrl-grab
-Use Right-Ctrl to grab mouse (instead of Ctrl-Alt).
+Use Right-Ctrl to grab mouse (instead of Ctrl-Alt). Note that this also
+affects the special keys (for fullscreen, monitor-mode switching, etc).
ETEXI
DEF("no-quit", 0, QEMU_OPTION_no_quit,
commit 091959defe5856d1ac52dc4c33ed01921484fbf8
Merge: 86f1f2a... be13cc7...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Sat May 14 16:54:59 2011 +0200
Merge branch 'ppc-next' of git://repo.or.cz/qemu/agraf
* 'ppc-next' of git://repo.or.cz/qemu/agraf:
PPC: Qdev'ify e500 pci
PPC MPC7544DS: Use new TLB helper function
PPC: Implement e500 (FSL) MMU
PPC: Add another 64 bits to instruction feature mask
PPC: Add GS MSR definition
PPC: Make MPC8544DS emulation work w/o KVM
PPC: Make MPC8544DS obey -cpu switch
Fix off-by-one error in sizing pSeries hcall table
ppc64: Fix out-of-tree builds
kvm: ppc: warn user on PAGE_SIZE mismatch
kvm: ppc: detect old headers
monitor: add PPC BookE SPRs
kvm: ppc: fixes for KVM_SET_SREGS on init
ppc64: Don't try to build sPAPR RTAS on Darwin
Place pseries vty devices at addresses more similar to existing machines
Make pSeries 'model' property more closely resemble real hardware
pseries: Increase maximum CPUs to 256
commit 86f1f2aee8fa8dd6f25ead09433fa0c888db6d37
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat May 14 07:14:57 2011 +0000
sparc64: fix incorrect BPcc target sign extension
Fix wrong number of bits used when sign extending the branch offset of BPcc
instructions.
Reported-by: Artyom Tarasenko <atar4qemu at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 9222cde..fe99f0b 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1893,7 +1893,7 @@ static void disas_sparc_insn(DisasContext * dc)
int cc;
target = GET_FIELD_SP(insn, 0, 18);
- target = sign_extend(target, 18);
+ target = sign_extend(target, 19);
target <<= 2;
cc = GET_FIELD_SP(insn, 20, 21);
if (cc == 0)
commit a2589e5cf288971d66afd0d41f5eefb735419890
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Tue Apr 26 18:44:20 2011 +0000
sparc64: fix wrpstate and wrtl on delay slot
Use TCG local to work around TCG register flush due to a branch.
Thanks to Artyom Tarasenko, Igor Kovalenko and Aurelien Jarno.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 3c958b2..9222cde 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -3505,16 +3505,28 @@ static void disas_sparc_insn(DisasContext * dc)
tcg_gen_mov_tl(cpu_tbr, cpu_tmp0);
break;
case 6: // pstate
- save_state(dc, cpu_cond);
- gen_helper_wrpstate(cpu_tmp0);
- dc->npc = DYNAMIC_PC;
+ {
+ TCGv r_tmp = tcg_temp_local_new();
+
+ tcg_gen_mov_tl(r_tmp, cpu_tmp0);
+ save_state(dc, cpu_cond);
+ gen_helper_wrpstate(r_tmp);
+ tcg_temp_free(r_tmp);
+ dc->npc = DYNAMIC_PC;
+ }
break;
case 7: // tl
- save_state(dc, cpu_cond);
- tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
- tcg_gen_st_i32(cpu_tmp32, cpu_env,
- offsetof(CPUSPARCState, tl));
- dc->npc = DYNAMIC_PC;
+ {
+ TCGv r_tmp = tcg_temp_local_new();
+
+ tcg_gen_mov_tl(r_tmp, cpu_tmp0);
+ save_state(dc, cpu_cond);
+ tcg_gen_trunc_tl_i32(cpu_tmp32, r_tmp);
+ tcg_temp_free(r_tmp);
+ tcg_gen_st_i32(cpu_tmp32, cpu_env,
+ offsetof(CPUSPARCState, tl));
+ dc->npc = DYNAMIC_PC;
+ }
break;
case 8: // pil
gen_helper_wrpil(cpu_tmp0);
commit 711c21280b2cb56060859cc574221a8bf40f908a
Merge: 89bb563... 2f17284...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Thu May 12 08:08:12 2011 -0500
Merge remote-tracking branch 'stefanha/trivial-patches' into staging
Conflicts:
cpu-all.h
commit 89bb563f6912b3f538d6bdf5833881ed7cdbd923
Merge: 0225e25... c962247...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Thu May 12 08:06:06 2011 -0500
Merge remote-tracking branch 'agraf/xen-next' into staging
commit be13cc7a352b74412374a554a15b32b105f6706b
Author: Alexander Graf <agraf at suse.de>
Date: Tue Aug 31 00:22:28 2010 +0200
PPC: Qdev'ify e500 pci
The e500 PCI controller isn't qdev'ified yet. This leads to severe issues
when running with -drive.
To be able to use a virtio disk with an e500 VM, let's convert the PCI
controller over to qdev.
Reviewed-by: Paul Brook <paul at codesourcery.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/ppce500.h b/hw/ppce500.h
deleted file mode 100644
index 24d49bb..0000000
--- a/hw/ppce500.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * QEMU PowerPC E500 emulation shared definitions
- *
- * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: Yu Liu, <yu.liu at freescale.com>
- *
- * This file is derived from hw/ppc440.h
- * the copyright for that material belongs to the original owners.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#if !defined(PPC_E500_H)
-#define PPC_E500_H
-
-PCIBus *ppce500_pci_init(qemu_irq *pic, target_phys_addr_t registers);
-
-#endif /* !defined(PPC_E500_H) */
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 96c37df..17b0165 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -29,9 +29,9 @@
#include "device_tree.h"
#include "openpic.h"
#include "ppc.h"
-#include "ppce500.h"
#include "loader.h"
#include "elf.h"
+#include "sysbus.h"
#define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb"
#define UIMAGE_LOAD_BASE 0
@@ -222,7 +222,8 @@ static void mpc8544ds_init(ram_addr_t ram_size,
target_long initrd_size=0;
int i=0;
unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
- qemu_irq *irqs, *mpic, *pci_irqs;
+ qemu_irq *irqs, *mpic;
+ DeviceState *dev;
struct boot_info *boot_info;
/* Setup CPU */
@@ -270,12 +271,11 @@ static void mpc8544ds_init(ram_addr_t ram_size,
}
/* PCI */
- pci_irqs = qemu_malloc(sizeof(qemu_irq) * 4);
- pci_irqs[0] = mpic[pci_irq_nrs[0]];
- pci_irqs[1] = mpic[pci_irq_nrs[1]];
- pci_irqs[2] = mpic[pci_irq_nrs[2]];
- pci_irqs[3] = mpic[pci_irq_nrs[3]];
- pci_bus = ppce500_pci_init(pci_irqs, MPC8544_PCI_REGS_BASE);
+ dev = sysbus_create_varargs("e500-pcihost", MPC8544_PCI_REGS_BASE,
+ mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]],
+ mpic[pci_irq_nrs[2]], mpic[pci_irq_nrs[3]],
+ NULL);
+ pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
if (!pci_bus)
printf("couldn't create PCI controller!\n");
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 83a20e4..069af96 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -15,7 +15,6 @@
*/
#include "hw.h"
-#include "ppce500.h"
#include "pci.h"
#include "pci_host.h"
#include "bswap.h"
@@ -29,7 +28,8 @@
#define PCIE500_CFGADDR 0x0
#define PCIE500_CFGDATA 0x4
#define PCIE500_REG_BASE 0xC00
-#define PCIE500_REG_SIZE (0x1000 - PCIE500_REG_BASE)
+#define PCIE500_ALL_SIZE 0x1000
+#define PCIE500_REG_SIZE (PCIE500_ALL_SIZE - PCIE500_REG_BASE)
#define PPCE500_PCI_CONFIG_ADDR 0x0
#define PPCE500_PCI_CONFIG_DATA 0x4
@@ -73,11 +73,15 @@ struct pci_inbound {
};
struct PPCE500PCIState {
+ PCIHostState pci_state;
struct pci_outbound pob[PPCE500_PCI_NR_POBS];
struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
uint32_t gasket_time;
- PCIHostState pci_state;
- PCIDevice *pci_dev;
+ qemu_irq irq[4];
+ /* mmio maps */
+ int cfgaddr;
+ int cfgdata;
+ int reg;
};
typedef struct PPCE500PCIState PPCE500PCIState;
@@ -250,7 +254,6 @@ static const VMStateDescription vmstate_ppce500_pci = {
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
- VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPCE500PCIState),
VMSTATE_STRUCT_ARRAY(pob, PPCE500PCIState, PPCE500_PCI_NR_POBS, 1,
vmstate_pci_outbound, struct pci_outbound),
VMSTATE_STRUCT_ARRAY(pib, PPCE500PCIState, PPCE500_PCI_NR_PIBS, 1,
@@ -260,60 +263,73 @@ static const VMStateDescription vmstate_ppce500_pci = {
}
};
-PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
+static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
+{
+ PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+ PPCE500PCIState *s = DO_UPCAST(PPCE500PCIState, pci_state, h);
+
+ cpu_register_physical_memory(base + PCIE500_CFGADDR, 4, s->cfgaddr);
+ cpu_register_physical_memory(base + PCIE500_CFGDATA, 4, s->cfgdata);
+ cpu_register_physical_memory(base + PCIE500_REG_BASE, PCIE500_REG_SIZE,
+ s->reg);
+}
+
+static int e500_pcihost_initfn(SysBusDevice *dev)
+{
+ PCIHostState *h;
+ PPCE500PCIState *s;
+ PCIBus *b;
+ int i;
+
+ h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+ s = DO_UPCAST(PPCE500PCIState, pci_state, h);
+
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
+ sysbus_init_irq(dev, &s->irq[i]);
+ }
+
+ b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
+ mpc85xx_pci_map_irq, s->irq, PCI_DEVFN(0x11, 0), 4);
+ s->pci_state.bus = b;
+
+ pci_create_simple(b, 0, "e500-host-bridge");
+
+ s->cfgaddr = pci_host_conf_register_mmio(&s->pci_state, DEVICE_BIG_ENDIAN);
+ s->cfgdata = pci_host_data_register_mmio(&s->pci_state,
+ DEVICE_LITTLE_ENDIAN);
+ s->reg = cpu_register_io_memory(e500_pci_reg_read, e500_pci_reg_write, s,
+ DEVICE_BIG_ENDIAN);
+ sysbus_init_mmio_cb(dev, PCIE500_ALL_SIZE, e500_pci_map);
+
+ return 0;
+}
+
+static int e500_host_bridge_initfn(PCIDevice *dev)
+{
+ pci_config_set_vendor_id(dev->config, PCI_VENDOR_ID_FREESCALE);
+ pci_config_set_device_id(dev->config, PCI_DEVICE_ID_MPC8533E);
+ pci_config_set_class(dev->config, PCI_CLASS_PROCESSOR_POWERPC);
+
+ return 0;
+}
+
+static PCIDeviceInfo e500_host_bridge_info = {
+ .qdev.name = "e500-host-bridge",
+ .qdev.desc = "Host bridge",
+ .qdev.size = sizeof(PCIDevice),
+ .init = e500_host_bridge_initfn,
+};
+
+static SysBusDeviceInfo e500_pcihost_info = {
+ .init = e500_pcihost_initfn,
+ .qdev.name = "e500-pcihost",
+ .qdev.size = sizeof(PPCE500PCIState),
+ .qdev.vmsd = &vmstate_ppce500_pci,
+};
+
+static void e500_pci_register(void)
{
- PPCE500PCIState *controller;
- PCIDevice *d;
- int index;
- static int ppce500_pci_id;
-
- controller = qemu_mallocz(sizeof(PPCE500PCIState));
-
- controller->pci_state.bus = pci_register_bus(NULL, "pci",
- mpc85xx_pci_set_irq,
- mpc85xx_pci_map_irq,
- pci_irqs, PCI_DEVFN(0x11, 0),
- 4);
- d = pci_register_device(controller->pci_state.bus,
- "host bridge", sizeof(PCIDevice),
- 0, NULL, NULL);
-
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_FREESCALE);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_MPC8533E);
- pci_config_set_class(d->config, PCI_CLASS_PROCESSOR_POWERPC);
-
- controller->pci_dev = d;
-
- /* CFGADDR */
- index = pci_host_conf_register_mmio(&controller->pci_state,
- DEVICE_BIG_ENDIAN);
- if (index < 0)
- goto free;
- cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
-
- /* CFGDATA */
- index = pci_host_data_register_mmio(&controller->pci_state,
- DEVICE_BIG_ENDIAN);
- if (index < 0)
- goto free;
- cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index);
-
- index = cpu_register_io_memory(e500_pci_reg_read,
- e500_pci_reg_write, controller,
- DEVICE_NATIVE_ENDIAN);
- if (index < 0)
- goto free;
- cpu_register_physical_memory(registers + PCIE500_REG_BASE,
- PCIE500_REG_SIZE, index);
-
- /* XXX load/save code not tested. */
- vmstate_register(&d->qdev, ppce500_pci_id++, &vmstate_ppce500_pci,
- controller);
-
- return controller->pci_state.bus;
-
-free:
- printf("%s error\n", __func__);
- qemu_free(controller);
- return NULL;
+ sysbus_register_withprop(&e500_pcihost_info);
+ pci_qdev_register(&e500_host_bridge_info);
}
+device_init(e500_pci_register);
commit 5389055a91dd2128279ba6ac6828264465eb19ee
Author: Alexander Graf <agraf at suse.de>
Date: Fri May 6 10:37:56 2011 +0200
PPC MPC7544DS: Use new TLB helper function
Now that we have some nice helpers that can find us a TLB entry, let's
use that on the machine initialization code, so we don't need to know
about the internals of the TLB array.
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 25c14c1..96c37df 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -179,7 +179,7 @@ static void mmubooke_create_initial_mapping(CPUState *env,
target_ulong va,
target_phys_addr_t pa)
{
- ppcemb_tlb_t *tlb = &env->tlb[512].tlbe;
+ ppcemb_tlb_t *tlb = booke206_get_tlbe(env, 1, 0, 0);
tlb->attr = 0;
tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
commit 01662f3e513399107c7278f2ee8f6ee4cf03fa70
Author: Alexander Graf <agraf at suse.de>
Date: Sat Apr 30 23:34:58 2011 +0200
PPC: Implement e500 (FSL) MMU
Most of the code to support e500 style MMUs is already in place, but
we're missing on some of the special TLB0-TLB1 handling code and slightly
different TLB modification.
This patch adds support for the FSL style MMU.
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 2a7431c..dd2f93f 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -108,8 +108,8 @@ enum powerpc_mmu_t {
POWERPC_MMU_MPC8xx = 0x00000007,
/* BookE MMU model */
POWERPC_MMU_BOOKE = 0x00000008,
- /* BookE FSL MMU model */
- POWERPC_MMU_BOOKE_FSL = 0x00000009,
+ /* BookE 2.06 MMU model */
+ POWERPC_MMU_BOOKE206 = 0x00000009,
/* PowerPC 601 MMU model (specific BATs format) */
POWERPC_MMU_601 = 0x0000000A,
#if defined(TARGET_PPC64)
@@ -608,6 +608,224 @@ enum {
#define vscr_sat (((env->vscr) >> VSCR_SAT) & 0x1)
/*****************************************************************************/
+/* BookE e500 MMU registers */
+
+#define MAS0_NV_SHIFT 0
+#define MAS0_NV_MASK (0xfff << MAS0_NV_SHIFT)
+
+#define MAS0_WQ_SHIFT 12
+#define MAS0_WQ_MASK (3 << MAS0_WQ_SHIFT)
+/* Write TLB entry regardless of reservation */
+#define MAS0_WQ_ALWAYS (0 << MAS0_WQ_SHIFT)
+/* Write TLB entry only already in use */
+#define MAS0_WQ_COND (1 << MAS0_WQ_SHIFT)
+/* Clear TLB entry */
+#define MAS0_WQ_CLR_RSRV (2 << MAS0_WQ_SHIFT)
+
+#define MAS0_HES_SHIFT 14
+#define MAS0_HES (1 << MAS0_HES_SHIFT)
+
+#define MAS0_ESEL_SHIFT 16
+#define MAS0_ESEL_MASK (0xfff << MAS0_ESEL_SHIFT)
+
+#define MAS0_TLBSEL_SHIFT 28
+#define MAS0_TLBSEL_MASK (3 << MAS0_TLBSEL_SHIFT)
+#define MAS0_TLBSEL_TLB0 (0 << MAS0_TLBSEL_SHIFT)
+#define MAS0_TLBSEL_TLB1 (1 << MAS0_TLBSEL_SHIFT)
+#define MAS0_TLBSEL_TLB2 (2 << MAS0_TLBSEL_SHIFT)
+#define MAS0_TLBSEL_TLB3 (3 << MAS0_TLBSEL_SHIFT)
+
+#define MAS0_ATSEL_SHIFT 31
+#define MAS0_ATSEL (1 << MAS0_ATSEL_SHIFT)
+#define MAS0_ATSEL_TLB 0
+#define MAS0_ATSEL_LRAT MAS0_ATSEL
+
+#define MAS1_TSIZE_SHIFT 8
+#define MAS1_TSIZE_MASK (0xf << MAS1_TSIZE_SHIFT)
+
+#define MAS1_TS_SHIFT 12
+#define MAS1_TS (1 << MAS1_TS_SHIFT)
+
+#define MAS1_IND_SHIFT 13
+#define MAS1_IND (1 << MAS1_IND_SHIFT)
+
+#define MAS1_TID_SHIFT 16
+#define MAS1_TID_MASK (0x3fff << MAS1_TID_SHIFT)
+
+#define MAS1_IPROT_SHIFT 30
+#define MAS1_IPROT (1 << MAS1_IPROT_SHIFT)
+
+#define MAS1_VALID_SHIFT 31
+#define MAS1_VALID 0x80000000
+
+#define MAS2_EPN_SHIFT 12
+#define MAS2_EPN_MASK (0xfffff << MAS2_EPN_SHIFT)
+
+#define MAS2_ACM_SHIFT 6
+#define MAS2_ACM (1 << MAS2_ACM_SHIFT)
+
+#define MAS2_VLE_SHIFT 5
+#define MAS2_VLE (1 << MAS2_VLE_SHIFT)
+
+#define MAS2_W_SHIFT 4
+#define MAS2_W (1 << MAS2_W_SHIFT)
+
+#define MAS2_I_SHIFT 3
+#define MAS2_I (1 << MAS2_I_SHIFT)
+
+#define MAS2_M_SHIFT 2
+#define MAS2_M (1 << MAS2_M_SHIFT)
+
+#define MAS2_G_SHIFT 1
+#define MAS2_G (1 << MAS2_G_SHIFT)
+
+#define MAS2_E_SHIFT 0
+#define MAS2_E (1 << MAS2_E_SHIFT)
+
+#define MAS3_RPN_SHIFT 12
+#define MAS3_RPN_MASK (0xfffff << MAS3_RPN_SHIFT)
+
+#define MAS3_U0 0x00000200
+#define MAS3_U1 0x00000100
+#define MAS3_U2 0x00000080
+#define MAS3_U3 0x00000040
+#define MAS3_UX 0x00000020
+#define MAS3_SX 0x00000010
+#define MAS3_UW 0x00000008
+#define MAS3_SW 0x00000004
+#define MAS3_UR 0x00000002
+#define MAS3_SR 0x00000001
+#define MAS3_SPSIZE_SHIFT 1
+#define MAS3_SPSIZE_MASK (0x3e << MAS3_SPSIZE_SHIFT)
+
+#define MAS4_TLBSELD_SHIFT MAS0_TLBSEL_SHIFT
+#define MAS4_TLBSELD_MASK MAS0_TLBSEL_MASK
+#define MAS4_TIDSELD_MASK 0x00030000
+#define MAS4_TIDSELD_PID0 0x00000000
+#define MAS4_TIDSELD_PID1 0x00010000
+#define MAS4_TIDSELD_PID2 0x00020000
+#define MAS4_TIDSELD_PIDZ 0x00030000
+#define MAS4_INDD 0x00008000 /* Default IND */
+#define MAS4_TSIZED_SHIFT MAS1_TSIZE_SHIFT
+#define MAS4_TSIZED_MASK MAS1_TSIZE_MASK
+#define MAS4_ACMD 0x00000040
+#define MAS4_VLED 0x00000020
+#define MAS4_WD 0x00000010
+#define MAS4_ID 0x00000008
+#define MAS4_MD 0x00000004
+#define MAS4_GD 0x00000002
+#define MAS4_ED 0x00000001
+#define MAS4_WIMGED_MASK 0x0000001f /* Default WIMGE */
+#define MAS4_WIMGED_SHIFT 0
+
+#define MAS5_SGS 0x80000000
+#define MAS5_SLPID_MASK 0x00000fff
+
+#define MAS6_SPID0 0x3fff0000
+#define MAS6_SPID1 0x00007ffe
+#define MAS6_ISIZE(x) MAS1_TSIZE(x)
+#define MAS6_SAS 0x00000001
+#define MAS6_SPID MAS6_SPID0
+#define MAS6_SIND 0x00000002 /* Indirect page */
+#define MAS6_SIND_SHIFT 1
+#define MAS6_SPID_MASK 0x3fff0000
+#define MAS6_SPID_SHIFT 16
+#define MAS6_ISIZE_MASK 0x00000f80
+#define MAS6_ISIZE_SHIFT 7
+
+#define MAS7_RPN 0xffffffff
+
+#define MAS8_TGS 0x80000000
+#define MAS8_VF 0x40000000
+#define MAS8_TLBPID 0x00000fff
+
+/* Bit definitions for MMUCFG */
+#define MMUCFG_MAVN 0x00000003 /* MMU Architecture Version Number */
+#define MMUCFG_MAVN_V1 0x00000000 /* v1.0 */
+#define MMUCFG_MAVN_V2 0x00000001 /* v2.0 */
+#define MMUCFG_NTLBS 0x0000000c /* Number of TLBs */
+#define MMUCFG_PIDSIZE 0x000007c0 /* PID Reg Size */
+#define MMUCFG_TWC 0x00008000 /* TLB Write Conditional (v2.0) */
+#define MMUCFG_LRAT 0x00010000 /* LRAT Supported (v2.0) */
+#define MMUCFG_RASIZE 0x00fe0000 /* Real Addr Size */
+#define MMUCFG_LPIDSIZE 0x0f000000 /* LPID Reg Size */
+
+/* Bit definitions for MMUCSR0 */
+#define MMUCSR0_TLB1FI 0x00000002 /* TLB1 Flash invalidate */
+#define MMUCSR0_TLB0FI 0x00000004 /* TLB0 Flash invalidate */
+#define MMUCSR0_TLB2FI 0x00000040 /* TLB2 Flash invalidate */
+#define MMUCSR0_TLB3FI 0x00000020 /* TLB3 Flash invalidate */
+#define MMUCSR0_TLBFI (MMUCSR0_TLB0FI | MMUCSR0_TLB1FI | \
+ MMUCSR0_TLB2FI | MMUCSR0_TLB3FI)
+#define MMUCSR0_TLB0PS 0x00000780 /* TLB0 Page Size */
+#define MMUCSR0_TLB1PS 0x00007800 /* TLB1 Page Size */
+#define MMUCSR0_TLB2PS 0x00078000 /* TLB2 Page Size */
+#define MMUCSR0_TLB3PS 0x00780000 /* TLB3 Page Size */
+
+/* TLBnCFG encoding */
+#define TLBnCFG_N_ENTRY 0x00000fff /* number of entries */
+#define TLBnCFG_HES 0x00002000 /* HW select supported */
+#define TLBnCFG_AVAIL 0x00004000 /* variable page size */
+#define TLBnCFG_IPROT 0x00008000 /* IPROT supported */
+#define TLBnCFG_GTWE 0x00010000 /* Guest can write */
+#define TLBnCFG_IND 0x00020000 /* IND entries supported */
+#define TLBnCFG_PT 0x00040000 /* Can load from page table */
+#define TLBnCFG_MINSIZE 0x00f00000 /* Minimum Page Size (v1.0) */
+#define TLBnCFG_MINSIZE_SHIFT 20
+#define TLBnCFG_MAXSIZE 0x000f0000 /* Maximum Page Size (v1.0) */
+#define TLBnCFG_MAXSIZE_SHIFT 16
+#define TLBnCFG_ASSOC 0xff000000 /* Associativity */
+#define TLBnCFG_ASSOC_SHIFT 24
+
+/* TLBnPS encoding */
+#define TLBnPS_4K 0x00000004
+#define TLBnPS_8K 0x00000008
+#define TLBnPS_16K 0x00000010
+#define TLBnPS_32K 0x00000020
+#define TLBnPS_64K 0x00000040
+#define TLBnPS_128K 0x00000080
+#define TLBnPS_256K 0x00000100
+#define TLBnPS_512K 0x00000200
+#define TLBnPS_1M 0x00000400
+#define TLBnPS_2M 0x00000800
+#define TLBnPS_4M 0x00001000
+#define TLBnPS_8M 0x00002000
+#define TLBnPS_16M 0x00004000
+#define TLBnPS_32M 0x00008000
+#define TLBnPS_64M 0x00010000
+#define TLBnPS_128M 0x00020000
+#define TLBnPS_256M 0x00040000
+#define TLBnPS_512M 0x00080000
+#define TLBnPS_1G 0x00100000
+#define TLBnPS_2G 0x00200000
+#define TLBnPS_4G 0x00400000
+#define TLBnPS_8G 0x00800000
+#define TLBnPS_16G 0x01000000
+#define TLBnPS_32G 0x02000000
+#define TLBnPS_64G 0x04000000
+#define TLBnPS_128G 0x08000000
+#define TLBnPS_256G 0x10000000
+
+/* tlbilx action encoding */
+#define TLBILX_T_ALL 0
+#define TLBILX_T_TID 1
+#define TLBILX_T_FULLMATCH 3
+#define TLBILX_T_CLASS0 4
+#define TLBILX_T_CLASS1 5
+#define TLBILX_T_CLASS2 6
+#define TLBILX_T_CLASS3 7
+
+/* BookE 2.06 helper defines */
+
+#define BOOKE206_FLUSH_TLB0 (1 << 0)
+#define BOOKE206_FLUSH_TLB1 (1 << 1)
+#define BOOKE206_FLUSH_TLB2 (1 << 2)
+#define BOOKE206_FLUSH_TLB3 (1 << 3)
+
+/* number of possible TLBs */
+#define BOOKE206_MAX_TLBN 4
+
+/*****************************************************************************/
/* The whole PowerPC CPU context */
#define NB_MMU_MODES 3
@@ -678,7 +896,7 @@ struct CPUPPCState {
int nb_BATs;
target_ulong DBAT[2][8];
target_ulong IBAT[2][8];
- /* PowerPC TLB registers (for 4xx and 60x software driven TLBs) */
+ /* PowerPC TLB registers (for 4xx, e500 and 60x software driven TLBs) */
int nb_tlb; /* Total number of TLB */
int tlb_per_way; /* Speed-up helper: used to avoid divisions at run time */
int nb_ways; /* Number of ways in the TLB set */
@@ -856,6 +1074,10 @@ void store_40x_dbcr0 (CPUPPCState *env, uint32_t val);
void store_40x_sler (CPUPPCState *env, uint32_t val);
void store_booke_tcr (CPUPPCState *env, target_ulong val);
void store_booke_tsr (CPUPPCState *env, target_ulong val);
+void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot);
+int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
+ target_phys_addr_t *raddrp, target_ulong address,
+ uint32_t pid, int ext, int i);
void ppc_tlb_invalidate_all (CPUPPCState *env);
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
#if defined(TARGET_PPC64)
@@ -1547,6 +1769,11 @@ enum {
PPC_DCRUX = 0x4000000000000000ULL,
/* popcntw and popcntd instructions */
PPC_POPCNTWD = 0x8000000000000000ULL,
+
+ /* extended type values */
+
+ /* BookE 2.06 PowerPC specification */
+ PPC2_BOOKE206 = 0x0000000000000001ULL,
};
/*****************************************************************************/
@@ -1699,6 +1926,77 @@ static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
#endif
}
+#if !defined(CONFIG_USER_ONLY)
+static inline int booke206_tlbe_id(CPUState *env, ppcemb_tlb_t *tlbe)
+{
+ ulong tlbel = (ulong)tlbe;
+ ulong tlbl = (ulong)env->tlb;
+
+ return (tlbel - tlbl) / sizeof(env->tlb[0]);
+}
+
+static inline int booke206_tlb_size(CPUState *env, int tlbn)
+{
+ uint32_t tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
+ int r = tlbncfg & TLBnCFG_N_ENTRY;
+ return r;
+}
+
+static inline int booke206_tlb_ways(CPUState *env, int tlbn)
+{
+ uint32_t tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
+ int r = tlbncfg >> TLBnCFG_ASSOC_SHIFT;
+ return r;
+}
+
+static inline int booke206_tlbe_to_tlbn(CPUState *env, ppcemb_tlb_t *tlbe)
+{
+ int id = booke206_tlbe_id(env, tlbe);
+ int end = 0;
+ int i;
+
+ for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+ end += booke206_tlb_size(env, i);
+ if (id < end) {
+ return i;
+ }
+ }
+
+ cpu_abort(env, "Unknown TLBe: %d\n", id);
+ return 0;
+}
+
+static inline int booke206_tlbe_to_way(CPUState *env, ppcemb_tlb_t *tlb)
+{
+ int tlbn = booke206_tlbe_to_tlbn(env, tlb);
+ int tlbid = booke206_tlbe_id(env, tlb);
+ return tlbid & (booke206_tlb_ways(env, tlbn) - 1);
+}
+
+static inline ppcemb_tlb_t *booke206_get_tlbe(CPUState *env, const int tlbn,
+ target_ulong ea, int way)
+{
+ int r;
+ uint32_t ways = booke206_tlb_ways(env, tlbn);
+ int ways_bits = ffs(ways) - 1;
+ int tlb_bits = ffs(booke206_tlb_size(env, tlbn)) - 1;
+ int i;
+
+ way &= ways - 1;
+ ea >>= MAS2_EPN_SHIFT;
+ ea &= (1 << (tlb_bits - ways_bits)) - 1;
+ r = (ea << ways_bits) | way;
+
+ /* bump up to tlbn index */
+ for (i = 0; i < tlbn; i++) {
+ r += booke206_tlb_size(env, i);
+ }
+
+ return &env->tlb[r].tlbe;
+}
+
+#endif
+
extern void (*cpu_ppc_hypercall)(CPUState *);
#endif /* !defined (__CPU_PPC_H__) */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 5e4030b..4238be6 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -993,10 +993,10 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
}
/* Generic TLB check function for embedded PowerPC implementations */
-static inline int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
- target_phys_addr_t *raddrp,
- target_ulong address, uint32_t pid, int ext,
- int i)
+int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
+ target_phys_addr_t *raddrp,
+ target_ulong address, uint32_t pid, int ext,
+ int i)
{
target_ulong mask;
@@ -1006,8 +1006,8 @@ static inline int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
}
mask = ~(tlb->size - 1);
LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
- " " TARGET_FMT_lx " %u\n", __func__, i, address, pid, tlb->EPN,
- mask, (uint32_t)tlb->PID);
+ " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
+ mask, (uint32_t)tlb->PID, tlb->prot);
/* Check PID */
if (tlb->PID != 0 && tlb->PID != pid)
return -1;
@@ -1153,48 +1153,164 @@ void store_40x_sler (CPUPPCState *env, uint32_t val)
env->spr[SPR_405_SLER] = val;
}
+static inline int mmubooke_check_tlb (CPUState *env, ppcemb_tlb_t *tlb,
+ target_phys_addr_t *raddr, int *prot,
+ target_ulong address, int rw,
+ int access_type, int i)
+{
+ int ret, _prot;
+
+ if (ppcemb_tlb_check(env, tlb, raddr, address,
+ env->spr[SPR_BOOKE_PID],
+ !env->nb_pids, i) >= 0) {
+ goto found_tlb;
+ }
+
+ if (env->spr[SPR_BOOKE_PID1] &&
+ ppcemb_tlb_check(env, tlb, raddr, address,
+ env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
+ goto found_tlb;
+ }
+
+ if (env->spr[SPR_BOOKE_PID2] &&
+ ppcemb_tlb_check(env, tlb, raddr, address,
+ env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
+ goto found_tlb;
+ }
+
+ LOG_SWTLB("%s: TLB entry not found\n", __func__);
+ return -1;
+
+found_tlb:
+
+ if (msr_pr != 0) {
+ _prot = tlb->prot & 0xF;
+ } else {
+ _prot = (tlb->prot >> 4) & 0xF;
+ }
+
+ /* Check the address space */
+ if (access_type == ACCESS_CODE) {
+ if (msr_ir != (tlb->attr & 1)) {
+ LOG_SWTLB("%s: AS doesn't match\n", __func__);
+ return -1;
+ }
+
+ *prot = _prot;
+ if (_prot & PAGE_EXEC) {
+ LOG_SWTLB("%s: good TLB!\n", __func__);
+ return 0;
+ }
+
+ LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
+ ret = -3;
+ } else {
+ if (msr_dr != (tlb->attr & 1)) {
+ LOG_SWTLB("%s: AS doesn't match\n", __func__);
+ return -1;
+ }
+
+ *prot = _prot;
+ if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
+ LOG_SWTLB("%s: found TLB!\n", __func__);
+ return 0;
+ }
+
+ LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
+ ret = -2;
+ }
+
+ return ret;
+}
+
static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
target_ulong address, int rw,
int access_type)
{
ppcemb_tlb_t *tlb;
target_phys_addr_t raddr;
- int i, prot, ret;
+ int i, ret;
ret = -1;
raddr = (target_phys_addr_t)-1ULL;
for (i = 0; i < env->nb_tlb; i++) {
tlb = &env->tlb[i].tlbe;
- if (ppcemb_tlb_check(env, tlb, &raddr, address,
- env->spr[SPR_BOOKE_PID], 1, i) < 0)
- continue;
- if (msr_pr != 0)
- prot = tlb->prot & 0xF;
- else
- prot = (tlb->prot >> 4) & 0xF;
- /* Check the address space */
- if (access_type == ACCESS_CODE) {
- if (msr_ir != (tlb->attr & 1))
- continue;
- ctx->prot = prot;
- if (prot & PAGE_EXEC) {
- ret = 0;
- break;
+ ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
+ access_type, i);
+ if (!ret) {
+ break;
+ }
+ }
+
+ if (ret >= 0) {
+ ctx->raddr = raddr;
+ LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
+ " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
+ ret);
+ } else {
+ LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
+ " %d %d\n", __func__, address, raddr, ctx->prot, ret);
+ }
+
+ return ret;
+}
+
+void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
+{
+ int tlb_size;
+ int i, j;
+ ppc_tlb_t *tlb = env->tlb;
+
+ for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+ if (flags & (1 << i)) {
+ tlb_size = booke206_tlb_size(env, i);
+ for (j = 0; j < tlb_size; j++) {
+ if (!check_iprot || !(tlb[j].tlbe.attr & MAS1_IPROT)) {
+ tlb[j].tlbe.prot = 0;
+ }
}
- ret = -3;
- } else {
- if (msr_dr != (tlb->attr & 1))
- continue;
- ctx->prot = prot;
- if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
- ret = 0;
- break;
+ }
+ tlb += booke206_tlb_size(env, i);
+ }
+
+ tlb_flush(env, 1);
+}
+
+static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
+ target_ulong address, int rw,
+ int access_type)
+{
+ ppcemb_tlb_t *tlb;
+ target_phys_addr_t raddr;
+ int i, j, ret;
+
+ ret = -1;
+ raddr = (target_phys_addr_t)-1ULL;
+
+ for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+ int ways = booke206_tlb_ways(env, i);
+
+ for (j = 0; j < ways; j++) {
+ tlb = booke206_get_tlbe(env, i, address, j);
+ ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
+ access_type, j);
+ if (ret != -1) {
+ goto found_tlb;
}
- ret = -2;
}
}
- if (ret >= 0)
+
+found_tlb:
+
+ if (ret >= 0) {
ctx->raddr = raddr;
+ LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
+ " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
+ ret);
+ } else {
+ LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
+ " %d %d\n", __func__, address, raddr, ctx->prot, ret);
+ }
return ret;
}
@@ -1254,9 +1370,8 @@ static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
/* XXX: TODO */
cpu_abort(env, "MPC8xx MMU model is not implemented\n");
break;
- case POWERPC_MMU_BOOKE_FSL:
- /* XXX: TODO */
- cpu_abort(env, "BookE FSL MMU model not implemented\n");
+ case POWERPC_MMU_BOOKE206:
+ cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
break;
default:
cpu_abort(env, "Unknown or invalid MMU model\n");
@@ -1281,6 +1396,9 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
IS and DS bits only affect the address space. */
ret = mmubooke_get_physical_address(env, ctx, eaddr,
rw, access_type);
+ } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
+ ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
+ access_type);
} else {
/* No address translation. */
ret = check_physical(env, ctx, eaddr, rw);
@@ -1314,14 +1432,14 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
ret = mmubooke_get_physical_address(env, ctx, eaddr,
rw, access_type);
break;
+ case POWERPC_MMU_BOOKE206:
+ ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
+ access_type);
+ break;
case POWERPC_MMU_MPC8xx:
/* XXX: TODO */
cpu_abort(env, "MPC8xx MMU model is not implemented\n");
break;
- case POWERPC_MMU_BOOKE_FSL:
- /* XXX: TODO */
- cpu_abort(env, "BookE FSL MMU model not implemented\n");
- return -1;
case POWERPC_MMU_REAL:
cpu_abort(env, "PowerPC in real mode do not do any translation\n");
return -1;
@@ -1348,6 +1466,46 @@ target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
return ctx.raddr & TARGET_PAGE_MASK;
}
+static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
+ int rw)
+{
+ env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
+ env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
+ env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
+ env->spr[SPR_BOOKE_MAS3] = 0;
+ env->spr[SPR_BOOKE_MAS6] = 0;
+ env->spr[SPR_BOOKE_MAS7] = 0;
+
+ /* AS */
+ if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
+ env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
+ env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
+ }
+
+ env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
+ env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
+
+ switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
+ case MAS4_TIDSELD_PID0:
+ env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
+ break;
+ case MAS4_TIDSELD_PID1:
+ env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
+ break;
+ case MAS4_TIDSELD_PID2:
+ env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
+ break;
+ }
+
+ env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
+
+ /* next victim logic */
+ env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
+ env->last_way++;
+ env->last_way &= booke206_tlb_ways(env, 0) - 1;
+ env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
+}
+
/* Perform address translation */
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int mmu_idx, int is_softmmu)
@@ -1403,15 +1561,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
env->exception_index = POWERPC_EXCP_ISI;
env->error_code = 0x40000000;
break;
+ case POWERPC_MMU_BOOKE206:
+ booke206_update_mas_tlb_miss(env, address, rw);
+ /* fall through */
case POWERPC_MMU_BOOKE:
env->exception_index = POWERPC_EXCP_ITLB;
env->error_code = 0;
env->spr[SPR_BOOKE_DEAR] = address;
return -1;
- case POWERPC_MMU_BOOKE_FSL:
- /* XXX: TODO */
- cpu_abort(env, "BookE FSL MMU model is not implemented\n");
- return -1;
case POWERPC_MMU_MPC8xx:
/* XXX: TODO */
cpu_abort(env, "MPC8xx MMU model is not implemented\n");
@@ -1432,7 +1589,8 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
break;
case -3:
/* No execute protection violation */
- if (env->mmu_model == POWERPC_MMU_BOOKE) {
+ if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
+ (env->mmu_model == POWERPC_MMU_BOOKE206)) {
env->spr[SPR_BOOKE_ESR] = 0x00000000;
}
env->exception_index = POWERPC_EXCP_ISI;
@@ -1522,16 +1680,15 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
/* XXX: TODO */
cpu_abort(env, "MPC8xx MMU model is not implemented\n");
break;
+ case POWERPC_MMU_BOOKE206:
+ booke206_update_mas_tlb_miss(env, address, rw);
+ /* fall through */
case POWERPC_MMU_BOOKE:
env->exception_index = POWERPC_EXCP_DTLB;
env->error_code = 0;
env->spr[SPR_BOOKE_DEAR] = address;
env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
return -1;
- case POWERPC_MMU_BOOKE_FSL:
- /* XXX: TODO */
- cpu_abort(env, "BookE FSL MMU model is not implemented\n");
- return -1;
case POWERPC_MMU_REAL:
cpu_abort(env, "PowerPC in real mode should never raise "
"any MMU exceptions\n");
@@ -1551,7 +1708,8 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
if (rw) {
env->spr[SPR_40x_ESR] |= 0x00800000;
}
- } else if (env->mmu_model == POWERPC_MMU_BOOKE) {
+ } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
+ (env->mmu_model == POWERPC_MMU_BOOKE206)) {
env->spr[SPR_BOOKE_DEAR] = address;
env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
} else {
@@ -1822,10 +1980,8 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
case POWERPC_MMU_BOOKE:
tlb_flush(env, 1);
break;
- case POWERPC_MMU_BOOKE_FSL:
- /* XXX: TODO */
- if (!kvm_enabled())
- cpu_abort(env, "BookE MMU model is not implemented\n");
+ case POWERPC_MMU_BOOKE206:
+ booke206_flush_tlb(env, -1, 0);
break;
case POWERPC_MMU_32B:
case POWERPC_MMU_601:
@@ -1869,9 +2025,9 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
/* XXX: TODO */
cpu_abort(env, "BookE MMU model is not implemented\n");
break;
- case POWERPC_MMU_BOOKE_FSL:
+ case POWERPC_MMU_BOOKE206:
/* XXX: TODO */
- cpu_abort(env, "BookE FSL MMU model is not implemented\n");
+ cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
break;
case POWERPC_MMU_32B:
case POWERPC_MMU_601:
@@ -2589,7 +2745,8 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
env->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
- if (env->mmu_model == POWERPC_MMU_BOOKE) {
+ if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
+ (env->mmu_model == POWERPC_MMU_BOOKE206)) {
/* XXX: The BookE changes address space when switching modes,
we should probably implement that as different MMU indexes,
but for the moment we do it the slow way and flush all. */
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 7c02be9..51c99c8 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -334,6 +334,12 @@ DEF_HELPER_1(4xx_tlbsx, tl, tl)
DEF_HELPER_2(440_tlbre, tl, i32, tl)
DEF_HELPER_3(440_tlbwe, void, i32, tl, tl)
DEF_HELPER_1(440_tlbsx, tl, tl)
+DEF_HELPER_0(booke206_tlbre, void)
+DEF_HELPER_0(booke206_tlbwe, void)
+DEF_HELPER_1(booke206_tlbsx, void, tl)
+DEF_HELPER_1(booke206_tlbivax, void, tl)
+DEF_HELPER_1(booke206_tlbflush, void, i32)
+DEF_HELPER_2(booke_setpid, void, i32, tl)
DEF_HELPER_1(6xx_tlbd, void, tl)
DEF_HELPER_1(6xx_tlbi, void, tl)
DEF_HELPER_1(74xx_tlbd, void, tl)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index d5db484..e165444 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -4206,4 +4206,300 @@ target_ulong helper_440_tlbsx (target_ulong address)
return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
}
+/* PowerPC BookE 2.06 TLB management */
+
+static ppcemb_tlb_t *booke206_cur_tlb(CPUState *env)
+{
+ uint32_t tlbncfg = 0;
+ int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
+ int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
+ int tlb;
+
+ tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
+ tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
+
+ if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
+ cpu_abort(env, "we don't support HES yet\n");
+ }
+
+ return booke206_get_tlbe(env, tlb, ea, esel);
+}
+
+static inline target_phys_addr_t booke206_tlb_to_page_size(int size)
+{
+ return (1 << (size << 1)) << 10;
+}
+
+static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size)
+{
+ return (ffs(size >> 10) - 1) >> 1;
+}
+
+void helper_booke_setpid(uint32_t pidn, target_ulong pid)
+{
+ env->spr[pidn] = pid;
+ /* changing PIDs mean we're in a different address space now */
+ tlb_flush(env, 1);
+}
+
+void helper_booke206_tlbwe(void)
+{
+ uint32_t tlbncfg, tlbn;
+ ppcemb_tlb_t *tlb;
+ target_phys_addr_t rpn;
+ int tlbe_size;
+
+ switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
+ case MAS0_WQ_ALWAYS:
+ /* good to go, write that entry */
+ break;
+ case MAS0_WQ_COND:
+ /* XXX check if reserved */
+ if (0) {
+ return;
+ }
+ break;
+ case MAS0_WQ_CLR_RSRV:
+ /* XXX clear entry */
+ return;
+ default:
+ /* no idea what to do */
+ return;
+ }
+
+ if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
+ !msr_gs) {
+ /* XXX we don't support direct LRAT setting yet */
+ fprintf(stderr, "cpu: don't support LRAT setting yet\n");
+ return;
+ }
+
+ tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
+ tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
+
+ tlb = booke206_cur_tlb(env);
+
+ if (msr_gs) {
+ cpu_abort(env, "missing HV implementation\n");
+ } else {
+ rpn = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
+ (env->spr[SPR_BOOKE_MAS3] & 0xfffff000);
+ }
+ tlb->RPN = rpn;
+
+ tlb->PID = (env->spr[SPR_BOOKE_MAS1] & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
+ if (tlbncfg & TLBnCFG_AVAIL) {
+ tlbe_size = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK)
+ >> MAS1_TSIZE_SHIFT;
+ } else {
+ tlbe_size = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
+ }
+
+ tlb->size = booke206_tlb_to_page_size(tlbe_size);
+ tlb->EPN = (uint32_t)(env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
+ tlb->attr = env->spr[SPR_BOOKE_MAS2] & (MAS2_ACM | MAS2_VLE | MAS2_W |
+ MAS2_I | MAS2_M | MAS2_G | MAS2_E)
+ << 1;
+
+ if (tlbncfg & TLBnCFG_IPROT) {
+ tlb->attr |= env->spr[SPR_BOOKE_MAS1] & MAS1_IPROT;
+ }
+ tlb->attr |= (env->spr[SPR_BOOKE_MAS3] &
+ ((MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3)) << 8);
+ if (env->spr[SPR_BOOKE_MAS1] & MAS1_TS) {
+ tlb->attr |= 1;
+ }
+
+ tlb->prot = 0;
+
+ if (env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) {
+ tlb->prot |= PAGE_VALID;
+ }
+ if (env->spr[SPR_BOOKE_MAS3] & MAS3_UX) {
+ tlb->prot |= PAGE_EXEC;
+ }
+ if (env->spr[SPR_BOOKE_MAS3] & MAS3_SX) {
+ tlb->prot |= PAGE_EXEC << 4;
+ }
+ if (env->spr[SPR_BOOKE_MAS3] & MAS3_UW) {
+ tlb->prot |= PAGE_WRITE;
+ }
+ if (env->spr[SPR_BOOKE_MAS3] & MAS3_SW) {
+ tlb->prot |= PAGE_WRITE << 4;
+ }
+ if (env->spr[SPR_BOOKE_MAS3] & MAS3_UR) {
+ tlb->prot |= PAGE_READ;
+ }
+ if (env->spr[SPR_BOOKE_MAS3] & MAS3_SR) {
+ tlb->prot |= PAGE_READ << 4;
+ }
+
+ if (tlb->size == TARGET_PAGE_SIZE) {
+ tlb_flush_page(env, tlb->EPN);
+ } else {
+ tlb_flush(env, 1);
+ }
+}
+
+static inline void booke206_tlb_to_mas(CPUState *env, ppcemb_tlb_t *tlb)
+{
+ int tlbn = booke206_tlbe_to_tlbn(env, tlb);
+ int way = booke206_tlbe_to_way(env, tlb);
+
+ env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
+ env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
+
+ env->spr[SPR_BOOKE_MAS1] = MAS1_VALID;
+ env->spr[SPR_BOOKE_MAS2] = 0;
+
+ env->spr[SPR_BOOKE_MAS7] = (uint64_t)tlb->RPN >> 32;
+ env->spr[SPR_BOOKE_MAS3] = tlb->RPN;
+ env->spr[SPR_BOOKE_MAS1] |= tlb->PID << MAS1_TID_SHIFT;
+ env->spr[SPR_BOOKE_MAS1] |= booke206_page_size_to_tlb(tlb->size)
+ << MAS1_TSIZE_SHIFT;
+ env->spr[SPR_BOOKE_MAS1] |= tlb->attr & MAS1_IPROT;
+ if (tlb->attr & 1) {
+ env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
+ }
+
+ env->spr[SPR_BOOKE_MAS2] = tlb->EPN;
+ env->spr[SPR_BOOKE_MAS2] |= (tlb->attr >> 1) &
+ (MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E);
+
+ if (tlb->prot & PAGE_EXEC) {
+ env->spr[SPR_BOOKE_MAS3] |= MAS3_UX;
+ }
+ if (tlb->prot & (PAGE_EXEC << 4)) {
+ env->spr[SPR_BOOKE_MAS3] |= MAS3_SX;
+ }
+ if (tlb->prot & PAGE_WRITE) {
+ env->spr[SPR_BOOKE_MAS3] |= MAS3_UW;
+ }
+ if (tlb->prot & (PAGE_WRITE << 4)) {
+ env->spr[SPR_BOOKE_MAS3] |= MAS3_SW;
+ }
+ if (tlb->prot & PAGE_READ) {
+ env->spr[SPR_BOOKE_MAS3] |= MAS3_UR;
+ }
+ if (tlb->prot & (PAGE_READ << 4)) {
+ env->spr[SPR_BOOKE_MAS3] |= MAS3_SR;
+ }
+
+ env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
+}
+
+void helper_booke206_tlbre(void)
+{
+ ppcemb_tlb_t *tlb = NULL;
+
+ tlb = booke206_cur_tlb(env);
+ booke206_tlb_to_mas(env, tlb);
+}
+
+void helper_booke206_tlbsx(target_ulong address)
+{
+ ppcemb_tlb_t *tlb = NULL;
+ int i, j;
+ target_phys_addr_t raddr;
+ uint32_t spid, sas;
+
+ spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
+ sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
+
+ for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+ int ways = booke206_tlb_ways(env, i);
+
+ for (j = 0; j < ways; j++) {
+ tlb = booke206_get_tlbe(env, i, address, j);
+
+ if (ppcemb_tlb_check(env, tlb, &raddr, address, spid, 0, j)) {
+ continue;
+ }
+
+ if (sas != (tlb->attr & MAS6_SAS)) {
+ continue;
+ }
+
+ booke206_tlb_to_mas(env, tlb);
+ return;
+ }
+ }
+
+ /* no entry found, fill with defaults */
+ env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
+ env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
+ env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
+ env->spr[SPR_BOOKE_MAS3] = 0;
+ env->spr[SPR_BOOKE_MAS7] = 0;
+
+ if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
+ env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
+ }
+
+ env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
+ << MAS1_TID_SHIFT;
+
+ /* next victim logic */
+ env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
+ env->last_way++;
+ env->last_way &= booke206_tlb_ways(env, 0) - 1;
+ env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
+}
+
+static inline void booke206_invalidate_ea_tlb(CPUState *env, int tlbn,
+ uint32_t ea)
+{
+ int i;
+ int ways = booke206_tlb_ways(env, tlbn);
+
+ for (i = 0; i < ways; i++) {
+ ppcemb_tlb_t *tlb = booke206_get_tlbe(env, tlbn, ea, i);
+ target_phys_addr_t masked_ea = ea & ~(tlb->size - 1);
+ if ((tlb->EPN == (masked_ea >> MAS2_EPN_SHIFT)) &&
+ !(tlb->attr & MAS1_IPROT)) {
+ tlb->prot = 0;
+ }
+ }
+}
+
+void helper_booke206_tlbivax(target_ulong address)
+{
+ if (address & 0x4) {
+ /* flush all entries */
+ if (address & 0x8) {
+ /* flush all of TLB1 */
+ booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
+ } else {
+ /* flush all of TLB0 */
+ booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
+ }
+ return;
+ }
+
+ if (address & 0x8) {
+ /* flush TLB1 entries */
+ booke206_invalidate_ea_tlb(env, 1, address);
+ tlb_flush(env, 1);
+ } else {
+ /* flush TLB0 entries */
+ booke206_invalidate_ea_tlb(env, 0, address);
+ tlb_flush_page(env, address & MAS2_EPN_MASK);
+ }
+}
+
+void helper_booke206_tlbflush(uint32_t type)
+{
+ int flags = 0;
+
+ if (type & 2) {
+ flags |= BOOKE206_FLUSH_TLB1;
+ }
+
+ if (type & 4) {
+ flags |= BOOKE206_FLUSH_TLB0;
+ }
+
+ booke206_flush_tlb(env, flags, 1);
+}
+
#endif /* !CONFIG_USER_ONLY */
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 95813f2..9b3f90c 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -5988,6 +5988,80 @@ static void gen_tlbwe_440(DisasContext *ctx)
#endif
}
+/* TLB management - PowerPC BookE 2.06 implementation */
+
+/* tlbre */
+static void gen_tlbre_booke206(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+#else
+ if (unlikely(!ctx->mem_idx)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+ return;
+ }
+
+ gen_helper_booke206_tlbre();
+#endif
+}
+
+/* tlbsx - tlbsx. */
+static void gen_tlbsx_booke206(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+#else
+ TCGv t0;
+ if (unlikely(!ctx->mem_idx)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+ return;
+ }
+
+ if (rA(ctx->opcode)) {
+ t0 = tcg_temp_new();
+ tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
+ } else {
+ t0 = tcg_const_tl(0);
+ }
+
+ tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
+ gen_helper_booke206_tlbsx(t0);
+#endif
+}
+
+/* tlbwe */
+static void gen_tlbwe_booke206(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+#else
+ if (unlikely(!ctx->mem_idx)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+ return;
+ }
+ gen_helper_booke206_tlbwe();
+#endif
+}
+
+static void gen_tlbivax_booke206(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+#else
+ TCGv t0;
+ if (unlikely(!ctx->mem_idx)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+ return;
+ }
+
+ t0 = tcg_temp_new();
+ gen_addr_reg_index(ctx, t0);
+
+ gen_helper_booke206_tlbivax(t0);
+#endif
+}
+
+
/* wrtee */
static void gen_wrtee(DisasContext *ctx)
{
@@ -8434,7 +8508,7 @@ GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
-GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE),
+GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
@@ -8443,12 +8517,23 @@ GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
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_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
+ PPC_NONE, PPC2_BOOKE206),
+GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
+ PPC_NONE, PPC2_BOOKE206),
+GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
+ PPC_NONE, PPC2_BOOKE206),
+GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
+ PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, 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),
-GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE),
+GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
+ PPC_BOOKE, PPC2_BOOKE206),
+GEN_HANDLER_E(msync, 0x1F, 0x16, 0x12, 0x03FFF801,
+ PPC_BOOKE, PPC2_BOOKE206),
+GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
+ PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
@@ -9197,7 +9282,7 @@ void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
#endif
cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
break;
- case POWERPC_MMU_BOOKE_FSL:
+ case POWERPC_MMU_BOOKE206:
cpu_fprintf(f, " MAS0 " TARGET_FMT_lx " MAS1 " TARGET_FMT_lx
" MAS2 " TARGET_FMT_lx " MAS3 " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index aec0e13..40092b3 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -1355,6 +1355,31 @@ static void gen_74xx_soft_tlb (CPUPPCState *env, int nb_tlbs, int nb_ways)
#endif
}
+#if !defined(CONFIG_USER_ONLY)
+static void spr_write_e500_l1csr0 (void *opaque, int sprn, int gprn)
+{
+ TCGv t0 = tcg_temp_new();
+
+ tcg_gen_andi_tl(t0, cpu_gpr[gprn], ~256);
+ gen_store_spr(sprn, t0);
+ tcg_temp_free(t0);
+}
+
+static void spr_write_booke206_mmucsr0 (void *opaque, int sprn, int gprn)
+{
+ TCGv t0 = tcg_const_i32(sprn);
+ gen_helper_booke206_tlbflush(t0);
+ tcg_temp_free(t0);
+}
+
+static void spr_write_booke_pid (void *opaque, int sprn, int gprn)
+{
+ TCGv t0 = tcg_const_i32(sprn);
+ gen_helper_booke_setpid(t0, cpu_gpr[gprn]);
+ tcg_temp_free(t0);
+}
+#endif
+
static void gen_spr_usprgh (CPUPPCState *env)
{
spr_register(env, SPR_USPRG4, "USPRG4",
@@ -1494,7 +1519,7 @@ static void gen_spr_BookE (CPUPPCState *env, uint64_t ivor_mask)
}
spr_register(env, SPR_BOOKE_PID, "PID",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_booke_pid,
0x00000000);
spr_register(env, SPR_BOOKE_TCR, "TCR",
SPR_NOACCESS, SPR_NOACCESS,
@@ -1536,8 +1561,19 @@ static void gen_spr_BookE (CPUPPCState *env, uint64_t ivor_mask)
0x00000000);
}
-/* FSL storage control registers */
-static void gen_spr_BookE_FSL (CPUPPCState *env, uint32_t mas_mask)
+static inline uint32_t gen_tlbncfg(uint32_t assoc, uint32_t minsize,
+ uint32_t maxsize, uint32_t flags,
+ uint32_t nentries)
+{
+ return (assoc << TLBnCFG_ASSOC_SHIFT) |
+ (minsize << TLBnCFG_MINSIZE_SHIFT) |
+ (maxsize << TLBnCFG_MAXSIZE_SHIFT) |
+ flags | nentries;
+}
+
+/* BookE 2.06 storage control registers */
+static void gen_spr_BookE206(CPUPPCState *env, uint32_t mas_mask,
+ uint32_t *tlbncfg)
{
#if !defined(CONFIG_USER_ONLY)
const char *mas_names[8] = {
@@ -1563,14 +1599,14 @@ static void gen_spr_BookE_FSL (CPUPPCState *env, uint32_t mas_mask)
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_PID1, "PID1",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_booke_pid,
0x00000000);
}
if (env->nb_pids > 2) {
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_PID2, "PID2",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_booke_pid,
0x00000000);
}
/* XXX : not implemented */
@@ -1578,45 +1614,38 @@ static void gen_spr_BookE_FSL (CPUPPCState *env, uint32_t mas_mask)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
0x00000000); /* TOFIX */
- /* XXX : not implemented */
- spr_register(env, SPR_MMUCSR0, "MMUCSR0",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000); /* TOFIX */
switch (env->nb_ways) {
case 4:
- /* XXX : not implemented */
spr_register(env, SPR_BOOKE_TLB3CFG, "TLB3CFG",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
- 0x00000000); /* TOFIX */
+ tlbncfg[3]);
/* Fallthru */
case 3:
- /* XXX : not implemented */
spr_register(env, SPR_BOOKE_TLB2CFG, "TLB2CFG",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
- 0x00000000); /* TOFIX */
+ tlbncfg[2]);
/* Fallthru */
case 2:
- /* XXX : not implemented */
spr_register(env, SPR_BOOKE_TLB1CFG, "TLB1CFG",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
- 0x00000000); /* TOFIX */
+ tlbncfg[1]);
/* Fallthru */
case 1:
- /* XXX : not implemented */
spr_register(env, SPR_BOOKE_TLB0CFG, "TLB0CFG",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
- 0x00000000); /* TOFIX */
+ tlbncfg[0]);
/* Fallthru */
case 0:
default:
break;
}
#endif
+
+ gen_spr_usprgh(env);
}
/* SPR specific to PowerPC 440 implementation */
@@ -4113,7 +4142,7 @@ static void init_proc_G2LE (CPUPPCState *env)
PPC_BOOKE)
#define POWERPC_INSNS2_e200 (PPC_NONE)
#define POWERPC_MSRM_e200 (0x000000000606FF30ULL)
-#define POWERPC_MMU_e200 (POWERPC_MMU_BOOKE_FSL)
+#define POWERPC_MMU_e200 (POWERPC_MMU_BOOKE206)
#define POWERPC_EXCP_e200 (POWERPC_EXCP_BOOKE)
#define POWERPC_INPUT_e200 (PPC_FLAGS_INPUT_BookE)
#define POWERPC_BFDM_e200 (bfd_mach_ppc_860)
@@ -4134,7 +4163,7 @@ static void init_proc_e200 (CPUPPCState *env)
&spr_read_spefscr, &spr_write_spefscr,
0x00000000);
/* Memory management */
- gen_spr_BookE_FSL(env, 0x0000005D);
+ gen_spr_BookE206(env, 0x0000005D, NULL);
/* XXX : not implemented */
spr_register(env, SPR_HID0, "HID0",
SPR_NOACCESS, SPR_NOACCESS,
@@ -4205,6 +4234,11 @@ static void init_proc_e200 (CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+ /* XXX : not implemented */
+ spr_register(env, SPR_MMUCSR0, "MMUCSR0",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000); /* TOFIX */
spr_register(env, SPR_BOOKE_DSRR0, "DSRR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
@@ -4282,11 +4316,10 @@ static void init_proc_e300 (CPUPPCState *env)
PPC_WRTEE | PPC_RFDI | \
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
- PPC_MEM_TLBSYNC | PPC_TLBIVAX | \
- PPC_BOOKE)
-#define POWERPC_INSNS2_e500v1 (PPC_NONE)
+ PPC_MEM_TLBSYNC | PPC_TLBIVAX)
+#define POWERPC_INSNS2_e500v1 (PPC2_BOOKE206)
#define POWERPC_MSRM_e500v1 (0x000000000606FF30ULL)
-#define POWERPC_MMU_e500v1 (POWERPC_MMU_BOOKE_FSL)
+#define POWERPC_MMU_e500v1 (POWERPC_MMU_BOOKE206)
#define POWERPC_EXCP_e500v1 (POWERPC_EXCP_BOOKE)
#define POWERPC_INPUT_e500v1 (PPC_FLAGS_INPUT_BookE)
#define POWERPC_BFDM_e500v1 (bfd_mach_ppc_860)
@@ -4294,7 +4327,7 @@ static void init_proc_e300 (CPUPPCState *env)
POWERPC_FLAG_UBLE | POWERPC_FLAG_DE | \
POWERPC_FLAG_BUS_CLK)
#define check_pow_e500v1 check_pow_hid0
-#define init_proc_e500v1 init_proc_e500
+#define init_proc_e500v1 init_proc_e500v1
/* e500v2 core */
#define POWERPC_INSNS_e500v2 (PPC_INSNS_BASE | PPC_ISEL | \
@@ -4302,11 +4335,10 @@ static void init_proc_e300 (CPUPPCState *env)
PPC_WRTEE | PPC_RFDI | \
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
- PPC_MEM_TLBSYNC | PPC_TLBIVAX | \
- PPC_BOOKE)
-#define POWERPC_INSNS2_e500v2 (PPC_NONE)
+ PPC_MEM_TLBSYNC | PPC_TLBIVAX)
+#define POWERPC_INSNS2_e500v2 (PPC2_BOOKE206)
#define POWERPC_MSRM_e500v2 (0x000000000606FF30ULL)
-#define POWERPC_MMU_e500v2 (POWERPC_MMU_BOOKE_FSL)
+#define POWERPC_MMU_e500v2 (POWERPC_MMU_BOOKE206)
#define POWERPC_EXCP_e500v2 (POWERPC_EXCP_BOOKE)
#define POWERPC_INPUT_e500v2 (PPC_FLAGS_INPUT_BookE)
#define POWERPC_BFDM_e500v2 (bfd_mach_ppc_860)
@@ -4314,13 +4346,23 @@ static void init_proc_e300 (CPUPPCState *env)
POWERPC_FLAG_UBLE | POWERPC_FLAG_DE | \
POWERPC_FLAG_BUS_CLK)
#define check_pow_e500v2 check_pow_hid0
-#define init_proc_e500v2 init_proc_e500
+#define init_proc_e500v2 init_proc_e500v2
-static void init_proc_e500 (CPUPPCState *env)
+static void init_proc_e500 (CPUPPCState *env, int version)
{
+ uint32_t tlbncfg[2];
+#if !defined(CONFIG_USER_ONLY)
+ int i;
+#endif
+
/* Time base */
gen_tbl(env);
- gen_spr_BookE(env, 0x0000000F0000FD7FULL);
+ /*
+ * XXX The e500 doesn't implement IVOR7 and IVOR9, but doesn't
+ * complain when accessing them.
+ * gen_spr_BookE(env, 0x0000000F0000FD7FULL);
+ */
+ gen_spr_BookE(env, 0x0000000F0000FFFFULL);
/* Processor identification */
spr_register(env, SPR_BOOKE_PIR, "PIR",
SPR_NOACCESS, SPR_NOACCESS,
@@ -4334,8 +4376,24 @@ static void init_proc_e500 (CPUPPCState *env)
/* Memory management */
#if !defined(CONFIG_USER_ONLY)
env->nb_pids = 3;
+ env->nb_ways = 2;
+ env->id_tlbs = 0;
+ switch (version) {
+ case 1:
+ /* e500v1 */
+ tlbncfg[0] = gen_tlbncfg(2, 1, 1, 0, 256);
+ tlbncfg[1] = gen_tlbncfg(16, 1, 9, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
+ break;
+ case 2:
+ /* e500v2 */
+ tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512);
+ tlbncfg[1] = gen_tlbncfg(16, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
+ break;
+ default:
+ cpu_abort(env, "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
+ }
#endif
- gen_spr_BookE_FSL(env, 0x0000005F);
+ gen_spr_BookE206(env, 0x000000DF, tlbncfg);
/* XXX : not implemented */
spr_register(env, SPR_HID0, "HID0",
SPR_NOACCESS, SPR_NOACCESS,
@@ -4384,23 +4442,13 @@ static void init_proc_e500 (CPUPPCState *env)
/* XXX : not implemented */
spr_register(env, SPR_Exxx_L1CSR0, "L1CSR0",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_e500_l1csr0,
0x00000000);
/* XXX : not implemented */
spr_register(env, SPR_Exxx_L1CSR1, "L1CSR1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_TLB0CFG, "TLB0CFG",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
- /* XXX : not implemented */
- spr_register(env, SPR_BOOKE_TLB1CFG, "TLB1CFG",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
- 0x00000000);
spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
@@ -4409,11 +4457,18 @@ static void init_proc_e500 (CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+ spr_register(env, SPR_MMUCSR0, "MMUCSR0",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_booke206_mmucsr0,
+ 0x00000000);
+
#if !defined(CONFIG_USER_ONLY)
- env->nb_tlb = 64;
- env->nb_ways = 1;
- env->id_tlbs = 0;
+ env->nb_tlb = 0;
+ for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+ env->nb_tlb += booke206_tlb_size(env, i);
+ }
#endif
+
init_excp_e200(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
@@ -4421,6 +4476,16 @@ static void init_proc_e500 (CPUPPCState *env)
ppce500_irq_init(env);
}
+static void init_proc_e500v1(CPUPPCState *env)
+{
+ init_proc_e500(env, 1);
+}
+
+static void init_proc_e500v2(CPUPPCState *env)
+{
+ init_proc_e500(env, 2);
+}
+
/* Non-embedded PowerPC */
/* POWER : same as 601, without mfmsr, mfsr */
@@ -9756,8 +9821,8 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
case POWERPC_MMU_BOOKE:
mmu_model = "PowerPC BookE";
break;
- case POWERPC_MMU_BOOKE_FSL:
- mmu_model = "PowerPC BookE FSL";
+ case POWERPC_MMU_BOOKE206:
+ mmu_model = "PowerPC BookE 2.06";
break;
case POWERPC_MMU_601:
mmu_model = "PowerPC 601";
commit a5858d7af064c01d9b634399b62f641386eacfcf
Author: Alexander Graf <agraf at suse.de>
Date: Sun May 1 00:00:58 2011 +0200
PPC: Add another 64 bits to instruction feature mask
To enable quick runtime detection of instruction groups to the currently
selected CPU emulation, we have a feature mask of what exactly the respective
instruction supports.
This feature mask is 64 bits long and we just successfully exceeded those 64
bits. To add more features, we need to think of something.
The easiest solution that came to my mind was to simply add another 64 bits
that we can also match on. Since the comparison is only done on start of the
qemu process to generate an internal opcode calling table, we should be fine
on any performance penalties here.
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index c6b2255..2a7431c 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -722,6 +722,7 @@ struct CPUPPCState {
int bfd_mach;
uint32_t flags;
uint64_t insns_flags;
+ uint64_t insns_flags2;
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
target_phys_addr_t vpa;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 99f572a..95813f2 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -201,6 +201,8 @@ struct opc_handler_t {
uint32_t inval;
/* instruction type */
uint64_t type;
+ /* extended instruction type */
+ uint64_t type2;
/* handler */
void (*handler)(DisasContext *ctx);
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
@@ -314,10 +316,16 @@ static inline void gen_sync_exception(DisasContext *ctx)
}
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
-GEN_OPCODE(name, opc1, opc2, opc3, inval, type)
+GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
+
+#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2) \
+GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
-GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type)
+GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)
+
+#define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2) \
+GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
typedef struct opcode_t {
unsigned char opc1, opc2, opc3;
@@ -457,7 +465,7 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
/* PowerPC instructions table */
#if defined(DO_PPC_STATISTICS)
-#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
+#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
{ \
.opc1 = op1, \
.opc2 = op2, \
@@ -466,12 +474,13 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
.handler = { \
.inval = invl, \
.type = _typ, \
+ .type2 = _typ2, \
.handler = &gen_##name, \
.oname = stringify(name), \
}, \
.oname = stringify(name), \
}
-#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
+#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
{ \
.opc1 = op1, \
.opc2 = op2, \
@@ -480,13 +489,14 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
.handler = { \
.inval = invl, \
.type = _typ, \
+ .type2 = _typ2, \
.handler = &gen_##name, \
.oname = onam, \
}, \
.oname = onam, \
}
#else
-#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
+#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
{ \
.opc1 = op1, \
.opc2 = op2, \
@@ -495,11 +505,12 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
.handler = { \
.inval = invl, \
.type = _typ, \
+ .type2 = _typ2, \
.handler = &gen_##name, \
}, \
.oname = stringify(name), \
}
-#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
+#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
{ \
.opc1 = op1, \
.opc2 = op2, \
@@ -508,6 +519,7 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
.handler = { \
.inval = invl, \
.type = _typ, \
+ .type2 = _typ2, \
.handler = &gen_##name, \
}, \
.oname = onam, \
@@ -534,6 +546,7 @@ static void gen_invalid(DisasContext *ctx)
static opc_handler_t invalid_handler = {
.inval = 0xFFFFFFFF,
.type = PPC_NONE,
+ .type2 = PPC_NONE,
.handler = gen_invalid,
};
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index e2a83c5..aec0e13 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -37,6 +37,7 @@ struct ppc_def_t {
uint32_t pvr;
uint32_t svr;
uint64_t insns_flags;
+ uint64_t insns_flags2;
uint64_t msr_mask;
powerpc_mmu_t mmu_model;
powerpc_excp_t excp_model;
@@ -3201,6 +3202,7 @@ static int check_pow_hid0_74xx (CPUPPCState *env)
PPC_CACHE_DCBZ | \
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_4xx_COMMON | PPC_40x_EXCP)
+#define POWERPC_INSNS2_401 (PPC_NONE)
#define POWERPC_MSRM_401 (0x00000000000FD201ULL)
#define POWERPC_MMU_401 (POWERPC_MMU_REAL)
#define POWERPC_EXCP_401 (POWERPC_EXCP_40x)
@@ -3230,6 +3232,7 @@ static void init_proc_401 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
PPC_4xx_COMMON | PPC_40x_EXCP)
+#define POWERPC_INSNS2_401x2 (PPC_NONE)
#define POWERPC_MSRM_401x2 (0x00000000001FD231ULL)
#define POWERPC_MMU_401x2 (POWERPC_MMU_SOFT_4xx_Z)
#define POWERPC_EXCP_401x2 (POWERPC_EXCP_40x)
@@ -3266,6 +3269,7 @@ static void init_proc_401x2 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
PPC_4xx_COMMON | PPC_40x_EXCP)
+#define POWERPC_INSNS2_401x3 (PPC_NONE)
#define POWERPC_MSRM_401x3 (0x00000000001FD631ULL)
#define POWERPC_MMU_401x3 (POWERPC_MMU_SOFT_4xx_Z)
#define POWERPC_EXCP_401x3 (POWERPC_EXCP_40x)
@@ -3298,6 +3302,7 @@ static void init_proc_401x3 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
PPC_4xx_COMMON | PPC_40x_EXCP)
+#define POWERPC_INSNS2_IOP480 (PPC_NONE)
#define POWERPC_MSRM_IOP480 (0x00000000001FD231ULL)
#define POWERPC_MMU_IOP480 (POWERPC_MMU_SOFT_4xx_Z)
#define POWERPC_EXCP_IOP480 (POWERPC_EXCP_40x)
@@ -3333,6 +3338,7 @@ static void init_proc_IOP480 (CPUPPCState *env)
PPC_CACHE_DCBZ | \
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_4xx_COMMON | PPC_40x_EXCP)
+#define POWERPC_INSNS2_403 (PPC_NONE)
#define POWERPC_MSRM_403 (0x000000000007D00DULL)
#define POWERPC_MMU_403 (POWERPC_MMU_REAL)
#define POWERPC_EXCP_403 (POWERPC_EXCP_40x)
@@ -3363,6 +3369,7 @@ static void init_proc_403 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
PPC_4xx_COMMON | PPC_40x_EXCP)
+#define POWERPC_INSNS2_403GCX (PPC_NONE)
#define POWERPC_MSRM_403GCX (0x000000000007D00DULL)
#define POWERPC_MMU_403GCX (POWERPC_MMU_SOFT_4xx_Z)
#define POWERPC_EXCP_403GCX (POWERPC_EXCP_40x)
@@ -3411,6 +3418,7 @@ static void init_proc_403GCX (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
PPC_4xx_COMMON | PPC_405_MAC | PPC_40x_EXCP)
+#define POWERPC_INSNS2_405 (PPC_NONE)
#define POWERPC_MSRM_405 (0x000000000006E630ULL)
#define POWERPC_MMU_405 (POWERPC_MMU_SOFT_4xx)
#define POWERPC_EXCP_405 (POWERPC_EXCP_40x)
@@ -3458,6 +3466,7 @@ static void init_proc_405 (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_MFTB | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
+#define POWERPC_INSNS2_440EP (PPC_NONE)
#define POWERPC_MSRM_440EP (0x000000000006D630ULL)
#define POWERPC_MMU_440EP (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_440EP (POWERPC_EXCP_BOOKE)
@@ -3538,6 +3547,7 @@ static void init_proc_440EP (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_TLBIVA | PPC_MFTB | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
+#define POWERPC_INSNS2_440GP (PPC_NONE)
#define POWERPC_MSRM_440GP (0x000000000006FF30ULL)
#define POWERPC_MMU_440GP (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_440GP (POWERPC_EXCP_BOOKE)
@@ -3600,6 +3610,7 @@ static void init_proc_440GP (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_MFTB | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
+#define POWERPC_INSNS2_440x4 (PPC_NONE)
#define POWERPC_MSRM_440x4 (0x000000000006FF30ULL)
#define POWERPC_MMU_440x4 (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_440x4 (POWERPC_EXCP_BOOKE)
@@ -3662,6 +3673,7 @@ static void init_proc_440x4 (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_MFTB | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
+#define POWERPC_INSNS2_440x5 (PPC_NONE)
#define POWERPC_MSRM_440x5 (0x000000000006FF30ULL)
#define POWERPC_MMU_440x5 (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_440x5 (POWERPC_EXCP_BOOKE)
@@ -3742,6 +3754,7 @@ static void init_proc_440x5 (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_TLBIVA | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
+#define POWERPC_INSNS2_460 (PPC_NONE)
#define POWERPC_MSRM_460 (0x000000000006FF30ULL)
#define POWERPC_MMU_460 (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_460 (POWERPC_EXCP_BOOKE)
@@ -3831,6 +3844,7 @@ static void init_proc_460 (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_TLBIVA | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
+#define POWERPC_INSNS2_460F (PPC_NONE)
#define POWERPC_MSRM_460 (0x000000000006FF30ULL)
#define POWERPC_MMU_460F (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_460F (POWERPC_EXCP_BOOKE)
@@ -3913,6 +3927,7 @@ static void init_proc_460F (CPUPPCState *env)
PPC_MEM_EIEIO | PPC_MEM_SYNC | \
PPC_CACHE_ICBI | PPC_FLOAT | PPC_FLOAT_STFIWX | \
PPC_MFTB)
+#define POWERPC_INSNS2_MPC5xx (PPC_NONE)
#define POWERPC_MSRM_MPC5xx (0x000000000001FF43ULL)
#define POWERPC_MMU_MPC5xx (POWERPC_MMU_REAL)
#define POWERPC_EXCP_MPC5xx (POWERPC_EXCP_603)
@@ -3939,6 +3954,7 @@ static void init_proc_MPC5xx (CPUPPCState *env)
#define POWERPC_INSNS_MPC8xx (PPC_INSNS_BASE | PPC_STRING | \
PPC_MEM_EIEIO | PPC_MEM_SYNC | \
PPC_CACHE_ICBI | PPC_MFTB)
+#define POWERPC_INSNS2_MPC8xx (PPC_NONE)
#define POWERPC_MSRM_MPC8xx (0x000000000001F673ULL)
#define POWERPC_MMU_MPC8xx (POWERPC_MMU_MPC8xx)
#define POWERPC_EXCP_MPC8xx (POWERPC_EXCP_603)
@@ -3970,6 +3986,7 @@ static void init_proc_MPC8xx (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_G2 (PPC_NONE)
#define POWERPC_MSRM_G2 (0x000000000006FFF2ULL)
#define POWERPC_MMU_G2 (POWERPC_MMU_SOFT_6xx)
//#define POWERPC_EXCP_G2 (POWERPC_EXCP_G2)
@@ -4027,6 +4044,7 @@ static void init_proc_G2 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_G2LE (PPC_NONE)
#define POWERPC_MSRM_G2LE (0x000000000007FFF3ULL)
#define POWERPC_MMU_G2LE (POWERPC_MMU_SOFT_6xx)
#define POWERPC_EXCP_G2LE (POWERPC_EXCP_G2)
@@ -4093,6 +4111,7 @@ static void init_proc_G2LE (CPUPPCState *env)
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
PPC_MEM_TLBSYNC | PPC_TLBIVAX | \
PPC_BOOKE)
+#define POWERPC_INSNS2_e200 (PPC_NONE)
#define POWERPC_MSRM_e200 (0x000000000606FF30ULL)
#define POWERPC_MMU_e200 (POWERPC_MMU_BOOKE_FSL)
#define POWERPC_EXCP_e200 (POWERPC_EXCP_BOOKE)
@@ -4213,6 +4232,7 @@ static void init_proc_e200 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_e300 (PPC_NONE)
#define POWERPC_MSRM_e300 (0x000000000007FFF3ULL)
#define POWERPC_MMU_e300 (POWERPC_MMU_SOFT_6xx)
#define POWERPC_EXCP_e300 (POWERPC_EXCP_603)
@@ -4264,6 +4284,7 @@ static void init_proc_e300 (CPUPPCState *env)
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
PPC_MEM_TLBSYNC | PPC_TLBIVAX | \
PPC_BOOKE)
+#define POWERPC_INSNS2_e500v1 (PPC_NONE)
#define POWERPC_MSRM_e500v1 (0x000000000606FF30ULL)
#define POWERPC_MMU_e500v1 (POWERPC_MMU_BOOKE_FSL)
#define POWERPC_EXCP_e500v1 (POWERPC_EXCP_BOOKE)
@@ -4283,6 +4304,7 @@ static void init_proc_e300 (CPUPPCState *env)
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
PPC_MEM_TLBSYNC | PPC_TLBIVAX | \
PPC_BOOKE)
+#define POWERPC_INSNS2_e500v2 (PPC_NONE)
#define POWERPC_MSRM_e500v2 (0x000000000606FF30ULL)
#define POWERPC_MMU_e500v2 (POWERPC_MMU_BOOKE_FSL)
#define POWERPC_EXCP_e500v2 (POWERPC_EXCP_BOOKE)
@@ -4414,6 +4436,7 @@ static void init_proc_e500 (CPUPPCState *env)
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | \
PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_601 (PPC_NONE)
#define POWERPC_MSRM_601 (0x000000000000FD70ULL)
#define POWERPC_MSRR_601 (0x0000000000001040ULL)
//#define POWERPC_MMU_601 (POWERPC_MMU_601)
@@ -4466,6 +4489,7 @@ static void init_proc_601 (CPUPPCState *env)
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | \
PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_601v (PPC_NONE)
#define POWERPC_MSRM_601v (0x000000000000FD70ULL)
#define POWERPC_MSRR_601v (0x0000000000001040ULL)
#define POWERPC_MMU_601v (POWERPC_MMU_601)
@@ -4493,6 +4517,7 @@ static void init_proc_601v (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_6xx_TLB | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_602_SPEC)
+#define POWERPC_INSNS2_602 (PPC_NONE)
#define POWERPC_MSRM_602 (0x0000000000C7FF73ULL)
/* XXX: 602 MMU is quite specific. Should add a special case */
#define POWERPC_MMU_602 (POWERPC_MMU_SOFT_6xx)
@@ -4538,6 +4563,7 @@ static void init_proc_602 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_603 (PPC_NONE)
#define POWERPC_MSRM_603 (0x000000000007FF73ULL)
#define POWERPC_MMU_603 (POWERPC_MMU_SOFT_6xx)
//#define POWERPC_EXCP_603 (POWERPC_EXCP_603)
@@ -4582,6 +4608,7 @@ static void init_proc_603 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_603E (PPC_NONE)
#define POWERPC_MSRM_603E (0x000000000007FF73ULL)
#define POWERPC_MMU_603E (POWERPC_MMU_SOFT_6xx)
//#define POWERPC_EXCP_603E (POWERPC_EXCP_603E)
@@ -4631,6 +4658,7 @@ static void init_proc_603E (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_604 (PPC_NONE)
#define POWERPC_MSRM_604 (0x000000000005FF77ULL)
#define POWERPC_MMU_604 (POWERPC_MMU_32B)
//#define POWERPC_EXCP_604 (POWERPC_EXCP_604)
@@ -4669,6 +4697,7 @@ static void init_proc_604 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_604E (PPC_NONE)
#define POWERPC_MSRM_604E (0x000000000005FF77ULL)
#define POWERPC_MMU_604E (POWERPC_MMU_32B)
#define POWERPC_EXCP_604E (POWERPC_EXCP_604)
@@ -4727,6 +4756,7 @@ static void init_proc_604E (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_740 (PPC_NONE)
#define POWERPC_MSRM_740 (0x000000000005FF77ULL)
#define POWERPC_MMU_740 (POWERPC_MMU_32B)
#define POWERPC_EXCP_740 (POWERPC_EXCP_7x0)
@@ -4772,6 +4802,7 @@ static void init_proc_740 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_750 (PPC_NONE)
#define POWERPC_MSRM_750 (0x000000000005FF77ULL)
#define POWERPC_MMU_750 (POWERPC_MMU_32B)
#define POWERPC_EXCP_750 (POWERPC_EXCP_7x0)
@@ -4863,6 +4894,7 @@ static void init_proc_750 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_750cl (PPC_NONE)
#define POWERPC_MSRM_750cl (0x000000000005FF77ULL)
#define POWERPC_MMU_750cl (POWERPC_MMU_32B)
#define POWERPC_EXCP_750cl (POWERPC_EXCP_7x0)
@@ -5001,6 +5033,7 @@ static void init_proc_750cl (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_750cx (PPC_NONE)
#define POWERPC_MSRM_750cx (0x000000000005FF77ULL)
#define POWERPC_MMU_750cx (POWERPC_MMU_32B)
#define POWERPC_EXCP_750cx (POWERPC_EXCP_7x0)
@@ -5058,6 +5091,7 @@ static void init_proc_750cx (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_750fx (PPC_NONE)
#define POWERPC_MSRM_750fx (0x000000000005FF77ULL)
#define POWERPC_MMU_750fx (POWERPC_MMU_32B)
#define POWERPC_EXCP_750fx (POWERPC_EXCP_7x0)
@@ -5120,6 +5154,7 @@ static void init_proc_750fx (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_750gx (PPC_NONE)
#define POWERPC_MSRM_750gx (0x000000000005FF77ULL)
#define POWERPC_MMU_750gx (POWERPC_MMU_32B)
#define POWERPC_EXCP_750gx (POWERPC_EXCP_7x0)
@@ -5182,6 +5217,7 @@ static void init_proc_750gx (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_745 (PPC_NONE)
#define POWERPC_MSRM_745 (0x000000000005FF77ULL)
#define POWERPC_MMU_745 (POWERPC_MMU_SOFT_6xx)
#define POWERPC_EXCP_745 (POWERPC_EXCP_7x5)
@@ -5235,6 +5271,7 @@ static void init_proc_745 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
+#define POWERPC_INSNS2_755 (PPC_NONE)
#define POWERPC_MSRM_755 (0x000000000005FF77ULL)
#define POWERPC_MMU_755 (POWERPC_MMU_SOFT_6xx)
#define POWERPC_EXCP_755 (POWERPC_EXCP_7x5)
@@ -5303,6 +5340,7 @@ static void init_proc_755 (CPUPPCState *env)
PPC_MEM_TLBIA | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
+#define POWERPC_INSNS2_7400 (PPC_NONE)
#define POWERPC_MSRM_7400 (0x000000000205FF77ULL)
#define POWERPC_MMU_7400 (POWERPC_MMU_32B)
#define POWERPC_EXCP_7400 (POWERPC_EXCP_74xx)
@@ -5355,6 +5393,7 @@ static void init_proc_7400 (CPUPPCState *env)
PPC_MEM_TLBIA | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
+#define POWERPC_INSNS2_7410 (PPC_NONE)
#define POWERPC_MSRM_7410 (0x000000000205FF77ULL)
#define POWERPC_MMU_7410 (POWERPC_MMU_32B)
#define POWERPC_EXCP_7410 (POWERPC_EXCP_74xx)
@@ -5413,6 +5452,7 @@ static void init_proc_7410 (CPUPPCState *env)
PPC_MEM_TLBIA | PPC_74xx_TLB | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
+#define POWERPC_INSNS2_7440 (PPC_NONE)
#define POWERPC_MSRM_7440 (0x000000000205FF77ULL)
#define POWERPC_MMU_7440 (POWERPC_MMU_SOFT_74xx)
#define POWERPC_EXCP_7440 (POWERPC_EXCP_74xx)
@@ -5498,6 +5538,7 @@ static void init_proc_7440 (CPUPPCState *env)
PPC_MEM_TLBIA | PPC_74xx_TLB | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
+#define POWERPC_INSNS2_7450 (PPC_NONE)
#define POWERPC_MSRM_7450 (0x000000000205FF77ULL)
#define POWERPC_MMU_7450 (POWERPC_MMU_SOFT_74xx)
#define POWERPC_EXCP_7450 (POWERPC_EXCP_74xx)
@@ -5609,6 +5650,7 @@ static void init_proc_7450 (CPUPPCState *env)
PPC_MEM_TLBIA | PPC_74xx_TLB | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
+#define POWERPC_INSNS2_7445 (PPC_NONE)
#define POWERPC_MSRM_7445 (0x000000000205FF77ULL)
#define POWERPC_MMU_7445 (POWERPC_MMU_SOFT_74xx)
#define POWERPC_EXCP_7445 (POWERPC_EXCP_74xx)
@@ -5723,6 +5765,7 @@ static void init_proc_7445 (CPUPPCState *env)
PPC_MEM_TLBIA | PPC_74xx_TLB | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
+#define POWERPC_INSNS2_7455 (PPC_NONE)
#define POWERPC_MSRM_7455 (0x000000000205FF77ULL)
#define POWERPC_MMU_7455 (POWERPC_MMU_SOFT_74xx)
#define POWERPC_EXCP_7455 (POWERPC_EXCP_74xx)
@@ -5839,6 +5882,7 @@ static void init_proc_7455 (CPUPPCState *env)
PPC_MEM_TLBIA | PPC_74xx_TLB | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
+#define POWERPC_INSNS2_7457 (PPC_NONE)
#define POWERPC_MSRM_7457 (0x000000000205FF77ULL)
#define POWERPC_MMU_7457 (POWERPC_MMU_SOFT_74xx)
#define POWERPC_EXCP_7457 (POWERPC_EXCP_74xx)
@@ -5978,6 +6022,7 @@ static void init_proc_7457 (CPUPPCState *env)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI)
+#define POWERPC_INSNS2_970 (PPC_NONE)
#define POWERPC_MSRM_970 (0x900000000204FF36ULL)
#define POWERPC_MMU_970 (POWERPC_MMU_64B)
//#define POWERPC_EXCP_970 (POWERPC_EXCP_970)
@@ -6073,6 +6118,7 @@ static void init_proc_970 (CPUPPCState *env)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI)
+#define POWERPC_INSNS2_970FX (PPC_NONE)
#define POWERPC_MSRM_970FX (0x800000000204FF36ULL)
#define POWERPC_MMU_970FX (POWERPC_MMU_64B)
#define POWERPC_EXCP_970FX (POWERPC_EXCP_970)
@@ -6174,6 +6220,7 @@ static void init_proc_970FX (CPUPPCState *env)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI)
+#define POWERPC_INSNS2_970GX (PPC_NONE)
#define POWERPC_MSRM_970GX (0x800000000204FF36ULL)
#define POWERPC_MMU_970GX (POWERPC_MMU_64B)
#define POWERPC_EXCP_970GX (POWERPC_EXCP_970)
@@ -6263,6 +6310,7 @@ static void init_proc_970GX (CPUPPCState *env)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI)
+#define POWERPC_INSNS2_970MP (PPC_NONE)
#define POWERPC_MSRM_970MP (0x900000000204FF36ULL)
#define POWERPC_MMU_970MP (POWERPC_MMU_64B)
#define POWERPC_EXCP_970MP (POWERPC_EXCP_970)
@@ -6354,6 +6402,7 @@ static void init_proc_970MP (CPUPPCState *env)
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI | \
PPC_POPCNTB | PPC_POPCNTWD)
+#define POWERPC_INSNS2_POWER7 (PPC_NONE)
#define POWERPC_MSRM_POWER7 (0x800000000204FF36ULL)
#define POWERPC_MMU_POWER7 (POWERPC_MMU_2_06)
#define POWERPC_EXCP_POWER7 (POWERPC_EXCP_POWER7)
@@ -6424,6 +6473,7 @@ static void init_proc_POWER7 (CPUPPCState *env)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_64B | PPC_SLBI)
+#define POWERPC_INSNS2_620 (PPC_NONE)
#define POWERPC_MSRM_620 (0x800000000005FF77ULL)
//#define POWERPC_MMU_620 (POWERPC_MMU_620)
#define POWERPC_EXCP_620 (POWERPC_EXCP_970)
@@ -6459,6 +6509,7 @@ static void init_proc_620 (CPUPPCState *env)
/* Default 32 bits PowerPC target will be 604 */
#define CPU_POWERPC_PPC32 CPU_POWERPC_604
#define POWERPC_INSNS_PPC32 POWERPC_INSNS_604
+#define POWERPC_INSNS2_PPC32 POWERPC_INSNS2_604
#define POWERPC_MSRM_PPC32 POWERPC_MSRM_604
#define POWERPC_MMU_PPC32 POWERPC_MMU_604
#define POWERPC_EXCP_PPC32 POWERPC_EXCP_604
@@ -6471,6 +6522,7 @@ static void init_proc_620 (CPUPPCState *env)
/* Default 64 bits PowerPC target will be 970 FX */
#define CPU_POWERPC_PPC64 CPU_POWERPC_970FX
#define POWERPC_INSNS_PPC64 POWERPC_INSNS_970FX
+#define POWERPC_INSNS2_PPC64 POWERPC_INSNS2_970FX
#define POWERPC_MSRM_PPC64 POWERPC_MSRM_970FX
#define POWERPC_MMU_PPC64 POWERPC_MMU_970FX
#define POWERPC_EXCP_PPC64 POWERPC_EXCP_970FX
@@ -6482,27 +6534,29 @@ static void init_proc_620 (CPUPPCState *env)
/* Default PowerPC target will be PowerPC 32 */
#if defined (TARGET_PPC64) && 0 // XXX: TODO
-#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC64
-#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC64
-#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC64
-#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC64
-#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC64
-#define POWERPC_INPUT_DEFAULT POWERPC_INPUT_PPC64
-#define POWERPC_BFDM_DEFAULT POWERPC_BFDM_PPC64
-#define POWERPC_FLAG_DEFAULT POWERPC_FLAG_PPC64
-#define check_pow_DEFAULT check_pow_PPC64
-#define init_proc_DEFAULT init_proc_PPC64
+#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC64
+#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC64
+#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC64
+#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC64
+#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC64
+#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC64
+#define POWERPC_INPUT_DEFAULT POWERPC_INPUT_PPC64
+#define POWERPC_BFDM_DEFAULT POWERPC_BFDM_PPC64
+#define POWERPC_FLAG_DEFAULT POWERPC_FLAG_PPC64
+#define check_pow_DEFAULT check_pow_PPC64
+#define init_proc_DEFAULT init_proc_PPC64
#else
-#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC32
-#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC32
-#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC32
-#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC32
-#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC32
-#define POWERPC_INPUT_DEFAULT POWERPC_INPUT_PPC32
-#define POWERPC_BFDM_DEFAULT POWERPC_BFDM_PPC32
-#define POWERPC_FLAG_DEFAULT POWERPC_FLAG_PPC32
-#define check_pow_DEFAULT check_pow_PPC32
-#define init_proc_DEFAULT init_proc_PPC32
+#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC32
+#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC32
+#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC32
+#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC32
+#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC32
+#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC32
+#define POWERPC_INPUT_DEFAULT POWERPC_INPUT_PPC32
+#define POWERPC_BFDM_DEFAULT POWERPC_BFDM_PPC32
+#define POWERPC_FLAG_DEFAULT POWERPC_FLAG_PPC32
+#define check_pow_DEFAULT check_pow_PPC32
+#define init_proc_DEFAULT init_proc_PPC32
#endif
/*****************************************************************************/
@@ -7351,18 +7405,19 @@ enum {
/* PowerPC CPU definitions */
#define POWERPC_DEF_SVR(_name, _pvr, _svr, _type) \
{ \
- .name = _name, \
- .pvr = _pvr, \
- .svr = _svr, \
- .insns_flags = glue(POWERPC_INSNS_,_type), \
- .msr_mask = glue(POWERPC_MSRM_,_type), \
- .mmu_model = glue(POWERPC_MMU_,_type), \
- .excp_model = glue(POWERPC_EXCP_,_type), \
- .bus_model = glue(POWERPC_INPUT_,_type), \
- .bfd_mach = glue(POWERPC_BFDM_,_type), \
- .flags = glue(POWERPC_FLAG_,_type), \
- .init_proc = &glue(init_proc_,_type), \
- .check_pow = &glue(check_pow_,_type), \
+ .name = _name, \
+ .pvr = _pvr, \
+ .svr = _svr, \
+ .insns_flags = glue(POWERPC_INSNS_,_type), \
+ .insns_flags2 = glue(POWERPC_INSNS2_,_type), \
+ .msr_mask = glue(POWERPC_MSRM_,_type), \
+ .mmu_model = glue(POWERPC_MMU_,_type), \
+ .excp_model = glue(POWERPC_EXCP_,_type), \
+ .bus_model = glue(POWERPC_INPUT_,_type), \
+ .bfd_mach = glue(POWERPC_BFDM_,_type), \
+ .flags = glue(POWERPC_FLAG_,_type), \
+ .init_proc = &glue(init_proc_,_type), \
+ .check_pow = &glue(check_pow_,_type), \
}
#define POWERPC_DEF(_name, _pvr, _type) \
POWERPC_DEF_SVR(_name, _pvr, POWERPC_SVR_NONE, _type)
@@ -9437,7 +9492,8 @@ static int create_ppc_opcodes (CPUPPCState *env, const ppc_def_t *def)
fill_new_table(env->opcodes, 0x40);
for (opc = opcodes; opc < &opcodes[ARRAY_SIZE(opcodes)]; opc++) {
- if ((opc->handler.type & def->insns_flags) != 0) {
+ if (((opc->handler.type & def->insns_flags) != 0) ||
+ ((opc->handler.type2 & def->insns_flags2) != 0)) {
if (register_insn(env->opcodes, opc) < 0) {
printf("*** ERROR initializing PowerPC instruction "
"0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
@@ -9650,6 +9706,7 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
env->excp_model = def->excp_model;
env->bus_model = def->bus_model;
env->insns_flags = def->insns_flags;
+ env->insns_flags2 = def->insns_flags2;
env->flags = def->flags;
env->bfd_mach = def->bfd_mach;
env->check_pow = def->check_pow;
commit 71afeb616534cb93d38ece73f2c4151e3ca4bc83
Author: Alexander Graf <agraf at suse.de>
Date: Sat Apr 30 23:34:56 2011 +0200
PPC: Add GS MSR definition
The BookE specification defines MSR bit 28 as Guest State. Add it
to the list of MSR macros.
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 303f8ce..c6b2255 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -420,6 +420,7 @@ struct ppc_slb_t {
#define MSR_CM 31 /* Computation mode for BookE hflags */
#define MSR_ICM 30 /* Interrupt computation mode for BookE */
#define MSR_THV 29 /* hypervisor state for 32 bits PowerPC hflags */
+#define MSR_GS 28 /* guest state for BookE */
#define MSR_UCLE 26 /* User-mode cache lock enable for BookE */
#define MSR_VR 25 /* altivec available x hflags */
#define MSR_SPE 25 /* SPE enable for BookE x hflags */
@@ -457,6 +458,7 @@ struct ppc_slb_t {
#define msr_cm ((env->msr >> MSR_CM) & 1)
#define msr_icm ((env->msr >> MSR_ICM) & 1)
#define msr_thv ((env->msr >> MSR_THV) & 1)
+#define msr_gs ((env->msr >> MSR_GS) & 1)
#define msr_ucle ((env->msr >> MSR_UCLE) & 1)
#define msr_vr ((env->msr >> MSR_VR) & 1)
#define msr_spe ((env->msr >> MSR_SPE) & 1)
commit 3b989d499e933626d09e0166b1fd7c8b8e1e65f2
Author: Alexander Graf <agraf at suse.de>
Date: Sat Apr 30 23:34:53 2011 +0200
PPC: Make MPC8544DS emulation work w/o KVM
The MPC8544DS board emulation was only used with KVM so far, so some
parts of the code didn't provide proper values for non-KVM execution.
This patch makes the machine work without KVM enabled. To actually use
this, you also need proper e500v2 MMU emulation.
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 1b8a1c4..25c14c1 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -28,6 +28,7 @@
#include "kvm_ppc.h"
#include "device_tree.h"
#include "openpic.h"
+#include "ppc.h"
#include "ppce500.h"
#include "loader.h"
#include "elf.h"
@@ -50,6 +51,12 @@
#define MPC8544_PCI_IO 0xE1000000
#define MPC8544_PCI_IOLEN 0x10000
+struct boot_info
+{
+ uint32_t dt_base;
+ uint32_t entry;
+};
+
#ifdef CONFIG_FDT
static int mpc8544_copy_soc_cell(void *fdt, const char *node, const char *prop)
{
@@ -82,7 +89,7 @@ static int mpc8544_load_device_tree(target_phys_addr_t addr,
{
int ret = -1;
#ifdef CONFIG_FDT
- uint32_t mem_reg_property[] = {0, ramsize};
+ uint32_t mem_reg_property[] = {0, cpu_to_be32(ramsize)};
char *filename;
int fdt_size;
void *fdt;
@@ -103,15 +110,19 @@ static int mpc8544_load_device_tree(target_phys_addr_t addr,
if (ret < 0)
fprintf(stderr, "couldn't set /memory/reg\n");
- ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
- initrd_base);
- if (ret < 0)
- fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+ if (initrd_size) {
+ ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+ initrd_base);
+ if (ret < 0) {
+ fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+ }
- ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
- (initrd_base + initrd_size));
- if (ret < 0)
- fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
+ ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+ (initrd_base + initrd_size));
+ if (ret < 0) {
+ fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
+ }
+ }
ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
kernel_cmdline);
@@ -145,6 +156,13 @@ static int mpc8544_load_device_tree(target_phys_addr_t addr,
mpc8544_copy_soc_cell(fdt, buf, "clock-frequency");
mpc8544_copy_soc_cell(fdt, buf, "timebase-frequency");
+ } else {
+ const uint32_t freq = 400000000;
+
+ qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,8544 at 0",
+ "clock-frequency", freq);
+ qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,8544 at 0",
+ "timebase-frequency", freq);
}
ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
@@ -156,6 +174,35 @@ out:
return ret;
}
+/* Create -kernel TLB entries for BookE, linearly spanning 256MB. */
+static void mmubooke_create_initial_mapping(CPUState *env,
+ target_ulong va,
+ target_phys_addr_t pa)
+{
+ ppcemb_tlb_t *tlb = &env->tlb[512].tlbe;
+
+ tlb->attr = 0;
+ tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+ tlb->size = 256 * 1024 * 1024;
+ tlb->EPN = va & TARGET_PAGE_MASK;
+ tlb->RPN = pa & TARGET_PAGE_MASK;
+ tlb->PID = 0;
+}
+
+static void mpc8544ds_cpu_reset(void *opaque)
+{
+ CPUState *env = opaque;
+ struct boot_info *bi = env->load_info;
+
+ cpu_reset(env);
+
+ /* Set initial guest state. */
+ env->gpr[1] = (16<<20) - 8;
+ env->gpr[3] = bi->dt_base;
+ env->nip = bi->entry;
+ mmubooke_create_initial_mapping(env, 0, 0);
+}
+
static void mpc8544ds_init(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename,
@@ -176,6 +223,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
int i=0;
unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
qemu_irq *irqs, *mpic, *pci_irqs;
+ struct boot_info *boot_info;
/* Setup CPU */
if (cpu_model == NULL) {
@@ -188,6 +236,13 @@ static void mpc8544ds_init(ram_addr_t ram_size,
exit(1);
}
+ /* XXX register timer? */
+ ppc_emb_timers_init(env, 400000000, PPC_INTERRUPT_DECR);
+ ppc_dcr_init(env, NULL, NULL);
+
+ /* Register reset handler */
+ qemu_register_reset(mpc8544ds_cpu_reset, env);
+
/* Fixup Memory size on a alignment boundary */
ram_size &= ~(RAM_SIZES_ALIGN - 1);
@@ -263,8 +318,13 @@ static void mpc8544ds_init(ram_addr_t ram_size,
}
}
+ boot_info = qemu_mallocz(sizeof(struct boot_info));
+
/* If we're loading a kernel directly, we must load the device tree too. */
if (kernel_filename) {
+#ifndef CONFIG_FDT
+ cpu_abort(env, "Compiled without FDT support - can't load kernel\n");
+#endif
dt_base = (kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
if (mpc8544_load_device_tree(dt_base, ram_size,
initrd_base, initrd_size, kernel_cmdline) < 0) {
@@ -272,17 +332,14 @@ static void mpc8544ds_init(ram_addr_t ram_size,
exit(1);
}
- /* Set initial guest state. */
- env->gpr[1] = (16<<20) - 8;
- env->gpr[3] = dt_base;
- env->nip = entry;
- /* XXX we currently depend on KVM to create some initial TLB entries. */
+ boot_info->entry = entry;
+ boot_info->dt_base = dt_base;
}
+ env->load_info = boot_info;
- if (kvm_enabled())
+ if (kvm_enabled()) {
kvmppc_init();
-
- return;
+ }
}
static QEMUMachine mpc8544ds_machine = {
commit ef250db6f152e53c7a96770c77167c366497c192
Author: Alexander Graf <agraf at suse.de>
Date: Sat Apr 30 23:05:03 2011 +0200
PPC: Make MPC8544DS obey -cpu switch
The MPC8544DS board emulation code ignored the user defined -cpu switch.
This patch enables it to only provide a sane default, not force an e500v2
CPU inside.
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index e111dda..1b8a1c4 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -178,7 +178,11 @@ static void mpc8544ds_init(ram_addr_t ram_size,
qemu_irq *irqs, *mpic, *pci_irqs;
/* Setup CPU */
- env = cpu_ppc_init("e500v2_v30");
+ if (cpu_model == NULL) {
+ cpu_model = "e500v2_v30";
+ }
+
+ env = cpu_ppc_init(cpu_model);
if (!env) {
fprintf(stderr, "Unable to initialize CPU!\n");
exit(1);
commit 7d7ba3feced4a28350fac84123be23a2fea1e28f
Author: David Gibson <david at gibson.dropbear.id.au>
Date: Tue May 10 16:06:21 2011 +1000
Fix off-by-one error in sizing pSeries hcall table
The pSeries machine uses two tables to look up guest hcalls for emulation.
One of these is exactly one entry too small to hold all the hcalls it needs
to, leading to memory corruption.
This patch fixes the bug, and while we're at it, make both tables 'static'
since they're never used from other modules.
Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index f88e1d2..5281ba2 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -455,8 +455,8 @@ static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr,
nret, rtas_r3 + 12 + 4*nargs);
}
-spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
-spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE];
+static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
+static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
{
commit 446b91652ce4eb19401d102e390899cfb1fb1c62
Author: Andreas Färber <andreas.faerber at web.de>
Date: Sun May 8 13:25:56 2011 +0200
ppc64: Fix out-of-tree builds
On ppc64 host, recursion into pc-bios/spapr-rtas/ fails for
out-of-tree builds. Add missing dir and symlink.
Cc: David Gibson <david at gibson.dropbear.id.au>
Cc: Alexander Graf <agraf at suse.de>
Signed-off-by: Andreas Färber <andreas.faerber at web.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/configure b/configure
index adfbb40..3b764f4 100755
--- a/configure
+++ b/configure
@@ -3475,11 +3475,13 @@ done # for target in $targets
# build tree in object directory in case the source is not in the current directory
DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
+DIRS="$DIRS pc-bios/spapr-rtas"
DIRS="$DIRS roms/seabios roms/vgabios"
DIRS="$DIRS fsdev ui"
FILES="Makefile tests/Makefile"
FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
+FILES="$FILES pc-bios/spapr-rtas/Makefile"
FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.rom $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
FILES="$FILES pc-bios/`basename $bios_file`"
commit d4d6868f7b18874d6371388e3c226ea235802215
Author: Alexander Graf <agraf at suse.de>
Date: Sat Apr 16 10:15:11 2011 +0200
kvm: ppc: warn user on PAGE_SIZE mismatch
On PPC, the default PAGE_SIZE is 64kb. Unfortunately, the hardware
alignments don't match here: There are RAM and MMIO regions within
a single page when it's 64kb in size.
So the only way out for now is to tell the user that he should use 4k
PAGE_SIZE.
This patch gives the user a hint on that, telling him that failing to
register a prefix slot is most likely to be caused by mismatching PAGE_SIZE.
This way it's also more future-proof, as bigger PAGE_SIZE can easily be
supported by other machines then, as long as they stick to 64kb granularities.
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/kvm-all.c b/kvm-all.c
index 3b81b68..106eb3a 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -603,6 +603,11 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
if (err) {
fprintf(stderr, "%s: error registering prefix slot: %s\n",
__func__, strerror(-err));
+#ifdef TARGET_PPC
+ fprintf(stderr, "%s: This is probably because your kernel's " \
+ "PAGE_SIZE is too big. Please try to use 4k " \
+ "PAGE_SIZE!\n", __func__);
+#endif
abort();
}
}
commit 64e07be544ee9c5fb5b741175262fd34726ec431
Author: Alexander Graf <agraf at suse.de>
Date: Sat Apr 16 02:00:36 2011 +0200
kvm: ppc: detect old headers
When compiling Qemu with older kernel headers, the PVR setting
mechanism isn't available yet. Unfortunately, back then I didn't add
a capability we could check against, so all we can do is add a configure
test to see if we support PVR setting. For BookE, we don't care yet.
This fixes compilation errors with KVM enabled on older kernel headers
(like 2.6.32).
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/configure b/configure
index fbf5d5f..adfbb40 100755
--- a/configure
+++ b/configure
@@ -1772,6 +1772,21 @@ recent kvm-kmod from http://sourceforge.net/projects/kvm."
fi
##########################################
+# test for ppc kvm pvr setting
+
+if test "$kvm" = "yes" && test "$cpu" = "ppc" -o "$cpu" = "ppc64"; then
+ cat > $TMPC <<EOF
+ #include <asm/kvm.h>
+ int main(void) { struct kvm_sregs s; s.pvr = 0; return 0; }
+EOF
+ if compile_prog "$kvm_cflags" "" ; then
+ kvm_ppc_pvr=yes
+ else
+ kvm_ppc_pvr=no
+ fi
+fi
+
+##########################################
# test for vhost net
if test "$vhost_net" != "no"; then
@@ -3257,6 +3272,9 @@ case "$target_arch2" in
if test $vhost_net = "yes" ; then
echo "CONFIG_VHOST_NET=y" >> $config_target_mak
fi
+ if test $kvm_ppc_pvr = "yes" ; then
+ echo "CONFIG_KVM_PPC_PVR=y" >> $config_target_mak
+ fi
fi
esac
if test "$target_bigendian" = "yes" ; then
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 5a1b6cb..ccf4668 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -94,19 +94,33 @@ static int kvm_arch_sync_sregs(CPUState *cenv)
int ret;
if (cenv->excp_model == POWERPC_EXCP_BOOKE) {
+ /* What we're really trying to say is "if we're on BookE, we use
+ the native PVR for now". This is the only sane way to check
+ it though, so we potentially confuse users that they can run
+ BookE guests on BookS. Let's hope nobody dares enough :) */
return 0;
} else {
if (!cap_segstate) {
- return 0;
+ fprintf(stderr, "kvm error: missing PVR setting capability\n");
+ return -ENOSYS;
}
}
+#if !defined(CONFIG_KVM_PPC_PVR)
+ if (1) {
+ fprintf(stderr, "kvm error: missing PVR setting capability\n");
+ return -ENOSYS;
+ }
+#endif
+
ret = kvm_vcpu_ioctl(cenv, KVM_GET_SREGS, &sregs);
if (ret) {
return ret;
}
+#ifdef CONFIG_KVM_PPC_PVR
sregs.pvr = cenv->spr[SPR_PVR];
+#endif
return kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
}
commit 90dc8812229a1d3f31bc08ccf0aa50e10282faef
Author: Scott Wood <scottwood at freescale.com>
Date: Fri Apr 29 17:10:23 2011 -0500
monitor: add PPC BookE SPRs
Read them via KVM_GET_SREGS in kvm_arch_get_registers(),
and display them in "info registers".
Also get CR and PID from the existing KVM_GET_REGS.
Signed-off-by: Scott Wood <scottwood at freescale.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/ppc.c b/hw/ppc.c
index 1873328..9157719 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -452,6 +452,10 @@ uint64_t cpu_ppc_load_tbl (CPUState *env)
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
+ if (kvm_enabled()) {
+ return env->spr[SPR_TBL];
+ }
+
tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
@@ -471,6 +475,10 @@ static inline uint32_t _cpu_ppc_load_tbu(CPUState *env)
uint32_t cpu_ppc_load_tbu (CPUState *env)
{
+ if (kvm_enabled()) {
+ return env->spr[SPR_TBU];
+ }
+
return _cpu_ppc_load_tbu(env);
}
@@ -616,6 +624,10 @@ uint32_t cpu_ppc_load_decr (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
+ if (kvm_enabled()) {
+ return env->spr[SPR_DECR];
+ }
+
return _cpu_ppc_load_decr(env, tb_env->decr_next);
}
diff --git a/monitor.c b/monitor.c
index 5f3bc72..f63cce0 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3466,7 +3466,76 @@ static const MonitorDef monitor_defs[] = {
{ "sr13", offsetof(CPUState, sr[13]) },
{ "sr14", offsetof(CPUState, sr[14]) },
{ "sr15", offsetof(CPUState, sr[15]) },
- /* Too lazy to put BATs and SPRs ... */
+ /* Too lazy to put BATs... */
+ { "pvr", offsetof(CPUState, spr[SPR_PVR]) },
+
+ { "srr0", offsetof(CPUState, spr[SPR_SRR0]) },
+ { "srr1", offsetof(CPUState, spr[SPR_SRR1]) },
+ { "sprg0", offsetof(CPUState, spr[SPR_SPRG0]) },
+ { "sprg1", offsetof(CPUState, spr[SPR_SPRG1]) },
+ { "sprg2", offsetof(CPUState, spr[SPR_SPRG2]) },
+ { "sprg3", offsetof(CPUState, spr[SPR_SPRG3]) },
+ { "sprg4", offsetof(CPUState, spr[SPR_SPRG4]) },
+ { "sprg5", offsetof(CPUState, spr[SPR_SPRG5]) },
+ { "sprg6", offsetof(CPUState, spr[SPR_SPRG6]) },
+ { "sprg7", offsetof(CPUState, spr[SPR_SPRG7]) },
+ { "pid", offsetof(CPUState, spr[SPR_BOOKE_PID]) },
+ { "csrr0", offsetof(CPUState, spr[SPR_BOOKE_CSRR0]) },
+ { "csrr1", offsetof(CPUState, spr[SPR_BOOKE_CSRR1]) },
+ { "esr", offsetof(CPUState, spr[SPR_BOOKE_ESR]) },
+ { "dear", offsetof(CPUState, spr[SPR_BOOKE_DEAR]) },
+ { "mcsr", offsetof(CPUState, spr[SPR_BOOKE_MCSR]) },
+ { "tsr", offsetof(CPUState, spr[SPR_BOOKE_TSR]) },
+ { "tcr", offsetof(CPUState, spr[SPR_BOOKE_TCR]) },
+ { "vrsave", offsetof(CPUState, spr[SPR_VRSAVE]) },
+ { "pir", offsetof(CPUState, spr[SPR_BOOKE_PIR]) },
+ { "mcsrr0", offsetof(CPUState, spr[SPR_BOOKE_MCSRR0]) },
+ { "mcsrr1", offsetof(CPUState, spr[SPR_BOOKE_MCSRR1]) },
+ { "decar", offsetof(CPUState, spr[SPR_BOOKE_DECAR]) },
+ { "ivpr", offsetof(CPUState, spr[SPR_BOOKE_IVPR]) },
+ { "epcr", offsetof(CPUState, spr[SPR_BOOKE_EPCR]) },
+ { "sprg8", offsetof(CPUState, spr[SPR_BOOKE_SPRG8]) },
+ { "ivor0", offsetof(CPUState, spr[SPR_BOOKE_IVOR0]) },
+ { "ivor1", offsetof(CPUState, spr[SPR_BOOKE_IVOR1]) },
+ { "ivor2", offsetof(CPUState, spr[SPR_BOOKE_IVOR2]) },
+ { "ivor3", offsetof(CPUState, spr[SPR_BOOKE_IVOR3]) },
+ { "ivor4", offsetof(CPUState, spr[SPR_BOOKE_IVOR4]) },
+ { "ivor5", offsetof(CPUState, spr[SPR_BOOKE_IVOR5]) },
+ { "ivor6", offsetof(CPUState, spr[SPR_BOOKE_IVOR6]) },
+ { "ivor7", offsetof(CPUState, spr[SPR_BOOKE_IVOR7]) },
+ { "ivor8", offsetof(CPUState, spr[SPR_BOOKE_IVOR8]) },
+ { "ivor9", offsetof(CPUState, spr[SPR_BOOKE_IVOR9]) },
+ { "ivor10", offsetof(CPUState, spr[SPR_BOOKE_IVOR10]) },
+ { "ivor11", offsetof(CPUState, spr[SPR_BOOKE_IVOR11]) },
+ { "ivor12", offsetof(CPUState, spr[SPR_BOOKE_IVOR12]) },
+ { "ivor13", offsetof(CPUState, spr[SPR_BOOKE_IVOR13]) },
+ { "ivor14", offsetof(CPUState, spr[SPR_BOOKE_IVOR14]) },
+ { "ivor15", offsetof(CPUState, spr[SPR_BOOKE_IVOR15]) },
+ { "ivor32", offsetof(CPUState, spr[SPR_BOOKE_IVOR32]) },
+ { "ivor33", offsetof(CPUState, spr[SPR_BOOKE_IVOR33]) },
+ { "ivor34", offsetof(CPUState, spr[SPR_BOOKE_IVOR34]) },
+ { "ivor35", offsetof(CPUState, spr[SPR_BOOKE_IVOR35]) },
+ { "ivor36", offsetof(CPUState, spr[SPR_BOOKE_IVOR36]) },
+ { "ivor37", offsetof(CPUState, spr[SPR_BOOKE_IVOR37]) },
+ { "mas0", offsetof(CPUState, spr[SPR_BOOKE_MAS0]) },
+ { "mas1", offsetof(CPUState, spr[SPR_BOOKE_MAS1]) },
+ { "mas2", offsetof(CPUState, spr[SPR_BOOKE_MAS2]) },
+ { "mas3", offsetof(CPUState, spr[SPR_BOOKE_MAS3]) },
+ { "mas4", offsetof(CPUState, spr[SPR_BOOKE_MAS4]) },
+ { "mas6", offsetof(CPUState, spr[SPR_BOOKE_MAS6]) },
+ { "mas7", offsetof(CPUState, spr[SPR_BOOKE_MAS7]) },
+ { "mmucfg", offsetof(CPUState, spr[SPR_MMUCFG]) },
+ { "tlb0cfg", offsetof(CPUState, spr[SPR_BOOKE_TLB0CFG]) },
+ { "tlb1cfg", offsetof(CPUState, spr[SPR_BOOKE_TLB1CFG]) },
+ { "epr", offsetof(CPUState, spr[SPR_BOOKE_EPR]) },
+ { "eplc", offsetof(CPUState, spr[SPR_BOOKE_EPLC]) },
+ { "epsc", offsetof(CPUState, spr[SPR_BOOKE_EPSC]) },
+ { "svr", offsetof(CPUState, spr[SPR_E500_SVR]) },
+ { "mcar", offsetof(CPUState, spr[SPR_Exxx_MCAR]) },
+ { "pid1", offsetof(CPUState, spr[SPR_BOOKE_PID1]) },
+ { "pid2", offsetof(CPUState, spr[SPR_BOOKE_PID2]) },
+ { "hid0", offsetof(CPUState, spr[SPR_HID0]) },
+
#elif defined(TARGET_SPARC)
{ "g0", offsetof(CPUState, gregs[0]) },
{ "g1", offsetof(CPUState, gregs[1]) },
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 04b1259..303f8ce 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1016,6 +1016,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
#define SPR_HSPRG1 (0x131)
#define SPR_HDSISR (0x132)
#define SPR_HDAR (0x133)
+#define SPR_BOOKE_EPCR (0x133)
#define SPR_SPURR (0x134)
#define SPR_BOOKE_DBCR0 (0x134)
#define SPR_IBCR (0x135)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 3ca39b7..5a1b6cb 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -2,6 +2,7 @@
* PowerPC implementation of KVM hooks
*
* Copyright IBM Corp. 2007
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
*
* Authors:
* Jerone Young <jyoung5 at us.ibm.com>
@@ -43,6 +44,10 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
static int cap_interrupt_unset = false;
static int cap_interrupt_level = false;
+static int cap_segstate;
+#ifdef KVM_CAP_PPC_BOOKE_SREGS
+static int cap_booke_sregs;
+#endif
/* XXX We have a race condition where we actually have a level triggered
* interrupt, but the infrastructure can't expose that yet, so the guest
@@ -68,6 +73,12 @@ int kvm_arch_init(KVMState *s)
#ifdef KVM_CAP_PPC_IRQ_LEVEL
cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL);
#endif
+#ifdef KVM_CAP_PPC_SEGSTATE
+ cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE);
+#endif
+#ifdef KVM_CAP_PPC_BOOKE_SREGS
+ cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS);
+#endif
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -85,13 +96,9 @@ static int kvm_arch_sync_sregs(CPUState *cenv)
if (cenv->excp_model == POWERPC_EXCP_BOOKE) {
return 0;
} else {
-#ifdef KVM_CAP_PPC_SEGSTATE
- if (!kvm_check_extension(cenv->kvm_state, KVM_CAP_PPC_SEGSTATE)) {
+ if (!cap_segstate) {
return 0;
}
-#else
- return 0;
-#endif
}
ret = kvm_vcpu_ioctl(cenv, KVM_GET_SREGS, &sregs);
@@ -149,6 +156,8 @@ int kvm_arch_put_registers(CPUState *env, int level)
regs.sprg6 = env->spr[SPR_SPRG6];
regs.sprg7 = env->spr[SPR_SPRG7];
+ regs.pid = env->spr[SPR_BOOKE_PID];
+
for (i = 0;i < 32; i++)
regs.gpr[i] = env->gpr[i];
@@ -163,15 +172,18 @@ int kvm_arch_get_registers(CPUState *env)
{
struct kvm_regs regs;
struct kvm_sregs sregs;
+ uint32_t cr;
int i, ret;
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s);
if (ret < 0)
return ret;
- ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
- if (ret < 0)
- return ret;
+ cr = regs.cr;
+ for (i = 7; i >= 0; i--) {
+ env->crf[i] = cr & 15;
+ cr >>= 4;
+ }
env->ctr = regs.ctr;
env->lr = regs.lr;
@@ -191,11 +203,124 @@ int kvm_arch_get_registers(CPUState *env)
env->spr[SPR_SPRG6] = regs.sprg6;
env->spr[SPR_SPRG7] = regs.sprg7;
+ env->spr[SPR_BOOKE_PID] = regs.pid;
+
for (i = 0;i < 32; i++)
env->gpr[i] = regs.gpr[i];
+#ifdef KVM_CAP_PPC_BOOKE_SREGS
+ if (cap_booke_sregs) {
+ ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (sregs.u.e.features & KVM_SREGS_E_BASE) {
+ env->spr[SPR_BOOKE_CSRR0] = sregs.u.e.csrr0;
+ env->spr[SPR_BOOKE_CSRR1] = sregs.u.e.csrr1;
+ env->spr[SPR_BOOKE_ESR] = sregs.u.e.esr;
+ env->spr[SPR_BOOKE_DEAR] = sregs.u.e.dear;
+ env->spr[SPR_BOOKE_MCSR] = sregs.u.e.mcsr;
+ env->spr[SPR_BOOKE_TSR] = sregs.u.e.tsr;
+ env->spr[SPR_BOOKE_TCR] = sregs.u.e.tcr;
+ env->spr[SPR_DECR] = sregs.u.e.dec;
+ env->spr[SPR_TBL] = sregs.u.e.tb & 0xffffffff;
+ env->spr[SPR_TBU] = sregs.u.e.tb >> 32;
+ env->spr[SPR_VRSAVE] = sregs.u.e.vrsave;
+ }
+
+ if (sregs.u.e.features & KVM_SREGS_E_ARCH206) {
+ env->spr[SPR_BOOKE_PIR] = sregs.u.e.pir;
+ env->spr[SPR_BOOKE_MCSRR0] = sregs.u.e.mcsrr0;
+ env->spr[SPR_BOOKE_MCSRR1] = sregs.u.e.mcsrr1;
+ env->spr[SPR_BOOKE_DECAR] = sregs.u.e.decar;
+ env->spr[SPR_BOOKE_IVPR] = sregs.u.e.ivpr;
+ }
+
+ if (sregs.u.e.features & KVM_SREGS_E_64) {
+ env->spr[SPR_BOOKE_EPCR] = sregs.u.e.epcr;
+ }
+
+ if (sregs.u.e.features & KVM_SREGS_E_SPRG8) {
+ env->spr[SPR_BOOKE_SPRG8] = sregs.u.e.sprg8;
+ }
+
+ if (sregs.u.e.features & KVM_SREGS_E_IVOR) {
+ env->spr[SPR_BOOKE_IVOR0] = sregs.u.e.ivor_low[0];
+ env->spr[SPR_BOOKE_IVOR1] = sregs.u.e.ivor_low[1];
+ env->spr[SPR_BOOKE_IVOR2] = sregs.u.e.ivor_low[2];
+ env->spr[SPR_BOOKE_IVOR3] = sregs.u.e.ivor_low[3];
+ env->spr[SPR_BOOKE_IVOR4] = sregs.u.e.ivor_low[4];
+ env->spr[SPR_BOOKE_IVOR5] = sregs.u.e.ivor_low[5];
+ env->spr[SPR_BOOKE_IVOR6] = sregs.u.e.ivor_low[6];
+ env->spr[SPR_BOOKE_IVOR7] = sregs.u.e.ivor_low[7];
+ env->spr[SPR_BOOKE_IVOR8] = sregs.u.e.ivor_low[8];
+ env->spr[SPR_BOOKE_IVOR9] = sregs.u.e.ivor_low[9];
+ env->spr[SPR_BOOKE_IVOR10] = sregs.u.e.ivor_low[10];
+ env->spr[SPR_BOOKE_IVOR11] = sregs.u.e.ivor_low[11];
+ env->spr[SPR_BOOKE_IVOR12] = sregs.u.e.ivor_low[12];
+ env->spr[SPR_BOOKE_IVOR13] = sregs.u.e.ivor_low[13];
+ env->spr[SPR_BOOKE_IVOR14] = sregs.u.e.ivor_low[14];
+ env->spr[SPR_BOOKE_IVOR15] = sregs.u.e.ivor_low[15];
+
+ if (sregs.u.e.features & KVM_SREGS_E_SPE) {
+ env->spr[SPR_BOOKE_IVOR32] = sregs.u.e.ivor_high[0];
+ env->spr[SPR_BOOKE_IVOR33] = sregs.u.e.ivor_high[1];
+ env->spr[SPR_BOOKE_IVOR34] = sregs.u.e.ivor_high[2];
+ }
+
+ if (sregs.u.e.features & KVM_SREGS_E_PM) {
+ env->spr[SPR_BOOKE_IVOR35] = sregs.u.e.ivor_high[3];
+ }
+
+ if (sregs.u.e.features & KVM_SREGS_E_PC) {
+ env->spr[SPR_BOOKE_IVOR36] = sregs.u.e.ivor_high[4];
+ env->spr[SPR_BOOKE_IVOR37] = sregs.u.e.ivor_high[5];
+ }
+ }
+
+ if (sregs.u.e.features & KVM_SREGS_E_ARCH206_MMU) {
+ env->spr[SPR_BOOKE_MAS0] = sregs.u.e.mas0;
+ env->spr[SPR_BOOKE_MAS1] = sregs.u.e.mas1;
+ env->spr[SPR_BOOKE_MAS2] = sregs.u.e.mas2;
+ env->spr[SPR_BOOKE_MAS3] = sregs.u.e.mas7_3 & 0xffffffff;
+ env->spr[SPR_BOOKE_MAS4] = sregs.u.e.mas4;
+ env->spr[SPR_BOOKE_MAS6] = sregs.u.e.mas6;
+ env->spr[SPR_BOOKE_MAS7] = sregs.u.e.mas7_3 >> 32;
+ env->spr[SPR_MMUCFG] = sregs.u.e.mmucfg;
+ env->spr[SPR_BOOKE_TLB0CFG] = sregs.u.e.tlbcfg[0];
+ env->spr[SPR_BOOKE_TLB1CFG] = sregs.u.e.tlbcfg[1];
+ }
+
+ if (sregs.u.e.features & KVM_SREGS_EXP) {
+ env->spr[SPR_BOOKE_EPR] = sregs.u.e.epr;
+ }
+
+ if (sregs.u.e.features & KVM_SREGS_E_PD) {
+ env->spr[SPR_BOOKE_EPLC] = sregs.u.e.eplc;
+ env->spr[SPR_BOOKE_EPSC] = sregs.u.e.epsc;
+ }
+
+ if (sregs.u.e.impl_id == KVM_SREGS_E_IMPL_FSL) {
+ env->spr[SPR_E500_SVR] = sregs.u.e.impl.fsl.svr;
+ env->spr[SPR_Exxx_MCAR] = sregs.u.e.impl.fsl.mcar;
+ env->spr[SPR_HID0] = sregs.u.e.impl.fsl.hid0;
+
+ if (sregs.u.e.impl.fsl.features & KVM_SREGS_E_FSL_PIDn) {
+ env->spr[SPR_BOOKE_PID1] = sregs.u.e.impl.fsl.pid1;
+ env->spr[SPR_BOOKE_PID2] = sregs.u.e.impl.fsl.pid2;
+ }
+ }
+ }
+#endif
+
#ifdef KVM_CAP_PPC_SEGSTATE
- if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_SEGSTATE)) {
+ if (cap_segstate) {
+ ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
+ if (ret < 0) {
+ return ret;
+ }
+
ppc_store_sdr1(env, sregs.u.s.sdr1);
/* Sync SLB */
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index a943dbc..99f572a 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2,6 +2,7 @@
* PowerPC emulation for qemu: main translation routines.
*
* Copyright (c) 2003-2007 Jocelyn Mayer
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -9124,9 +9125,84 @@ void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
}
cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
#if !defined(CONFIG_USER_ONLY)
- cpu_fprintf(f, "SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx " SDR1 "
- TARGET_FMT_lx "\n", env->spr[SPR_SRR0], env->spr[SPR_SRR1],
- env->spr[SPR_SDR1]);
+ cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx
+ " PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
+ env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+ env->spr[SPR_PVR], env->spr[SPR_VRSAVE]);
+
+ cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx
+ " SPRG2 " TARGET_FMT_lx " SPRG3 " TARGET_FMT_lx "\n",
+ env->spr[SPR_SPRG0], env->spr[SPR_SPRG1],
+ env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]);
+
+ cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx
+ " SPRG6 " TARGET_FMT_lx " SPRG7 " TARGET_FMT_lx "\n",
+ env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
+ env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);
+
+ if (env->excp_model == POWERPC_EXCP_BOOKE) {
+ cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
+ " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
+ env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
+ env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
+
+ cpu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
+ " ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
+ env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR],
+ env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
+
+ cpu_fprintf(f, " PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx
+ " IVPR " TARGET_FMT_lx " EPCR " TARGET_FMT_lx "\n",
+ env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR],
+ env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]);
+
+ cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx
+ " EPR " TARGET_FMT_lx "\n",
+ env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8],
+ env->spr[SPR_BOOKE_EPR]);
+
+ /* FSL-specific */
+ cpu_fprintf(f, " MCAR " TARGET_FMT_lx " PID1 " TARGET_FMT_lx
+ " PID2 " TARGET_FMT_lx " SVR " TARGET_FMT_lx "\n",
+ env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1],
+ env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]);
+
+ /*
+ * IVORs are left out as they are large and do not change often --
+ * they can be read with "p $ivor0", "p $ivor1", etc.
+ */
+ }
+
+ switch (env->mmu_model) {
+ case POWERPC_MMU_32B:
+ case POWERPC_MMU_601:
+ case POWERPC_MMU_SOFT_6xx:
+ case POWERPC_MMU_SOFT_74xx:
+#if defined(TARGET_PPC64)
+ case POWERPC_MMU_620:
+ case POWERPC_MMU_64B:
+#endif
+ cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
+ break;
+ case POWERPC_MMU_BOOKE_FSL:
+ cpu_fprintf(f, " MAS0 " TARGET_FMT_lx " MAS1 " TARGET_FMT_lx
+ " MAS2 " TARGET_FMT_lx " MAS3 " TARGET_FMT_lx "\n",
+ env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
+ env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]);
+
+ cpu_fprintf(f, " MAS4 " TARGET_FMT_lx " MAS6 " TARGET_FMT_lx
+ " MAS7 " TARGET_FMT_lx " PID " TARGET_FMT_lx "\n",
+ env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6],
+ env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]);
+
+ cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx
+ " TLB1CFG " TARGET_FMT_lx "\n",
+ env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG],
+ env->spr[SPR_BOOKE_TLB1CFG]);
+ break;
+ default:
+ break;
+ }
#endif
#undef RGPL
commit 5666ca4ae06d20497f887241151278e266947087
Author: Scott Wood <scottwood at freescale.com>
Date: Mon Apr 11 18:34:34 2011 -0500
kvm: ppc: fixes for KVM_SET_SREGS on init
Classic/server ppc has had SREGS for a while now (though I think not
always?), but it's still missing for booke. Check the capability before
calling KVM_SET_SREGS.
Without this, booke kvm fails to boot as of commit
84b4915dd2c0eaa86c970ffc42a68ea8ba9e48b5 (kvm: Handle kvm_init_vcpu
errors).
Also, don't write random stack state into the non-PVR sregs fields --
have kvm fill it in first.
Eventually booke will have sregs and it will have its own capability to
be tested here. However, we will want a way for platform code to request
to look like the actual CPU we're running on, especially if SoC devices
are being directly assigned.
Signed-off-by: Scott Wood <scottwood at freescale.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 2cfb24b..3ca39b7 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -77,13 +77,40 @@ int kvm_arch_init(KVMState *s)
return 0;
}
-int kvm_arch_init_vcpu(CPUState *cenv)
+static int kvm_arch_sync_sregs(CPUState *cenv)
{
- int ret = 0;
struct kvm_sregs sregs;
+ int ret;
+
+ if (cenv->excp_model == POWERPC_EXCP_BOOKE) {
+ return 0;
+ } else {
+#ifdef KVM_CAP_PPC_SEGSTATE
+ if (!kvm_check_extension(cenv->kvm_state, KVM_CAP_PPC_SEGSTATE)) {
+ return 0;
+ }
+#else
+ return 0;
+#endif
+ }
+
+ ret = kvm_vcpu_ioctl(cenv, KVM_GET_SREGS, &sregs);
+ if (ret) {
+ return ret;
+ }
sregs.pvr = cenv->spr[SPR_PVR];
- ret = kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
+ return kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
+}
+
+int kvm_arch_init_vcpu(CPUState *cenv)
+{
+ int ret;
+
+ ret = kvm_arch_sync_sregs(cenv);
+ if (ret) {
+ return ret;
+ }
idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_env, cenv);
commit d0384d1d38f3ae13909b527ba0676429472b2807
Author: Andreas Färber <andreas.faerber at web.de>
Date: Sun May 1 18:23:56 2011 +0200
ppc64: Don't try to build sPAPR RTAS on Darwin
The Darwin assembler fails to build it.
Cc: David Gibson <david at gibson.dropbear.id.au>
Cc: Alexander Graf <agraf at suse.de>
Signed-off-by: Andreas Färber <andreas.faerber at web.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/configure b/configure
index 6f75e2e..fbf5d5f 100755
--- a/configure
+++ b/configure
@@ -2540,7 +2540,7 @@ if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
"$softmmu" = yes ; then
roms="optionrom"
fi
-if test "$cpu" = "ppc64" ; then
+if test "$cpu" = "ppc64" -a "$targetos" != "Darwin" ; then
roms="$roms spapr-rtas"
fi
commit b4a78527359a4540d84d4cdf629d01cbb262f698
Author: David Gibson <david at gibson.dropbear.id.au>
Date: Tue Apr 19 11:54:52 2011 +1000
Place pseries vty devices at addresses more similar to existing machines
Currently the qemu pseries machine numbers its virtual serial devices
from 0. However, existing pSeries machines running pHyp number them from
0x30000000.
In theory these indices are arbitrary, since everything necessary for the
kernel to find them is advertised in the device tree. However the debian
installer, at least, incorrectly looks for a device named vty at 30... to
determine whether to use the hypervisor console.
Therefore this patch moves the numbers we use to match the existing pHyp
practice, in order to workaround broken userspace apps of this type.
Signed-off-by: David Gibson <dwg at au1.ibm.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/spapr.c b/hw/spapr.c
index 884c667..109b774 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -362,8 +362,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
for (i = 0; i < MAX_SERIAL_PORTS; i++, irq++) {
if (serial_hds[i]) {
- spapr_vty_create(spapr->vio_bus, i, serial_hds[i],
- xics_find_qirq(spapr->icp, irq), irq);
+ spapr_vty_create(spapr->vio_bus, SPAPR_VTY_BASE_ADDRESS + i,
+ serial_hds[i], xics_find_qirq(spapr->icp, irq),
+ irq);
}
}
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 16b6542..00c8ce5 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -44,7 +44,8 @@ static void rtas_display_character(sPAPREnvironment *spapr,
uint32_t nret, target_ulong rets)
{
uint8_t c = rtas_ld(args, 0);
- VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, 0);
+ VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus,
+ SPAPR_VTY_BASE_ADDRESS);
if (!sdev) {
rtas_st(rets, 0, -1);
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 841b043..603a8c4 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -32,6 +32,8 @@ enum VIOsPAPR_TCEAccess {
SPAPR_TCE_RW = 3,
};
+#define SPAPR_VTY_BASE_ADDRESS 0x30000000
+
struct VIOsPAPRDevice;
typedef struct VIOsPAPR_RTCE {
commit 5d73dd66e46f4aff784d15d0e869813dc4b1029a
Author: David Gibson <david at gibson.dropbear.id.au>
Date: Tue Apr 19 11:54:51 2011 +1000
Make pSeries 'model' property more closely resemble real hardware
Currently, the qemu emulated pseries machine puts
"qemu,emulated-pSeries-LPAR" in the device tree's root level 'model'
property. Unfortunately this confuses some installers and ybin, which
expect this to start with "IBM" on pSeries machines. This patch addresses
this problem, making the property more closely resemble the pattern of
existing real hardware.
Signed-off-by: David Gibson <dwg at au1.ibm.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/spapr.c b/hw/spapr.c
index 67dd1e5..884c667 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -93,7 +93,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
/* Root node */
_FDT((fdt_begin_node(fdt, "")));
_FDT((fdt_property_string(fdt, "device_type", "chrp")));
- _FDT((fdt_property_string(fdt, "model", "qemu,emulated-pSeries-LPAR")));
+ _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
_FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
_FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
commit 41019fecc83c466faeddbc6b3784a447516c03a7
Author: Anton Blanchard <anton at au1.ibm.com>
Date: Tue Apr 19 11:54:50 2011 +1000
pseries: Increase maximum CPUs to 256
The original pSeries machine was limited to 32 CPUs, more or less
arbitrarily. Particularly when we get SMT KVM guests it will be
pretty easy to exceed this. Therefore, raise the max number of CPUs
in a pseries machine guest to 256.
Signed-off-by: Anton Blanchard <anton at au1.ibm.com>
Signed-off-by: David Gibson <dwg at au1.ibm.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/spapr.c b/hw/spapr.c
index 1782cc0..67dd1e5 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -51,7 +51,7 @@
#define TIMEBASE_FREQ 512000000ULL
-#define MAX_CPUS 32
+#define MAX_CPUS 256
#define XICS_IRQS 1024
sPAPREnvironment *spapr;
commit 0225e254ae81c5638463cda8f5730f31619113b6
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat May 7 22:10:53 2011 +0200
usb-linux: Add missing break statement
cppcheck report:
usb-linux.c:661: warning: Redundant assignment of "len" in switch
Cc: Hans de Goede <hdegoede at redhat.com>
Cc: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/usb-linux.c b/usb-linux.c
index 36a01ea..0ef1d26 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -659,6 +659,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
switch(errno) {
case ETIMEDOUT:
len = USB_RET_NAK;
+ break;
case EPIPE:
default:
len = USB_RET_STALL;
commit b3e5759e090e7f1dcb8d226bd77a3db203892ebd
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Mon May 9 09:44:03 2011 +0200
usb-musb: uninline functions
Prototype without "inline" keyword breaks the build with some gcc
versions. Noticed by Alexander Graf.
Fix this by removing the inline keywork everywhere. Some functions
can't be inlined anyway as the are referenced using function pointers.
Beside that gcc does a pretty good job on auto-inlining these days.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index b30caeb..38986d3 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -497,14 +497,14 @@ static void musb_detach(USBPort *port)
musb_session_update(s, 1, s->session);
}
-static inline void musb_cb_tick0(void *opaque)
+static void musb_cb_tick0(void *opaque)
{
MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
ep->delayed_cb[0](&ep->packey[0].p, opaque);
}
-static inline void musb_cb_tick1(void *opaque)
+static void musb_cb_tick1(void *opaque)
{
MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
@@ -513,7 +513,7 @@ static inline void musb_cb_tick1(void *opaque)
#define musb_cb_tick (dir ? musb_cb_tick1 : musb_cb_tick0)
-static inline void musb_schedule_cb(USBDevice *dev, USBPacket *packey)
+static void musb_schedule_cb(USBDevice *dev, USBPacket *packey)
{
MUSBPacket *p = container_of(packey, MUSBPacket, p);
MUSBEndPoint *ep = p->ep;
@@ -572,7 +572,7 @@ static int musb_timeout(int ttype, int speed, int val)
hw_error("bad interval\n");
}
-static inline void musb_packet(MUSBState *s, MUSBEndPoint *ep,
+static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
int epnum, int pid, int len, USBCallback cb, int dir)
{
int ret;
commit 85097db6956bc86e2377b63a8309cb8b24d54139
Author: Richard Henderson <rth at twiddle.net>
Date: Wed May 4 13:34:31 2011 -0700
irq: Privatize CPU_INTERRUPT_NMI.
This interrupt name is used by i386, CRIS, and MicroBlaze.
Copy the name into each target.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/cpu-all.h b/cpu-all.h
index 39dfa46..54df1d3 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -826,10 +826,6 @@ extern CPUState *cpu_single_env;
/* First unused bit: 0x2000. */
-/* Temporary remapping from the generic names back to the previous
- cpu-specific names. These will be moved to target-foo/cpu.h next. */
-#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
-
/* The set of all bits that should be masked when single-stepping. */
#define CPU_INTERRUPT_SSTEP_MASK \
(CPU_INTERRUPT_HARD \
diff --git a/poison.h b/poison.h
index 4fcf46d..2b18232 100644
--- a/poison.h
+++ b/poison.h
@@ -41,7 +41,6 @@
#pragma GCC poison CPU_INTERRUPT_EXITTB
#pragma GCC poison CPU_INTERRUPT_HALT
#pragma GCC poison CPU_INTERRUPT_DEBUG
-#pragma GCC poison CPU_INTERRUPT_NMI
#pragma GCC poison CPU_INTERRUPT_TGT_EXT_0
#pragma GCC poison CPU_INTERRUPT_TGT_EXT_1
#pragma GCC poison CPU_INTERRUPT_TGT_EXT_2
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index d908775..8686dba 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -36,6 +36,9 @@
#define EXCP_IRQ 4
#define EXCP_BREAK 5
+/* CRIS-specific interrupt pending bits. */
+#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
+
/* Register aliases. R0 - R15 */
#define R_FP 8
#define R_SP 14
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 1fc421f..715828f 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -468,6 +468,7 @@
/* i386-specific interrupt pending bits. */
#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
+#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
#define CPU_INTERRUPT_MCE CPU_INTERRUPT_TGT_EXT_4
#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_INT_0
#define CPU_INTERRUPT_INIT CPU_INTERRUPT_TGT_INT_1
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 536222e..78fe14f 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -41,6 +41,9 @@ struct CPUMBState;
#define EXCP_HW_BREAK 5
#define EXCP_HW_EXCP 6
+/* MicroBlaze-specific interrupt pending bits. */
+#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
+
/* Register aliases. R0 - R15 */
#define R_SP 1
#define SR_PC 0
commit 00a152b48b0b7d9d77842511afcf59b5f25ec554
Author: Richard Henderson <rth at twiddle.net>
Date: Wed May 4 13:34:30 2011 -0700
target-i386: Privatize some i386-specific interrupt names.
SMI, VIRQ, INIT, SIPI, and MCE are all only used by the i386 port.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/cpu-all.h b/cpu-all.h
index b1305db..39dfa46 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -828,12 +828,7 @@ extern CPUState *cpu_single_env;
/* Temporary remapping from the generic names back to the previous
cpu-specific names. These will be moved to target-foo/cpu.h next. */
-#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
-#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_INT_0
#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
-#define CPU_INTERRUPT_INIT CPU_INTERRUPT_TGT_INT_1
-#define CPU_INTERRUPT_SIPI CPU_INTERRUPT_TGT_INT_2
-#define CPU_INTERRUPT_MCE CPU_INTERRUPT_TGT_EXT_4
/* The set of all bits that should be masked when single-stepping. */
#define CPU_INTERRUPT_SSTEP_MASK \
diff --git a/poison.h b/poison.h
index 787f8e9..4fcf46d 100644
--- a/poison.h
+++ b/poison.h
@@ -40,9 +40,7 @@
#pragma GCC poison CPU_INTERRUPT_HARD
#pragma GCC poison CPU_INTERRUPT_EXITTB
#pragma GCC poison CPU_INTERRUPT_HALT
-#pragma GCC poison CPU_INTERRUPT_SMI
#pragma GCC poison CPU_INTERRUPT_DEBUG
-#pragma GCC poison CPU_INTERRUPT_VIRQ
#pragma GCC poison CPU_INTERRUPT_NMI
#pragma GCC poison CPU_INTERRUPT_TGT_EXT_0
#pragma GCC poison CPU_INTERRUPT_TGT_EXT_1
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index c7047d5..1fc421f 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -466,6 +466,14 @@
#define EXCP_SYSCALL 0x100 /* only happens in user only emulation
for syscall instruction */
+/* i386-specific interrupt pending bits. */
+#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
+#define CPU_INTERRUPT_MCE CPU_INTERRUPT_TGT_EXT_4
+#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_INT_0
+#define CPU_INTERRUPT_INIT CPU_INTERRUPT_TGT_INT_1
+#define CPU_INTERRUPT_SIPI CPU_INTERRUPT_TGT_INT_2
+
+
enum {
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
CC_OP_EFLAGS, /* all cc are explicitly computed, CC_SRC = flags */
commit 403946c009cc7fd8a8aa719236801ed12121f8fd
Author: Richard Henderson <rth at twiddle.net>
Date: Wed May 4 13:34:29 2011 -0700
target-arm: Privatize CPU_INTERRUPT_FIQ.
This interrupt name was only used by the ARM port.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/cpu-all.h b/cpu-all.h
index a30943f..b1305db 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -828,7 +828,6 @@ extern CPUState *cpu_single_env;
/* Temporary remapping from the generic names back to the previous
cpu-specific names. These will be moved to target-foo/cpu.h next. */
-#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_INT_0
#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
diff --git a/poison.h b/poison.h
index 369d82d..787f8e9 100644
--- a/poison.h
+++ b/poison.h
@@ -39,7 +39,6 @@
#pragma GCC poison CPU_INTERRUPT_HARD
#pragma GCC poison CPU_INTERRUPT_EXITTB
-#pragma GCC poison CPU_INTERRUPT_FIQ
#pragma GCC poison CPU_INTERRUPT_HALT
#pragma GCC poison CPU_INTERRUPT_SMI
#pragma GCC poison CPU_INTERRUPT_DEBUG
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index d5af644..01f5b57 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -55,6 +55,10 @@
#define ARMV7M_EXCP_PENDSV 14
#define ARMV7M_EXCP_SYSTICK 15
+/* ARM-specific interrupt pending bits. */
+#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
+
+
typedef void ARMWriteCPFunc(void *opaque, int cp_info,
int srcreg, int operand, uint32_t value);
typedef uint32_t ARMReadCPFunc(void *opaque, int cp_info,
commit d1520316042de4f31e5c1464a992ffe57f1b6652
Author: Richard Henderson <rth at twiddle.net>
Date: Wed May 4 13:34:28 2011 -0700
irq: Remove CPU_INTERRUPT_TIMER.
It is no longer used anywhere.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/cpu-all.h b/cpu-all.h
index bc0dad8..a30943f 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -828,7 +828,6 @@ extern CPUState *cpu_single_env;
/* Temporary remapping from the generic names back to the previous
cpu-specific names. These will be moved to target-foo/cpu.h next. */
-#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_EXT_0
#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_INT_0
diff --git a/poison.h b/poison.h
index 8fa3ee6..369d82d 100644
--- a/poison.h
+++ b/poison.h
@@ -39,7 +39,6 @@
#pragma GCC poison CPU_INTERRUPT_HARD
#pragma GCC poison CPU_INTERRUPT_EXITTB
-#pragma GCC poison CPU_INTERRUPT_TIMER
#pragma GCC poison CPU_INTERRUPT_FIQ
#pragma GCC poison CPU_INTERRUPT_HALT
#pragma GCC poison CPU_INTERRUPT_SMI
commit 78aa29e4b8b0df716a25edc689cf24c7b5b424fe
Author: Richard Henderson <rth at twiddle.net>
Date: Wed May 4 13:34:27 2011 -0700
target-sparc: Do not check CPU_INTERRUPT_TIMER.
This bit is never set, therefore we should not read it either.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/cpu-exec.c b/cpu-exec.c
index 5b42b25..6d43726 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -489,9 +489,6 @@ int cpu_exec(CPUState *env1)
next_tb = 0;
}
}
- } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
- //do_interrupt(0, 0, 0, 0, 0);
- env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
}
#elif defined(TARGET_ARM)
if (interrupt_request & CPU_INTERRUPT_FIQ
commit ce0c6930cc2c199eee2d391e23759204a235b162
Author: Richard Henderson <rth at twiddle.net>
Date: Wed May 4 13:34:26 2011 -0700
target-mips: Do not check CPU_INTERRUPT_TIMER.
This bit is never set, therefore we should not read it either.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-mips/exec.h b/target-mips/exec.h
index b3c5a13..607edf1 100644
--- a/target-mips/exec.h
+++ b/target-mips/exec.h
@@ -29,10 +29,6 @@ static inline int cpu_has_work(CPUState *env)
has_work = 1;
}
- if (env->interrupt_request & CPU_INTERRUPT_TIMER) {
- has_work = 1;
- }
-
return has_work;
}
commit 3125f76335f54e17e2b41621184c9cda1c2b238e
Author: Richard Henderson <rth at twiddle.net>
Date: Wed May 4 13:34:25 2011 -0700
irq: Introduce and use CPU_INTERRUPT_SSTEP_MASK.
This mask contains all of the bits that should be ignored while single
stepping in the debugger. The mask contains 2 bits that are not currently
cleared, but are also never set. The bits are included in the mask for
consistency in handling of the CPU_INTERRUPT_TGT_EXT_N bits.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/cpu-all.h b/cpu-all.h
index dd9c230..bc0dad8 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -837,6 +837,14 @@ extern CPUState *cpu_single_env;
#define CPU_INTERRUPT_SIPI CPU_INTERRUPT_TGT_INT_2
#define CPU_INTERRUPT_MCE CPU_INTERRUPT_TGT_EXT_4
+/* The set of all bits that should be masked when single-stepping. */
+#define CPU_INTERRUPT_SSTEP_MASK \
+ (CPU_INTERRUPT_HARD \
+ | CPU_INTERRUPT_TGT_EXT_0 \
+ | CPU_INTERRUPT_TGT_EXT_1 \
+ | CPU_INTERRUPT_TGT_EXT_2 \
+ | CPU_INTERRUPT_TGT_EXT_3 \
+ | CPU_INTERRUPT_TGT_EXT_4)
#ifndef CONFIG_USER_ONLY
typedef void (*CPUInterruptHandler)(CPUState *, int);
diff --git a/cpu-exec.c b/cpu-exec.c
index 395cd8c..5b42b25 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -360,10 +360,7 @@ int cpu_exec(CPUState *env1)
if (unlikely(interrupt_request)) {
if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
/* Mask out external interrupts for this step. */
- interrupt_request &= ~(CPU_INTERRUPT_HARD |
- CPU_INTERRUPT_FIQ |
- CPU_INTERRUPT_SMI |
- CPU_INTERRUPT_NMI);
+ interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
}
if (interrupt_request & CPU_INTERRUPT_DEBUG) {
env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
commit 9c76219eaa68e9138521a8e28ee3fff056c83fb1
Author: Richard Henderson <rth at twiddle.net>
Date: Wed May 4 13:34:24 2011 -0700
irq: Introduce CPU_INTERRUPT_TGT_* defines.
These defines will be place-holders for cpu-specific functionality.
Generic code will, at the end of the patch series, no longer have to
concern itself about how SMI, NMI, etc should be handled. Instead,
generic code will know only that the interrupt is internal or external.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/cpu-all.h b/cpu-all.h
index 88126ea..dd9c230 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -786,18 +786,57 @@ void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...)
extern CPUState *first_cpu;
extern CPUState *cpu_single_env;
-#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
-#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
-#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
-#define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
-#define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
-#define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */
-#define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occured. */
-#define CPU_INTERRUPT_VIRQ 0x100 /* virtual interrupt pending. */
-#define CPU_INTERRUPT_NMI 0x200 /* NMI pending. */
-#define CPU_INTERRUPT_INIT 0x400 /* INIT pending. */
-#define CPU_INTERRUPT_SIPI 0x800 /* SIPI pending. */
-#define CPU_INTERRUPT_MCE 0x1000 /* (x86 only) MCE pending. */
+/* Flags for use in ENV->INTERRUPT_PENDING.
+
+ The numbers assigned here are non-sequential in order to preserve
+ binary compatibility with the vmstate dump. Bit 0 (0x0001) was
+ previously used for CPU_INTERRUPT_EXIT, and is cleared when loading
+ the vmstate dump. */
+
+/* External hardware interrupt pending. This is typically used for
+ interrupts from devices. */
+#define CPU_INTERRUPT_HARD 0x0002
+
+/* Exit the current TB. This is typically used when some system-level device
+ makes some change to the memory mapping. E.g. the a20 line change. */
+#define CPU_INTERRUPT_EXITTB 0x0004
+
+/* Halt the CPU. */
+#define CPU_INTERRUPT_HALT 0x0020
+
+/* Debug event pending. */
+#define CPU_INTERRUPT_DEBUG 0x0080
+
+/* Several target-specific external hardware interrupts. Each target/cpu.h
+ should define proper names based on these defines. */
+#define CPU_INTERRUPT_TGT_EXT_0 0x0008
+#define CPU_INTERRUPT_TGT_EXT_1 0x0010
+#define CPU_INTERRUPT_TGT_EXT_2 0x0040
+#define CPU_INTERRUPT_TGT_EXT_3 0x0200
+#define CPU_INTERRUPT_TGT_EXT_4 0x1000
+
+/* Several target-specific internal interrupts. These differ from the
+ preceeding target-specific interrupts in that they are intended to
+ originate from within the cpu itself, typically in response to some
+ instruction being executed. These, therefore, are not masked while
+ single-stepping within the debugger. */
+#define CPU_INTERRUPT_TGT_INT_0 0x0100
+#define CPU_INTERRUPT_TGT_INT_1 0x0400
+#define CPU_INTERRUPT_TGT_INT_2 0x0800
+
+/* First unused bit: 0x2000. */
+
+/* Temporary remapping from the generic names back to the previous
+ cpu-specific names. These will be moved to target-foo/cpu.h next. */
+#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_EXT_0
+#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
+#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
+#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_INT_0
+#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
+#define CPU_INTERRUPT_INIT CPU_INTERRUPT_TGT_INT_1
+#define CPU_INTERRUPT_SIPI CPU_INTERRUPT_TGT_INT_2
+#define CPU_INTERRUPT_MCE CPU_INTERRUPT_TGT_EXT_4
+
#ifndef CONFIG_USER_ONLY
typedef void (*CPUInterruptHandler)(CPUState *, int);
diff --git a/poison.h b/poison.h
index 93c75fa..8fa3ee6 100644
--- a/poison.h
+++ b/poison.h
@@ -46,6 +46,14 @@
#pragma GCC poison CPU_INTERRUPT_DEBUG
#pragma GCC poison CPU_INTERRUPT_VIRQ
#pragma GCC poison CPU_INTERRUPT_NMI
+#pragma GCC poison CPU_INTERRUPT_TGT_EXT_0
+#pragma GCC poison CPU_INTERRUPT_TGT_EXT_1
+#pragma GCC poison CPU_INTERRUPT_TGT_EXT_2
+#pragma GCC poison CPU_INTERRUPT_TGT_EXT_3
+#pragma GCC poison CPU_INTERRUPT_TGT_EXT_4
+#pragma GCC poison CPU_INTERRUPT_TGT_INT_0
+#pragma GCC poison CPU_INTERRUPT_TGT_INT_1
+#pragma GCC poison CPU_INTERRUPT_TGT_INT_2
#endif
#endif
commit 2f172849b63b166fe876aa97b411f63ee7d17467
Author: Hannes Reinecke <hare at suse.de>
Date: Mon May 2 09:54:05 2011 +0200
lsi53c895a: Rename 'sense' to 'status'
The 'sense' field in the HBA status structure is misnamed, as it
actually carries the SCSI status. Rename it.
Signed-off-by: Hannes Reinecke <hare at suse.de>
Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Cc: qemu-trivial at nongnu.org
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index be4df58..2ce38a9 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -189,7 +189,7 @@ typedef struct {
uint32_t script_ram_base;
int carry; /* ??? Should this be an a visible register somewhere? */
- int sense;
+ int status;
/* Action to take at the end of a MSG IN phase.
0 = COMMAND, 1 = disconnect, 2 = DATA OUT, 3 = DATA IN. */
int msg_action;
@@ -695,8 +695,8 @@ static void lsi_command_complete(SCSIBus *bus, int reason, uint32_t tag,
out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
if (reason == SCSI_REASON_DONE) {
- DPRINTF("Command complete sense=%d\n", (int)arg);
- s->sense = arg;
+ DPRINTF("Command complete status=%d\n", (int)arg);
+ s->status = arg;
s->command_complete = 2;
if (s->waiting && s->dbc != 0) {
/* Raise phase mismatch for short transfers. */
@@ -783,14 +783,14 @@ static void lsi_do_command(LSIState *s)
static void lsi_do_status(LSIState *s)
{
- uint8_t sense;
- DPRINTF("Get status len=%d sense=%d\n", s->dbc, s->sense);
+ uint8_t status;
+ DPRINTF("Get status len=%d status=%d\n", s->dbc, s->status);
if (s->dbc != 1)
BADF("Bad Status move\n");
s->dbc = 1;
- sense = s->sense;
- s->sfbr = sense;
- cpu_physical_memory_write(s->dnad, &sense, 1);
+ status = s->status;
+ s->sfbr = status;
+ cpu_physical_memory_write(s->dnad, &status, 1);
lsi_set_phase(s, PHASE_MI);
s->msg_action = 1;
lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */
@@ -2122,7 +2122,7 @@ static const VMStateDescription vmstate_lsi_scsi = {
VMSTATE_PCI_DEVICE(dev, LSIState),
VMSTATE_INT32(carry, LSIState),
- VMSTATE_INT32(sense, LSIState),
+ VMSTATE_INT32(status, LSIState),
VMSTATE_INT32(msg_action, LSIState),
VMSTATE_INT32(msg_len, LSIState),
VMSTATE_BUFFER(msg, LSIState),
commit 6774e44ae3bfe074f59a16ffb0b52ae441b9c66d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Mon May 2 09:54:03 2011 +0200
libcacard: add correct subdirectory dependencies
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Cc: qemu-trivial at nongnu.org
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/Makefile b/Makefile
index 67c0268..2b0438c 100644
--- a/Makefile
+++ b/Makefile
@@ -88,6 +88,8 @@ include $(SRC_PATH)/Makefile.objs
endif
$(common-obj-y): $(GENERATED_HEADERS)
+subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-malloc.o qemu-timer-common.o
+
$(filter %-softmmu,$(SUBDIR_RULES)): $(trace-obj-y) $(common-obj-y) subdir-libdis
$(filter %-user,$(SUBDIR_RULES)): $(GENERATED_HEADERS) $(trace-obj-y) subdir-libdis-user subdir-libuser
diff --git a/Makefile.objs b/Makefile.objs
index d82c60d..4478c61 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -7,8 +7,8 @@ qobject-obj-y += qerror.o
#######################################################################
# oslib-obj-y is code depending on the OS (win32 vs posix)
oslib-obj-y = osdep.o
-oslib-obj-$(CONFIG_WIN32) += oslib-win32.o
-oslib-obj-$(CONFIG_POSIX) += oslib-posix.o
+oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o
+oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o
#######################################################################
# block-obj-y is code used by both qemu system emulation and qemu-img
@@ -143,8 +143,7 @@ common-obj-y += $(addprefix ui/, $(ui-obj-y))
common-obj-$(CONFIG_VNC) += $(addprefix ui/, $(vnc-obj-y))
common-obj-y += iov.o acl.o
-common-obj-$(CONFIG_POSIX) += qemu-thread-posix.o compatfd.o
-common-obj-$(CONFIG_WIN32) += qemu-thread-win32.o
+common-obj-$(CONFIG_POSIX) += compatfd.o
common-obj-y += notify.o event_notifier.o
common-obj-y += qemu-timer.o qemu-timer-common.o
diff --git a/libcacard/Makefile b/libcacard/Makefile
index 4010029..1d34df0 100644
--- a/libcacard/Makefile
+++ b/libcacard/Makefile
@@ -4,14 +4,7 @@
$(call set-vpath, $(SRC_PATH):$(SRC_PATH)/libcacard)
-ifeq ($(CONFIG_WIN32),y)
-QEMU_THREAD=qemu-thread-win32.o
-else
-QEMU_THREAD=qemu-thread-posix.o
-endif
-
-
-QEMU_OBJS=$(addprefix ../, $(QEMU_THREAD) $(oslib-obj-y) $(trace-obj-y) qemu-malloc.o qemu-timer-common.o)
+QEMU_OBJS=$(addprefix ../, $(oslib-obj-y) $(trace-obj-y) qemu-malloc.o qemu-timer-common.o)
QEMU_CFLAGS+=-I../
commit 67bd9edec385b1244c06cce15fe88cc9a9da7097
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat May 7 22:32:25 2011 +0200
linux-user: Replace deprecated function
Function bzero is deprecated, so replace it by function memset.
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 279cef3..6e7d88e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -287,7 +287,7 @@ static int sys_uname(struct new_utsname *buf)
* struct linux kernel uses).
*/
- bzero(buf, sizeof (*buf));
+ memset(buf, 0, sizeof(*buf));
COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
commit 5ba185473b20902e862e90d89cabfa7f42f13a40
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat May 7 22:20:03 2011 +0200
Fix spelling in comments (intruction -> instruction)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 6b12f8b..0c3fca1 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -237,7 +237,7 @@ void cpu_loop(CPUX86State *env)
break;
#ifndef TARGET_ABI32
case EXCP_SYSCALL:
- /* syscall from syscall intruction */
+ /* syscall from syscall instruction */
if (bsd_type == target_freebsd)
env->regs[R_EAX] = do_freebsd_syscall(env,
env->regs[R_EAX],
diff --git a/linux-user/main.c b/linux-user/main.c
index a1e37e4..a4996e7 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -323,7 +323,7 @@ void cpu_loop(CPUX86State *env)
break;
#ifndef TARGET_ABI32
case EXCP_SYSCALL:
- /* linux syscall from syscall intruction */
+ /* linux syscall from syscall instruction */
env->regs[R_EAX] = do_syscall(env,
env->regs[R_EAX],
env->regs[R_EDI],
diff --git a/tests/test-i386.c b/tests/test-i386.c
index 8f481c7..56ff110 100644
--- a/tests/test-i386.c
+++ b/tests/test-i386.c
@@ -2281,7 +2281,7 @@ void test_sse_comi(double a1, double b1)
}
/* Force %xmm0 usage to avoid the case where both register index are 0
- to test intruction decoding more extensively */
+ to test instruction decoding more extensively */
#define CVT_OP_XMM2MMX(op)\
{\
asm volatile (#op " %1, %0" : "=y" (r.q[0]) : "x" (a.dq) \
commit 7ba4cbbf2e207a5383c30a27f5df9a9806a466d9
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sun May 8 08:58:11 2011 +0200
ac97: Remove unused local variables
cppcheck report:
hw/ac97.c:1004: style:
Variable 'written' is assigned a value that is never used
hw/ac97.c:1072: style:
Variable 'written' is assigned a value that is never used
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/hw/ac97.c b/hw/ac97.c
index d71072d..a946c1a 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1001,8 +1001,6 @@ static int write_audio (AC97LinkState *s, AC97BusMasterRegs *r,
static void write_bup (AC97LinkState *s, int elapsed)
{
- int written = 0;
-
dolog ("write_bup\n");
if (!(s->bup_flag & BUP_SET)) {
if (s->bup_flag & BUP_LAST) {
@@ -1026,7 +1024,6 @@ static void write_bup (AC97LinkState *s, int elapsed)
return;
temp -= copied;
elapsed -= copied;
- written += copied;
}
}
}
@@ -1069,7 +1066,7 @@ static int read_audio (AC97LinkState *s, AC97BusMasterRegs *r,
static void transfer_audio (AC97LinkState *s, int index, int elapsed)
{
AC97BusMasterRegs *r = &s->bm_regs[index];
- int written = 0, stop = 0;
+ int stop = 0;
if (s->invalid_freq[index]) {
AUD_log ("ac97", "attempt to use voice %d with invalid frequency %d\n",
@@ -1114,7 +1111,6 @@ static void transfer_audio (AC97LinkState *s, int index, int elapsed)
switch (index) {
case PO_INDEX:
temp = write_audio (s, r, elapsed, &stop);
- written += temp;
elapsed -= temp;
r->picb -= (temp >> 1);
break;
commit 0d50d616fe42fdcbb95ee8000a9a6603cb8c2e34
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:42 2011 +0200
Fix typos in comment (threshhold -> threshold, mapp -> map)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index e32534f..571a5b0 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -134,10 +134,10 @@ static inline int stream_idle(struct AXIStream *s)
static void stream_reset(struct AXIStream *s)
{
s->regs[R_DMASR] = DMASR_HALTED; /* starts up halted. */
- s->regs[R_DMACR] = 1 << 16; /* Starts with one in compl threshhold. */
+ s->regs[R_DMACR] = 1 << 16; /* Starts with one in compl threshold. */
}
-/* Mapp an offset addr into a channel index. */
+/* Map an offset addr into a channel index. */
static inline int streamid_from_addr(target_phys_addr_t addr)
{
int sid;
commit 8186e78311333a09315d86ea239c785c78519da1
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:41 2011 +0200
Fix typo in comment (truely -> truly)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 0cf22f8..994c02b 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -354,7 +354,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
}
wrapped = 1;
/* Don't actually use 0 when wrapping, instead indicate
- that we'd truely like an allocation in low memory. */
+ that we'd truly like an allocation in low memory. */
addr = (mmap_min_addr > TARGET_PAGE_SIZE
? TARGET_PAGE_ALIGN(mmap_min_addr)
: TARGET_PAGE_SIZE);
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index 41db158..5b14157 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -956,7 +956,7 @@ static int dec10_bdap_m(DisasContext *dc, int size)
return insn_len;
}
#endif
- /* Now the rest of the modes are truely indirect. */
+ /* Now the rest of the modes are truly indirect. */
insn_len += dec10_prep_move_m(dc, 1, size, cpu_PR[PR_PREFIX]);
tcg_gen_add_tl(cpu_PR[PR_PREFIX], cpu_PR[PR_PREFIX], cpu_R[rd]);
cris_set_prefix(dc);
commit e8e3bb2fa815095a79bcec29d5de3459024d28da
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:40 2011 +0200
Fix typo in comment (responsiblity -> responsibility)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index 0c4e8a5..f08d3c7 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -612,7 +612,7 @@ static bool pcie_aer_inject_uncor_error(PCIEAERInject *inj, bool is_fatal)
/*
* non-Function specific error must be recorded in all functions.
* It is the responsibility of the caller of this function.
- * It is also caller's responsiblity to determine which function should
+ * It is also caller's responsibility to determine which function should
* report the rerror.
*
* 6.2.4 Error Logging
commit 9cbc67fefee6008f7ea90f13093b4328f99f545d
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:39 2011 +0200
Fix typo in comment (relevent -> relevant)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/hppa-dis.c b/hppa-dis.c
index 49f99c8..a5760a9 100644
--- a/hppa-dis.c
+++ b/hppa-dis.c
@@ -1645,7 +1645,7 @@ static const char *const fp_reg_names[] =
typedef unsigned int CORE_ADDR;
-/* Get at various relevent fields of an instruction word. */
+/* Get at various relevant fields of an instruction word. */
#define MASK_5 0x1f
#define MASK_10 0x3ff
commit a1c7273b82dc084d85e2344e0562f5ee4e414d59
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:38 2011 +0200
Fix typos in comments and code (occured -> occurred and related)
The code changed here is an unused data type name (evt_flush_occurred).
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/block.c b/block.c
index 8767d31..f403718 100644
--- a/block.c
+++ b/block.c
@@ -747,7 +747,7 @@ DeviceState *bdrv_get_attached(BlockDriverState *bs)
* Run consistency checks on an image
*
* Returns 0 if the check could be completed (it doesn't mean that the image is
- * free of errors) or -errno when an internal error occured. The results of the
+ * free of errors) or -errno when an internal error occurred. The results of the
* check are stored in res.
*/
int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res)
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 915d85a..d62dc1c 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1063,7 +1063,7 @@ fail:
* Checks an image for refcount consistency.
*
* Returns 0 if no errors are found, the number of errors in case the image is
- * detected as corrupted, and -errno when an internal error occured.
+ * detected as corrupted, and -errno when an internal error occurred.
*/
int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
{
diff --git a/cpu-all.h b/cpu-all.h
index 88126ea..78e3fc8 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -792,7 +792,7 @@ extern CPUState *cpu_single_env;
#define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
#define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
#define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */
-#define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occured. */
+#define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occurred. */
#define CPU_INTERRUPT_VIRQ 0x100 /* virtual interrupt pending. */
#define CPU_INTERRUPT_NMI 0x200 /* NMI pending. */
#define CPU_INTERRUPT_INIT 0x400 /* INIT pending. */
diff --git a/cpu-exec.c b/cpu-exec.c
index 2cdcdc5..1b20f7b 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -509,7 +509,7 @@ int cpu_exec(CPUState *env1)
jump normally, then does the exception return when the
CPU tries to execute code at the magic address.
This will cause the magic PC value to be pushed to
- the stack if an interrupt occured at the wrong time.
+ the stack if an interrupt occurred at the wrong time.
We avoid this by disabling interrupts when
pc contains a magic address. */
if (interrupt_request & CPU_INTERRUPT_HARD
diff --git a/hw/bt.h b/hw/bt.h
index 4a702ad..3797254 100644
--- a/hw/bt.h
+++ b/hw/bt.h
@@ -1441,7 +1441,7 @@ typedef struct {
#define EVT_FLUSH_OCCURRED 0x11
typedef struct {
uint16_t handle;
-} __attribute__ ((packed)) evt_flush_occured;
+} __attribute__ ((packed)) evt_flush_occurred;
#define EVT_FLUSH_OCCURRED_SIZE 2
#define EVT_ROLE_CHANGE 0x12
diff --git a/hw/pcie.c b/hw/pcie.c
index 9de6149..39607bf 100644
--- a/hw/pcie.c
+++ b/hw/pcie.c
@@ -176,7 +176,7 @@ static void hotplug_event_notify(PCIDevice *dev)
}
/*
- * A PCI Express Hot-Plug Event has occured, so update slot status register
+ * A PCI Express Hot-Plug Event has occurred, so update slot status register
* and notify OS of the event if necessary.
*
* 6.7.3 PCI Express Hot-Plug Events
diff --git a/hw/pcie.h b/hw/pcie.h
index bc909e2..a213fba 100644
--- a/hw/pcie.h
+++ b/hw/pcie.h
@@ -40,7 +40,7 @@ typedef enum {
*
* Not all the bits of slot control register match with the ones of
* slot status. Not some bits of slot status register is used to
- * show status, not to report event occurence.
+ * show status, not to report event occurrence.
* So such bits must be masked out when checking the software
* notification condition.
*/
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index 14bbc34..8fdafe6 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -367,7 +367,7 @@ static void pflash_write (pflash_t *pfl, target_phys_addr_t offset,
case 4:
switch (pfl->cmd) {
case 0xA0:
- /* Ignore writes while flash data write is occuring */
+ /* Ignore writes while flash data write is occurring */
/* As we suppose write is immediate, this should never happen */
return;
case 0x80:
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 3119137..59190f6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -1331,7 +1331,7 @@ static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
return 0;
}
-/* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
+/* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
(ie. an undefined instruction). */
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
{
@@ -2335,7 +2335,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
return 0;
}
-/* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
+/* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
(ie. an undefined instruction). */
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
{
@@ -2681,7 +2681,7 @@ static TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size)
return tmp;
}
-/* Disassemble a VFP instruction. Returns nonzero if an error occured
+/* Disassemble a VFP instruction. Returns nonzero if an error occurred
(ie. an undefined instruction). */
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
{
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 514b039..faa8c42 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -714,7 +714,7 @@ void HELPER(macsats)(CPUState *env, uint32_t acc)
if (env->macsr & MACSR_V) {
env->macsr |= MACSR_PAV0 << acc;
if (env->macsr & MACSR_OMC) {
- /* The result is saturated to 32 bits, despite overflow occuring
+ /* The result is saturated to 32 bits, despite overflow occurring
at 48 bits. Seems weird, but that's what the hardware docs
say. */
result = (result >> 63) ^ 0x7fffffff;
commit 1301f32205433bf82d32a458d090b87335cc8f99
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:37 2011 +0200
Fix typos in comments (neccessary -> necessary)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index e343894..1ba2d08 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -323,7 +323,7 @@ abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len);
abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len);
/* Functions for accessing guest memory. The tget and tput functions
- read/write single values, byteswapping as neccessary. The lock_user
+ read/write single values, byteswapping as necessary. The lock_user
gets a pointer to a contiguous area of guest memory, but does not perform
and byteswapping. lock_user may return either a pointer to the guest
memory, or a temporary buffer. */
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index f522f5e..237386c 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -379,7 +379,7 @@ abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len);
abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len);
/* Functions for accessing guest memory. The tget and tput functions
- read/write single values, byteswapping as neccessary. The lock_user
+ read/write single values, byteswapping as necessary. The lock_user
gets a pointer to a contiguous area of guest memory, but does not perform
and byteswapping. lock_user may return either a pointer to the guest
memory, or a temporary buffer. */
diff --git a/target-arm/translate.c b/target-arm/translate.c
index a1af436..3119137 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7348,7 +7348,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
} else if ((insn & 0x000003e0) == 0x00000060) {
tmp = load_reg(s, rm);
shift = (insn >> 10) & 3;
- /* ??? In many cases it's not neccessary to do a
+ /* ??? In many cases it's not necessary to do a
rotate, a shift is sufficient. */
if (shift != 0)
tcg_gen_rotri_i32(tmp, tmp, shift * 8);
@@ -8139,7 +8139,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
case 1: /* Sign/zero extend. */
tmp = load_reg(s, rm);
shift = (insn >> 4) & 3;
- /* ??? In many cases it's not neccessary to do a
+ /* ??? In many cases it's not necessary to do a
rotate, a shift is sufficient. */
if (shift != 0)
tcg_gen_rotri_i32(tmp, tmp, shift * 8);
commit 60b14d955dbdbe28d5203fd75e0b3c48ce83ce9c
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:36 2011 +0200
Fix typos in comments (instanciation -> instantiation)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 7f9ed17..68bdfaa 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -38,7 +38,7 @@
#endif
/*****************************************************************************/
-/* Generic PowerPC 4xx processor instanciation */
+/* Generic PowerPC 4xx processor instantiation */
CPUState *ppc4xx_init (const char *cpu_model,
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
uint32_t sysclk)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index e2a83c5..ed291c3 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -9049,7 +9049,7 @@ static const ppc_def_t ppc_defs[] = {
};
/*****************************************************************************/
-/* Generic CPU instanciation routine */
+/* Generic CPU instantiation routine */
static void init_ppc_proc (CPUPPCState *env, const ppc_def_t *def)
{
#if !defined(CONFIG_USER_ONLY)
commit ff2712ba8938afe204dcbb0b50036b36fe057c42
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:35 2011 +0200
Fix typos in comments (interupt -> interrupt)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/cpu-exec.c b/cpu-exec.c
index 395cd8c..2cdcdc5 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -569,7 +569,7 @@ int cpu_exec(CPUState *env1)
next_tb = 0;
}
#endif
- /* Don't use the cached interupt_request value,
+ /* Don't use the cached interrupt_request value,
do_interrupt may have updated the EXITTB flag. */
if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index a04355c..4e47574 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -154,7 +154,7 @@ mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
case MST_MSCRD:
s->mscrd = value;
break;
- case MST_INTMSKENA: /* Mask interupt */
+ case MST_INTMSKENA: /* Mask interrupt */
s->intmskena = (value & 0xFEEFF);
qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
break;
diff --git a/hw/pl031.c b/hw/pl031.c
index 8c2f9d0..017a313 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -161,7 +161,7 @@ static void pl031_write(void * opaque, target_phys_addr_t offset,
pl031_update(s);
break;
case RTC_ICR:
- /* The PL031 documentation (DDI0224B) states that the interupt is
+ /* The PL031 documentation (DDI0224B) states that the interrupt is
cleared when bit 0 of the written value is set. However the
arm926e documentation (DDI0287B) states that the interrupt is
cleared when any value is written. */
diff --git a/hw/pl061.c b/hw/pl061.c
index 2e181f8..372dfc2 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -98,7 +98,7 @@ static uint32_t pl061_read(void *opaque, target_phys_addr_t offset)
return s->isense;
case 0x408: /* Interrupt both edges */
return s->ibe;
- case 0x40c: /* Interupt event */
+ case 0x40c: /* Interrupt event */
return s->iev;
case 0x410: /* Interrupt mask */
return s->im;
@@ -156,7 +156,7 @@ static void pl061_write(void *opaque, target_phys_addr_t offset,
case 0x408: /* Interrupt both edges */
s->ibe = value;
break;
- case 0x40c: /* Interupt event */
+ case 0x40c: /* Interrupt event */
s->iev = value;
break;
case 0x410: /* Interrupt mask */
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 8d9b5b9..d55c522 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -38,7 +38,7 @@
((1 << CP0C2_M))
/* No config4, no DSP ASE, no large physaddr (PABITS),
- no external interrupt controller, no vectored interupts,
+ no external interrupt controller, no vectored interrupts,
no 1kb pages, no SmartMIPS ASE, no trace logic */
#define MIPS_CONFIG3 \
((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \
commit 0cf818c476ae00e498091b1bdb72aac8faa003b0
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:34 2011 +0200
Fix typos in comments (existance -> existence)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/libcacard/vscard_common.h b/libcacard/vscard_common.h
index bebd52d..609ae98 100644
--- a/libcacard/vscard_common.h
+++ b/libcacard/vscard_common.h
@@ -153,7 +153,7 @@ typedef struct VSCMsgCardRemove {
/*
* VSCMsgAPDU Client <-> Host
- * Main reason of existance. Transfer a single APDU in either direction.
+ * Main reason of existence. Transfer a single APDU in either direction.
*/
typedef struct VSCMsgAPDU {
uint8_t data[0];
commit 4b71051e831f60cb19da92570dad091210058c15
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:33 2011 +0200
Fix typos in comments (imediately -> immediately)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 2dc8d18..4c42fe9 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -721,7 +721,7 @@ static void do_phy_write(lan9118_state *s, int reg, uint32_t val)
break;
}
s->phy_control = val & 0x7980;
- /* Complete autonegotiation imediately. */
+ /* Complete autonegotiation immediately. */
if (val & 0x1000) {
s->phy_status |= 0x0020;
}
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index df2950f..2ef7175 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -126,7 +126,7 @@ static void do_dma_tx(SyborgSerialState *s, uint32_t count)
s->dma_tx_ptr += count;
}
/* QEMU char backends do not have a nonblocking mode, so we transmit all
- the data imediately and the interrupt status will be unchanged. */
+ the data immediately and the interrupt status will be unchanged. */
}
/* Initiate RX DMA, and transfer data from the FIFO. */
commit 0c58751c37b0365c21153c47e90f096e53542a6b
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:32 2011 +0200
Fix typo in comment (dieing -> dying)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/linux-user/signal.c b/linux-user/signal.c
index ce033e9..6fe086b 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -391,7 +391,7 @@ static void QEMU_NORETURN force_sig(int target_sig)
target_sig, strsignal(host_sig), "core dumped" );
}
- /* The proper exit code for dieing from an uncaught signal is
+ /* The proper exit code for dying from an uncaught signal is
* -<signal>. The kernel doesn't allow exit() or _exit() to pass
* a negative value. To get the proper exit code we need to
* actually die from an uncaught signal. Here the default signal
commit fc27eefe9ba6cbbe62d9b1f5b7b3513ee0bebc3e
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:31 2011 +0200
Fix typo in comment (consistant -> consistent)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index baada52..f3db657 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -971,7 +971,7 @@ find_blank(const char *str)
/*
* We really want to use some existing argument parsing library here. That
- * would give us a consistant look */
+ * would give us a consistent look */
static VCardEmulOptions options;
#define READER_STEP 4
commit 5b46d07d07d6188126ed9edf9e26eb20658fc48d
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:30 2011 +0200
Fix typo in comment (embeded -> embedded)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 04b1259..e438b17 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -225,7 +225,7 @@ enum {
/* 970FX specific exceptions */
POWERPC_EXCP_SOFTP = 88, /* Soft patch exception */
POWERPC_EXCP_MAINT = 89, /* Maintenance exception */
- /* Freescale embeded cores specific exceptions */
+ /* Freescale embedded cores specific exceptions */
POWERPC_EXCP_MEXTBR = 90, /* Maskable external breakpoint */
POWERPC_EXCP_NMEXTBR = 91, /* Non maskable external breakpoint */
POWERPC_EXCP_ITLBE = 92, /* Instruction TLB error */
commit a7f22f065e47d5abc2b2ed46663dd4792a4e5311
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:29 2011 +0200
Fix typo in comment (auxilliary -> auxiliary)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/hw/pci_regs.h b/hw/pci_regs.h
index dd0bed4..5a5ab89 100644
--- a/hw/pci_regs.h
+++ b/hw/pci_regs.h
@@ -223,7 +223,7 @@
#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */
#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */
#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */
-#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */
+#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxiliary power support mask */
#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */
#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */
#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */
commit 4e9a0b5bf82e6655e228567e67cffe482e190f05
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:28 2011 +0200
Fix typo in comment (colum -> column)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/hw/ssd0303.c b/hw/ssd0303.c
index 108c068..b39e259 100644
--- a/hw/ssd0303.c
+++ b/hw/ssd0303.c
@@ -93,7 +93,7 @@ static int ssd0303_send(i2c_slave *i2c, uint8_t data)
DPRINTF("cmd 0x%02x\n", data);
s->mode = SSD0303_IDLE;
switch (data) {
- case 0x00 ... 0x0f: /* Set lower colum address. */
+ case 0x00 ... 0x0f: /* Set lower column address. */
s->col = (s->col & 0xf0) | (data & 0xf);
break;
case 0x10 ... 0x20: /* Set higher column address. */
commit 64c7b9d8e07936383db181876b59c597d6a1ff69
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:27 2011 +0200
Fix typos in comments (accessable -> accessible, priveleged -> privileged)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/hw/sh7750_regs.h b/hw/sh7750_regs.h
index 5a23a2c..6ec13ab 100644
--- a/hw/sh7750_regs.h
+++ b/hw/sh7750_regs.h
@@ -23,9 +23,9 @@
* All register has 2 addresses: in 0xff000000 - 0xffffffff (P4 address) and
* in 0x1f000000 - 0x1fffffff (area 7 address)
*/
-#define SH7750_P4_BASE 0xff000000 /* Accessable only in
- priveleged mode */
-#define SH7750_A7_BASE 0x1f000000 /* Accessable only using TLB */
+#define SH7750_P4_BASE 0xff000000 /* Accessible only in
+ privileged mode */
+#define SH7750_A7_BASE 0x1f000000 /* Accessible only using TLB */
#define SH7750_P4_REG32(ofs) (SH7750_P4_BASE + (ofs))
#define SH7750_A7_REG32(ofs) (SH7750_A7_BASE + (ofs))
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index d908775..4a9032b 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -101,7 +101,7 @@ typedef struct CPUCRISState {
/* P0 - P15 are referred to as special registers in the docs. */
uint32_t pregs[16];
- /* Pseudo register for the PC. Not directly accessable on CRIS. */
+ /* Pseudo register for the PC. Not directly accessible on CRIS. */
uint32_t pc;
/* Pseudo register for the kernel stack. */
diff --git a/tests/test-mmap.c b/tests/test-mmap.c
index c578e25..c67174a 100644
--- a/tests/test-mmap.c
+++ b/tests/test-mmap.c
@@ -322,7 +322,7 @@ void check_file_unfixed_eof_mmaps(void)
fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
== ((test_fsize - sizeof *p1) / sizeof *p1));
- /* Verify that the end of page is accessable and zeroed. */
+ /* Verify that the end of page is accessible and zeroed. */
cp = (void *) p1;
fail_unless (cp[pagesize - 4] == 0);
munmap (p1, pagesize);
@@ -365,7 +365,7 @@ void check_file_fixed_eof_mmaps(void)
fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
== ((test_fsize - sizeof *p1) / sizeof *p1));
- /* Verify that the end of page is accessable and zeroed. */
+ /* Verify that the end of page is accessible and zeroed. */
cp = (void *)p1;
fail_unless (cp[pagesize - 4] == 0);
munmap (p1, pagesize);
commit 5225d66921ec571eef9d828a60933579b3b7f5f0
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:26 2011 +0200
Fix typos in comments (accross -> across)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/darwin-user/syscall.c b/darwin-user/syscall.c
index 060acc8..f3cc1f8 100644
--- a/darwin-user/syscall.c
+++ b/darwin-user/syscall.c
@@ -977,7 +977,7 @@ long do_unix_syscall_indirect(void *cpu_env, int num)
#elif TARGET_PPC
{
int i;
- /* XXX: not really needed those regs are volatile accross calls */
+ /* XXX: not really needed those regs are volatile across calls */
uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
for(i = 11; i > 3; i--)
*regs[i] = *regs[i-1];
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index 5230b52..a623c7b 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -117,7 +117,7 @@ void do_interrupt(CPUState *env)
{
uint32_t t;
- /* IMM flag cannot propagate accross a branch and into the dslot. */
+ /* IMM flag cannot propagate across a branch and into the dslot. */
assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG)));
assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)));
/* assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions. */
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 3fab8d6..cecef63 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -252,9 +252,9 @@ typedef struct TCGTemp {
unsigned int fixed_reg:1;
unsigned int mem_coherent:1;
unsigned int mem_allocated:1;
- unsigned int temp_local:1; /* If true, the temp is saved accross
+ unsigned int temp_local:1; /* If true, the temp is saved across
basic blocks. Otherwise, it is not
- preserved accross basic blocks. */
+ preserved across basic blocks. */
unsigned int temp_allocated:1; /* never used for code gen */
/* index of next free temp of same base type, -1 if end */
int next_free_temp;
commit cbae0863d60a3708cb2c0647b35ea34b40313246
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Apr 28 17:20:25 2011 +0200
Fix typos in comments (dependancy -> dependency)
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/Changelog b/Changelog
index 152feaa..1c41e14 100644
--- a/Changelog
+++ b/Changelog
@@ -525,7 +525,7 @@ version 0.1.5:
- ppc64 support + personality() patch (Rusty Russell)
- first Alpha CPU patches (Falk Hueffner)
- - removed bfd.h dependancy
+ - removed bfd.h dependency
- fixed shrd, shld, idivl and divl on PowerPC.
- fixed buggy glibc PowerPC rint() function (test-i386 passes now on PowerPC).
diff --git a/Makefile.objs b/Makefile.objs
index 9d8851e..d82c60d 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -335,7 +335,7 @@ trace-dtrace.h: trace-dtrace.dtrace
$(call quiet-command,dtrace -o $@ -h -s $<, " GEN trace-dtrace.h")
# Normal practice is to name DTrace probe file with a '.d' extension
-# but that gets picked up by QEMU's Makefile as an external dependancy
+# but that gets picked up by QEMU's Makefile as an external dependency
# rule file. So we use '.dtrace' instead
trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak
commit c962247883ffd957dd7f3bccb519803e2775ced2
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Tue Oct 5 16:40:22 2010 +0100
xen: Add Xen hypercall for sleep state in the cmos_s3 callback.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 62cdf71..9a22a8a 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -179,7 +179,11 @@ static void pc_init1(ram_addr_t ram_size,
if (pci_enabled && acpi_enabled) {
i2c_bus *smbus;
- cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
+ if (!xen_enabled()) {
+ cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
+ } else {
+ cmos_s3 = qemu_allocate_irqs(xen_cmos_set_s3_resume, rtc_state, 1);
+ }
smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
/* TODO: Populate SPD eeprom data. */
smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
diff --git a/hw/xen.h b/hw/xen.h
index 6245b38..d435ca0 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -43,6 +43,7 @@ static inline int xen_mapcache_enabled(void)
int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
void xen_piix3_set_irq(void *opaque, int irq_num, int level);
void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len);
+void xen_cmos_set_s3_resume(void *opaque, int irq, int level);
qemu_irq *xen_interrupt_controller_init(void);
diff --git a/xen-all.c b/xen-all.c
index 19c2fe1..0eac202 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -9,6 +9,7 @@
#include <sys/mman.h>
#include "hw/pci.h"
+#include "hw/pc.h"
#include "hw/xen_common.h"
#include "hw/xen_backend.h"
@@ -99,6 +100,14 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
}
}
+void xen_cmos_set_s3_resume(void *opaque, int irq, int level)
+{
+ pc_cmos_set_s3_resume(opaque, irq, level);
+ if (level) {
+ xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
+ }
+}
+
/* Xen Interrupt Controller */
static void xen_set_irq(void *opaque, int irq, int level)
diff --git a/xen-stub.c b/xen-stub.c
index 8d2fa54..a4f35a1 100644
--- a/xen-stub.c
+++ b/xen-stub.c
@@ -22,6 +22,10 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
{
}
+void xen_cmos_set_s3_resume(void *opaque, int irq, int level)
+{
+}
+
void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
{
}
commit 29321335e0407f5f0c3aa415d98566279c232ad8
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Mon Sep 6 20:07:33 2010 +0100
xen: Set running state in xenstore.
This tells to the xen management tool that the machine can begin run.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/xen-all.c b/xen-all.c
index e849a38..19c2fe1 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -64,6 +64,8 @@ typedef struct XenIOState {
/* which vcpu we are serving */
int send_vcpu;
+ struct xs_handle *xenstore;
+
Notifier exit;
} XenIOState;
@@ -450,6 +452,17 @@ static void cpu_handle_ioreq(void *opaque)
}
}
+static void xenstore_record_dm_state(XenIOState *s, const char *state)
+{
+ char path[50];
+
+ snprintf(path, sizeof (path), "/local/domain/0/device-model/%u/state", xen_domid);
+ if (!xs_write(s->xenstore, XBT_NULL, path, state, strlen(state))) {
+ fprintf(stderr, "error recording dm state\n");
+ exit(1);
+ }
+}
+
static void xen_main_loop_prepare(XenIOState *state)
{
int evtchn_fd = -1;
@@ -465,6 +478,9 @@ static void xen_main_loop_prepare(XenIOState *state)
if (evtchn_fd != -1) {
qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
}
+
+ /* record state running */
+ xenstore_record_dm_state(state, "running");
}
@@ -483,6 +499,7 @@ static void xen_exit_notifier(Notifier *n)
XenIOState *state = container_of(n, XenIOState, exit);
xc_evtchn_close(state->xce_handle);
+ xs_daemon_close(state->xenstore);
}
int xen_init(void)
@@ -510,6 +527,12 @@ int xen_hvm_init(void)
return -errno;
}
+ state->xenstore = xs_daemon_open();
+ if (state->xenstore == NULL) {
+ perror("xen: xenstore open");
+ return -errno;
+ }
+
state->exit.notify = xen_exit_notifier;
qemu_add_exit_notifier(&state->exit);
commit 9ce94e7c8a997472d79879e687d5ceaa14eca944
Author: Arun Sharma <arun.sharma at intel.com>
Date: Mon Sep 6 20:07:14 2010 +0100
xen: Initialize event channels and io rings
Open and bind event channels; map ioreq and buffered ioreq rings.
Signed-off-by: Arun Sharma <arun.sharma at intel.com>
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/xen_common.h b/hw/xen_common.h
index dd3e896..a1958a0 100644
--- a/hw/xen_common.h
+++ b/hw/xen_common.h
@@ -107,4 +107,6 @@ static inline int xc_fd(xc_interface *xen_xc)
}
#endif
+void destroy_hvm_domain(void);
+
#endif /* QEMU_HW_XEN_COMMON_H */
diff --git a/xen-all.c b/xen-all.c
index cb01ab9..e849a38 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -6,6 +6,8 @@
*
*/
+#include <sys/mman.h>
+
#include "hw/pci.h"
#include "hw/xen_common.h"
#include "hw/xen_backend.h"
@@ -13,6 +15,58 @@
#include "xen-mapcache.h"
#include "trace.h"
+#include <xen/hvm/ioreq.h>
+#include <xen/hvm/params.h>
+
+//#define DEBUG_XEN
+
+#ifdef DEBUG_XEN
+#define DPRINTF(fmt, ...) \
+ do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+ do { } while (0)
+#endif
+
+/* Compatibility with older version */
+#if __XEN_LATEST_INTERFACE_VERSION__ < 0x0003020a
+static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
+{
+ return shared_page->vcpu_iodata[i].vp_eport;
+}
+static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
+{
+ return &shared_page->vcpu_iodata[vcpu].vp_ioreq;
+}
+# define FMT_ioreq_size PRIx64
+#else
+static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
+{
+ return shared_page->vcpu_ioreq[i].vp_eport;
+}
+static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
+{
+ return &shared_page->vcpu_ioreq[vcpu];
+}
+# define FMT_ioreq_size "u"
+#endif
+
+#define BUFFER_IO_MAX_DELAY 100
+
+typedef struct XenIOState {
+ shared_iopage_t *shared_page;
+ buffered_iopage_t *buffered_io_page;
+ QEMUTimer *buffered_io_timer;
+ /* the evtchn port for polling the notification, */
+ evtchn_port_t *ioreq_local_port;
+ /* the evtchn fd for polling */
+ XenEvtchn xce_handle;
+ /* which vcpu we are serving */
+ int send_vcpu;
+
+ Notifier exit;
+} XenIOState;
+
/* Xen specific function for piix pci */
int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
@@ -133,8 +187,304 @@ void xen_vcpu_init(void)
}
}
+/* get the ioreq packets from share mem */
+static ioreq_t *cpu_get_ioreq_from_shared_memory(XenIOState *state, int vcpu)
+{
+ ioreq_t *req = xen_vcpu_ioreq(state->shared_page, vcpu);
+
+ if (req->state != STATE_IOREQ_READY) {
+ DPRINTF("I/O request not ready: "
+ "%x, ptr: %x, port: %"PRIx64", "
+ "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
+ req->state, req->data_is_ptr, req->addr,
+ req->data, req->count, req->size);
+ return NULL;
+ }
+
+ xen_rmb(); /* see IOREQ_READY /then/ read contents of ioreq */
+
+ req->state = STATE_IOREQ_INPROCESS;
+ return req;
+}
+
+/* use poll to get the port notification */
+/* ioreq_vec--out,the */
+/* retval--the number of ioreq packet */
+static ioreq_t *cpu_get_ioreq(XenIOState *state)
+{
+ int i;
+ evtchn_port_t port;
+
+ port = xc_evtchn_pending(state->xce_handle);
+ if (port != -1) {
+ for (i = 0; i < smp_cpus; i++) {
+ if (state->ioreq_local_port[i] == port) {
+ break;
+ }
+ }
+
+ if (i == smp_cpus) {
+ hw_error("Fatal error while trying to get io event!\n");
+ }
+
+ /* unmask the wanted port again */
+ xc_evtchn_unmask(state->xce_handle, port);
+
+ /* get the io packet from shared memory */
+ state->send_vcpu = i;
+ return cpu_get_ioreq_from_shared_memory(state, i);
+ }
+
+ /* read error or read nothing */
+ return NULL;
+}
+
+static uint32_t do_inp(pio_addr_t addr, unsigned long size)
+{
+ switch (size) {
+ case 1:
+ return cpu_inb(addr);
+ case 2:
+ return cpu_inw(addr);
+ case 4:
+ return cpu_inl(addr);
+ default:
+ hw_error("inp: bad size: %04"FMT_pioaddr" %lx", addr, size);
+ }
+}
+
+static void do_outp(pio_addr_t addr,
+ unsigned long size, uint32_t val)
+{
+ switch (size) {
+ case 1:
+ return cpu_outb(addr, val);
+ case 2:
+ return cpu_outw(addr, val);
+ case 4:
+ return cpu_outl(addr, val);
+ default:
+ hw_error("outp: bad size: %04"FMT_pioaddr" %lx", addr, size);
+ }
+}
+
+static void cpu_ioreq_pio(ioreq_t *req)
+{
+ int i, sign;
+
+ sign = req->df ? -1 : 1;
+
+ if (req->dir == IOREQ_READ) {
+ if (!req->data_is_ptr) {
+ req->data = do_inp(req->addr, req->size);
+ } else {
+ uint32_t tmp;
+
+ for (i = 0; i < req->count; i++) {
+ tmp = do_inp(req->addr, req->size);
+ cpu_physical_memory_write(req->data + (sign * i * req->size),
+ (uint8_t *) &tmp, req->size);
+ }
+ }
+ } else if (req->dir == IOREQ_WRITE) {
+ if (!req->data_is_ptr) {
+ do_outp(req->addr, req->size, req->data);
+ } else {
+ for (i = 0; i < req->count; i++) {
+ uint32_t tmp = 0;
+
+ cpu_physical_memory_read(req->data + (sign * i * req->size),
+ (uint8_t*) &tmp, req->size);
+ do_outp(req->addr, req->size, tmp);
+ }
+ }
+ }
+}
+
+static void cpu_ioreq_move(ioreq_t *req)
+{
+ int i, sign;
+
+ sign = req->df ? -1 : 1;
+
+ if (!req->data_is_ptr) {
+ if (req->dir == IOREQ_READ) {
+ for (i = 0; i < req->count; i++) {
+ cpu_physical_memory_read(req->addr + (sign * i * req->size),
+ (uint8_t *) &req->data, req->size);
+ }
+ } else if (req->dir == IOREQ_WRITE) {
+ for (i = 0; i < req->count; i++) {
+ cpu_physical_memory_write(req->addr + (sign * i * req->size),
+ (uint8_t *) &req->data, req->size);
+ }
+ }
+ } else {
+ target_ulong tmp;
+
+ if (req->dir == IOREQ_READ) {
+ for (i = 0; i < req->count; i++) {
+ cpu_physical_memory_read(req->addr + (sign * i * req->size),
+ (uint8_t*) &tmp, req->size);
+ cpu_physical_memory_write(req->data + (sign * i * req->size),
+ (uint8_t*) &tmp, req->size);
+ }
+ } else if (req->dir == IOREQ_WRITE) {
+ for (i = 0; i < req->count; i++) {
+ cpu_physical_memory_read(req->data + (sign * i * req->size),
+ (uint8_t*) &tmp, req->size);
+ cpu_physical_memory_write(req->addr + (sign * i * req->size),
+ (uint8_t*) &tmp, req->size);
+ }
+ }
+ }
+}
+
+static void handle_ioreq(ioreq_t *req)
+{
+ if (!req->data_is_ptr && (req->dir == IOREQ_WRITE) &&
+ (req->size < sizeof (target_ulong))) {
+ req->data &= ((target_ulong) 1 << (8 * req->size)) - 1;
+ }
+
+ switch (req->type) {
+ case IOREQ_TYPE_PIO:
+ cpu_ioreq_pio(req);
+ break;
+ case IOREQ_TYPE_COPY:
+ cpu_ioreq_move(req);
+ break;
+ case IOREQ_TYPE_TIMEOFFSET:
+ break;
+ case IOREQ_TYPE_INVALIDATE:
+ qemu_invalidate_map_cache();
+ break;
+ default:
+ hw_error("Invalid ioreq type 0x%x\n", req->type);
+ }
+}
+
+static void handle_buffered_iopage(XenIOState *state)
+{
+ buf_ioreq_t *buf_req = NULL;
+ ioreq_t req;
+ int qw;
+
+ if (!state->buffered_io_page) {
+ return;
+ }
+
+ while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) {
+ buf_req = &state->buffered_io_page->buf_ioreq[
+ state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];
+ req.size = 1UL << buf_req->size;
+ req.count = 1;
+ req.addr = buf_req->addr;
+ req.data = buf_req->data;
+ req.state = STATE_IOREQ_READY;
+ req.dir = buf_req->dir;
+ req.df = 1;
+ req.type = buf_req->type;
+ req.data_is_ptr = 0;
+ qw = (req.size == 8);
+ if (qw) {
+ buf_req = &state->buffered_io_page->buf_ioreq[
+ (state->buffered_io_page->read_pointer + 1) % IOREQ_BUFFER_SLOT_NUM];
+ req.data |= ((uint64_t)buf_req->data) << 32;
+ }
+
+ handle_ioreq(&req);
+
+ xen_mb();
+ state->buffered_io_page->read_pointer += qw ? 2 : 1;
+ }
+}
+
+static void handle_buffered_io(void *opaque)
+{
+ XenIOState *state = opaque;
+
+ handle_buffered_iopage(state);
+ qemu_mod_timer(state->buffered_io_timer,
+ BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
+}
+
+static void cpu_handle_ioreq(void *opaque)
+{
+ XenIOState *state = opaque;
+ ioreq_t *req = cpu_get_ioreq(state);
+
+ handle_buffered_iopage(state);
+ if (req) {
+ handle_ioreq(req);
+
+ if (req->state != STATE_IOREQ_INPROCESS) {
+ fprintf(stderr, "Badness in I/O request ... not in service?!: "
+ "%x, ptr: %x, port: %"PRIx64", "
+ "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
+ req->state, req->data_is_ptr, req->addr,
+ req->data, req->count, req->size);
+ destroy_hvm_domain();
+ return;
+ }
+
+ xen_wmb(); /* Update ioreq contents /then/ update state. */
+
+ /*
+ * We do this before we send the response so that the tools
+ * have the opportunity to pick up on the reset before the
+ * guest resumes and does a hlt with interrupts disabled which
+ * causes Xen to powerdown the domain.
+ */
+ if (vm_running) {
+ if (qemu_shutdown_requested_get()) {
+ destroy_hvm_domain();
+ }
+ if (qemu_reset_requested_get()) {
+ qemu_system_reset();
+ }
+ }
+
+ req->state = STATE_IORESP_READY;
+ xc_evtchn_notify(state->xce_handle, state->ioreq_local_port[state->send_vcpu]);
+ }
+}
+
+static void xen_main_loop_prepare(XenIOState *state)
+{
+ int evtchn_fd = -1;
+
+ if (state->xce_handle != XC_HANDLER_INITIAL_VALUE) {
+ evtchn_fd = xc_evtchn_fd(state->xce_handle);
+ }
+
+ state->buffered_io_timer = qemu_new_timer_ms(rt_clock, handle_buffered_io,
+ state);
+ qemu_mod_timer(state->buffered_io_timer, qemu_get_clock_ms(rt_clock));
+
+ if (evtchn_fd != -1) {
+ qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
+ }
+}
+
+
/* Initialise Xen */
+static void xen_vm_change_state_handler(void *opaque, int running, int reason)
+{
+ XenIOState *state = opaque;
+ if (running) {
+ xen_main_loop_prepare(state);
+ }
+}
+
+static void xen_exit_notifier(Notifier *n)
+{
+ XenIOState *state = container_of(n, XenIOState, exit);
+
+ xc_evtchn_close(state->xce_handle);
+}
+
int xen_init(void)
{
xen_xc = xen_xc_interface_open(0, 0, 0);
@@ -148,9 +498,76 @@ int xen_init(void)
int xen_hvm_init(void)
{
+ int i, rc;
+ unsigned long ioreq_pfn;
+ XenIOState *state;
+
+ state = qemu_mallocz(sizeof (XenIOState));
+
+ state->xce_handle = xen_xc_evtchn_open(NULL, 0);
+ if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
+ perror("xen: event channel open");
+ return -errno;
+ }
+
+ state->exit.notify = xen_exit_notifier;
+ qemu_add_exit_notifier(&state->exit);
+
+ xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
+ DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
+ state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
+ PROT_READ|PROT_WRITE, ioreq_pfn);
+ if (state->shared_page == NULL) {
+ hw_error("map shared IO page returned error %d handle=" XC_INTERFACE_FMT,
+ errno, xen_xc);
+ }
+
+ xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
+ DPRINTF("buffered io page at pfn %lx\n", ioreq_pfn);
+ state->buffered_io_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
+ PROT_READ|PROT_WRITE, ioreq_pfn);
+ if (state->buffered_io_page == NULL) {
+ hw_error("map buffered IO page returned error %d", errno);
+ }
+
+ state->ioreq_local_port = qemu_mallocz(smp_cpus * sizeof (evtchn_port_t));
+
+ /* FIXME: how about if we overflow the page here? */
+ for (i = 0; i < smp_cpus; i++) {
+ rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
+ xen_vcpu_eport(state->shared_page, i));
+ if (rc == -1) {
+ fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
+ return -1;
+ }
+ state->ioreq_local_port[i] = rc;
+ }
+
/* Init RAM management */
qemu_map_cache_init();
xen_ram_init(ram_size);
+ qemu_add_vm_change_state_handler(xen_vm_change_state_handler, state);
+
return 0;
}
+
+void destroy_hvm_domain(void)
+{
+ XenXC xc_handle;
+ int sts;
+
+ xc_handle = xen_xc_interface_open(0, 0, 0);
+ if (xc_handle == XC_HANDLER_INITIAL_VALUE) {
+ fprintf(stderr, "Cannot acquire xenctrl handle\n");
+ } else {
+ sts = xc_domain_shutdown(xc_handle, xen_domid, SHUTDOWN_poweroff);
+ if (sts != 0) {
+ fprintf(stderr, "? xc_domain_shutdown failed to issue poweroff, "
+ "sts %d, %s\n", sts, strerror(errno));
+ } else {
+ fprintf(stderr, "Issued domain %d poweroff\n", xen_domid);
+ }
+ xc_interface_close(xc_handle);
+ }
+}
commit 1291eb35404b077ec96e5c06c7a70935597fe7c6
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Thu Jul 22 15:52:48 2010 +0100
vl.c: Introduce getter for shutdown_requested and reset_requested.
Introduce two functions qemu_shutdown_requested_get and
qemu_reset_requested_get to get the value of shutdown/reset_requested
without reset it.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/sysemu.h b/sysemu.h
index b0296a0..7e70daa 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -42,6 +42,8 @@ void qemu_system_shutdown_request(void);
void qemu_system_powerdown_request(void);
void qemu_system_debug_request(void);
void qemu_system_vmstop_request(int reason);
+int qemu_shutdown_requested_get(void);
+int qemu_reset_requested_get(void);
int qemu_shutdown_requested(void);
int qemu_reset_requested(void);
int qemu_powerdown_requested(void);
diff --git a/vl.c b/vl.c
index 3ed6855..bffba69 100644
--- a/vl.c
+++ b/vl.c
@@ -1161,6 +1161,16 @@ static int powerdown_requested;
static int debug_requested;
static int vmstop_requested;
+int qemu_shutdown_requested_get(void)
+{
+ return shutdown_requested;
+}
+
+int qemu_reset_requested_get(void)
+{
+ return reset_requested;
+}
+
int qemu_shutdown_requested(void)
{
int r = shutdown_requested;
commit 8c12f1912afed98715d995cb7c72c8203aaced9d
Author: John Baboval <john.baboval at virtualcomputer.com>
Date: Tue Mar 22 14:52:09 2011 +0000
pci: Use of qemu_put_ram_ptr in pci_add_option_rom.
Prevent a deadlock caused by leaving a map cache bucket locked by the
preceding qemu_get_ram_ptr() call.
Signed-off-By: John Baboval <john.baboval at virtualcomputer.com>
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/pci.c b/hw/pci.c
index 0875654..631d77c 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1922,6 +1922,8 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
pci_patch_ids(pdev, ptr, size);
}
+ qemu_put_ram_ptr(ptr);
+
pci_register_bar(pdev, PCI_ROM_SLOT, size,
0, pci_map_option_rom);
commit 64b3cfdb73fd08220ef848f71a2d0061e97ed7d8
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Thu Oct 21 12:47:08 2010 +0100
configure: Always use 64bits target physical addresses with xen enabled.
With MapCache, we can handle a 64b target, even with a 32b host/qemu.
So, we need to have target_phys_addr_t to 64bits.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/configure b/configure
index 6fc2bdd..3ba6401 100755
--- a/configure
+++ b/configure
@@ -3298,6 +3298,7 @@ echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >> $config_target_mak
case "$target_arch2" in
i386|x86_64)
if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
+ target_phys_bits=64
echo "CONFIG_XEN=y" >> $config_target_mak
if test "$cpu" = "i386" -o "$cpu" = "x86_64"; then
echo "CONFIG_XEN_MAPCACHE=y" >> $config_target_mak
commit 050a0ddf39cf5555ecf9b22a918b2a2b00bdbe34
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Thu Sep 16 13:57:49 2010 +0100
Introduce qemu_put_ram_ptr
This function allows to unlock a ram_ptr give by qemu_get_ram_ptr. After
a call to qemu_put_ram_ptr, the pointer may be unmap from QEMU when
used with Xen.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/cpu-common.h b/cpu-common.h
index 6410ccc..151c32c 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -67,6 +67,7 @@ void *qemu_get_ram_ptr(ram_addr_t addr);
/* Same but slower, to use for migration, where the order of
* RAMBlocks must not change. */
void *qemu_safe_ram_ptr(ram_addr_t addr);
+void qemu_put_ram_ptr(void *addr);
/* This should not be used by devices. */
int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
diff --git a/exec.c b/exec.c
index 8c81cff..a6df2d6 100644
--- a/exec.c
+++ b/exec.c
@@ -3110,6 +3110,27 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
return NULL;
}
+void qemu_put_ram_ptr(void *addr)
+{
+ trace_qemu_put_ram_ptr(addr);
+
+ if (xen_mapcache_enabled()) {
+ RAMBlock *block;
+
+ QLIST_FOREACH(block, &ram_list.blocks, next) {
+ if (addr == block->host) {
+ break;
+ }
+ }
+ if (block && block->host) {
+ xen_unmap_block(block->host, block->length);
+ block->host = NULL;
+ } else {
+ qemu_map_cache_unlock(addr);
+ }
+ }
+}
+
int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
{
RAMBlock *block;
@@ -3825,6 +3846,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
cpu_physical_memory_set_dirty_flags(
addr1, (0xff & ~CODE_DIRTY_FLAG));
}
+ qemu_put_ram_ptr(ptr);
}
} else {
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
@@ -3852,9 +3874,9 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
}
} else {
/* RAM case */
- ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
- (addr & ~TARGET_PAGE_MASK);
- memcpy(buf, ptr, l);
+ ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
+ memcpy(buf, ptr + (addr & ~TARGET_PAGE_MASK), l);
+ qemu_put_ram_ptr(ptr);
}
}
len -= l;
@@ -3895,6 +3917,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
/* ROM/RAM case */
ptr = qemu_get_ram_ptr(addr1);
memcpy(ptr, buf, l);
+ qemu_put_ram_ptr(ptr);
}
len -= l;
buf += l;
@@ -4036,6 +4059,15 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
access_len -= l;
}
}
+ if (xen_mapcache_enabled()) {
+ uint8_t *buffer1 = buffer;
+ uint8_t *end_buffer = buffer + len;
+
+ while (buffer1 < end_buffer) {
+ qemu_put_ram_ptr(buffer1);
+ buffer1 += TARGET_PAGE_SIZE;
+ }
+ }
return;
}
if (is_write) {
diff --git a/trace-events b/trace-events
index d703347..a00b63c 100644
--- a/trace-events
+++ b/trace-events
@@ -371,3 +371,6 @@ disable qemu_remap_bucket(uint64_t index) "index %#"PRIx64""
disable qemu_map_cache_return(void* ptr) "%p"
disable xen_map_block(uint64_t phys_addr, uint64_t size) "%#"PRIx64", size %#"PRIx64""
disable xen_unmap_block(void* addr, unsigned long size) "%p, size %#lx"
+
+# exec.c
+disable qemu_put_ram_ptr(void* addr) "%p"
diff --git a/xen-mapcache.c b/xen-mapcache.c
index 2ca18ce..349cc62 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -196,6 +196,39 @@ uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, u
return mapcache->last_address_vaddr + address_offset;
}
+void qemu_map_cache_unlock(void *buffer)
+{
+ MapCacheEntry *entry = NULL, *pentry = NULL;
+ MapCacheRev *reventry;
+ target_phys_addr_t paddr_index;
+ int found = 0;
+
+ QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
+ if (reventry->vaddr_req == buffer) {
+ paddr_index = reventry->paddr_index;
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ return;
+ }
+ QTAILQ_REMOVE(&mapcache->locked_entries, reventry, next);
+ qemu_free(reventry);
+
+ entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
+ while (entry && entry->paddr_index != paddr_index) {
+ pentry = entry;
+ entry = entry->next;
+ }
+ if (!entry) {
+ return;
+ }
+ if (entry->lock > 0) {
+ entry->lock--;
+ }
+}
+
ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
{
MapCacheRev *reventry;
commit ea6c5f8ffe6de12e04e63acbb9937683b30216e2
Author: John Baboval <john.baboval at virtualcomputer.com>
Date: Tue Mar 22 14:50:28 2011 +0000
xen: Adds a cap to the number of map cache entries.
Adds a cap to the number of map cache entries. This prevents the map
cache from overwhelming system memory.
I also removed the bitmap macros and #included bitmap.h instead.
Signed-off-By: John Baboval <john.baboval at virtualcomputer.com>
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/xen-mapcache.c b/xen-mapcache.c
index a539358..2ca18ce 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -12,6 +12,7 @@
#include "hw/xen_backend.h"
#include "blockdev.h"
+#include "bitmap.h"
#include <xen/hvm/params.h>
#include <sys/mman.h>
@@ -32,15 +33,13 @@
#if defined(__i386__)
# define MCACHE_BUCKET_SHIFT 16
+# define MCACHE_MAX_SIZE (1UL<<31) /* 2GB Cap */
#elif defined(__x86_64__)
# define MCACHE_BUCKET_SHIFT 20
+# define MCACHE_MAX_SIZE (1UL<<35) /* 32GB Cap */
#endif
#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT)
-#define BITS_PER_LONG (sizeof(long) * 8)
-#define BITS_TO_LONGS(bits) (((bits) + BITS_PER_LONG - 1) / BITS_PER_LONG)
-#define DECLARE_BITMAP(name, bits) unsigned long name[BITS_TO_LONGS(bits)]
-
typedef struct MapCacheEntry {
target_phys_addr_t paddr_index;
uint8_t *vaddr_base;
@@ -69,11 +68,6 @@ typedef struct MapCache {
static MapCache *mapcache;
-static inline int test_bit(unsigned int bit, const unsigned long *map)
-{
- return !!((map)[(bit) / BITS_PER_LONG] & (1UL << ((bit) % BITS_PER_LONG)));
-}
-
void qemu_map_cache_init(void)
{
unsigned long size;
@@ -85,9 +79,14 @@ void qemu_map_cache_init(void)
mapcache->last_address_index = -1;
getrlimit(RLIMIT_AS, &rlimit_as);
- rlimit_as.rlim_cur = rlimit_as.rlim_max;
+ if (rlimit_as.rlim_max < MCACHE_MAX_SIZE) {
+ rlimit_as.rlim_cur = rlimit_as.rlim_max;
+ } else {
+ rlimit_as.rlim_cur = MCACHE_MAX_SIZE;
+ }
+
setrlimit(RLIMIT_AS, &rlimit_as);
- mapcache->max_mcache_size = rlimit_as.rlim_max;
+ mapcache->max_mcache_size = rlimit_as.rlim_cur;
mapcache->nr_buckets =
(((mapcache->max_mcache_size >> XC_PAGE_SHIFT) +
@@ -107,7 +106,7 @@ static void qemu_remap_bucket(MapCacheEntry *entry,
uint8_t *vaddr_base;
xen_pfn_t *pfns;
int *err;
- unsigned int i, j;
+ unsigned int i;
target_phys_addr_t nb_pfn = size >> XC_PAGE_SHIFT;
trace_qemu_remap_bucket(address_index);
@@ -136,17 +135,11 @@ static void qemu_remap_bucket(MapCacheEntry *entry,
entry->vaddr_base = vaddr_base;
entry->paddr_index = address_index;
- for (i = 0; i < nb_pfn; i += BITS_PER_LONG) {
- unsigned long word = 0;
- if ((i + BITS_PER_LONG) > nb_pfn) {
- j = nb_pfn % BITS_PER_LONG;
- } else {
- j = BITS_PER_LONG;
- }
- while (j > 0) {
- word = (word << 1) | !err[i + --j];
+ bitmap_zero(entry->valid_mapping, nb_pfn);
+ for (i = 0; i < nb_pfn; i++) {
+ if (!err[i]) {
+ bitmap_set(entry->valid_mapping, i, 1);
}
- entry->valid_mapping[i / BITS_PER_LONG] = word;
}
qemu_free(pfns);
commit 432d268c0552fd30c8be564f7ea2504a2b546101
Author: Jun Nakajima <jun.nakajima at intel.com>
Date: Tue Aug 31 16:41:25 2010 +0100
xen: Introduce the Xen mapcache
On IA32 host or IA32 PAE host, at present, generally, we can't create
an HVM guest with more than 2G memory, because generally it's almost
impossible for Qemu to find a large enough and consecutive virtual
address space to map an HVM guest's whole physical address space.
The attached patch fixes this issue using dynamic mapping based on
little blocks of memory.
Each call to qemu_get_ram_ptr makes a call to qemu_map_cache with the
lock option, so mapcache will not unmap these ram_ptr.
Blocks that do not belong to the RAM, but usually to a device ROM or to
a framebuffer, are handled in a separate function. So the whole RAMBlock
can be map.
Signed-off-by: Jun Nakajima <jun.nakajima at intel.com>
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/Makefile.target b/Makefile.target
index fd84d46..2e281a4 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -214,8 +214,11 @@ else
CONFIG_NO_XEN = y
endif
# xen support
+CONFIG_NO_XEN_MAPCACHE = $(if $(subst n,,$(CONFIG_XEN_MAPCACHE)),n,y)
obj-i386-$(CONFIG_XEN) += xen-all.o
obj-$(CONFIG_NO_XEN) += xen-stub.o
+obj-i386-$(CONFIG_XEN_MAPCACHE) += xen-mapcache.o
+obj-$(CONFIG_NO_XEN_MAPCACHE) += xen-mapcache-stub.o
# Inter-VM PCI shared memory
CONFIG_IVSHMEM =
diff --git a/configure b/configure
index 5df84d2..6fc2bdd 100755
--- a/configure
+++ b/configure
@@ -3299,6 +3299,9 @@ case "$target_arch2" in
i386|x86_64)
if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
echo "CONFIG_XEN=y" >> $config_target_mak
+ if test "$cpu" = "i386" -o "$cpu" = "x86_64"; then
+ echo "CONFIG_XEN_MAPCACHE=y" >> $config_target_mak
+ fi
fi
esac
case "$target_arch2" in
diff --git a/exec.c b/exec.c
index 308a86d..8c81cff 100644
--- a/exec.c
+++ b/exec.c
@@ -32,6 +32,7 @@
#include "hw/qdev.h"
#include "osdep.h"
#include "kvm.h"
+#include "hw/xen.h"
#include "qemu-timer.h"
#if defined(CONFIG_USER_ONLY)
#include <qemu.h>
@@ -51,6 +52,8 @@
#include <libutil.h>
#endif
#endif
+#else /* !CONFIG_USER_ONLY */
+#include "xen-mapcache.h"
#endif
//#define DEBUG_TB_INVALIDATE
@@ -2889,6 +2892,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
}
}
+ new_block->offset = find_ram_offset(size);
if (host) {
new_block->host = host;
new_block->flags |= RAM_PREALLOC_MASK;
@@ -2911,13 +2915,15 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
PROT_EXEC|PROT_READ|PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
#else
- new_block->host = qemu_vmalloc(size);
+ if (xen_mapcache_enabled()) {
+ xen_ram_alloc(new_block->offset, size);
+ } else {
+ new_block->host = qemu_vmalloc(size);
+ }
#endif
qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
}
}
-
- new_block->offset = find_ram_offset(size);
new_block->length = size;
QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
@@ -2962,7 +2968,11 @@ void qemu_ram_free(ram_addr_t addr)
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
munmap(block->host, block->length);
#else
- qemu_vfree(block->host);
+ if (xen_mapcache_enabled()) {
+ qemu_invalidate_entry(block->host);
+ } else {
+ qemu_vfree(block->host);
+ }
#endif
}
qemu_free(block);
@@ -3051,6 +3061,16 @@ void *qemu_get_ram_ptr(ram_addr_t addr)
QLIST_REMOVE(block, next);
QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
}
+ if (xen_mapcache_enabled()) {
+ /* We need to check if the requested address is in the RAM
+ * because we don't want to map the entire memory in QEMU.
+ */
+ if (block->offset == 0) {
+ return qemu_map_cache(addr, 0, 1);
+ } else if (block->host == NULL) {
+ block->host = xen_map_block(block->offset, block->length);
+ }
+ }
return block->host + (addr - block->offset);
}
}
@@ -3070,6 +3090,16 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
QLIST_FOREACH(block, &ram_list.blocks, next) {
if (addr - block->offset < block->length) {
+ if (xen_mapcache_enabled()) {
+ /* We need to check if the requested address is in the RAM
+ * because we don't want to map the entire memory in QEMU.
+ */
+ if (block->offset == 0) {
+ return qemu_map_cache(addr, 0, 1);
+ } else if (block->host == NULL) {
+ block->host = xen_map_block(block->offset, block->length);
+ }
+ }
return block->host + (addr - block->offset);
}
}
@@ -3086,11 +3116,21 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
uint8_t *host = ptr;
QLIST_FOREACH(block, &ram_list.blocks, next) {
+ /* This case append when the block is not mapped. */
+ if (block->host == NULL) {
+ continue;
+ }
if (host - block->host < block->length) {
*ram_addr = block->offset + (host - block->host);
return 0;
}
}
+
+ if (xen_mapcache_enabled()) {
+ *ram_addr = qemu_ram_addr_from_mapcache(ptr);
+ return 0;
+ }
+
return -1;
}
diff --git a/hw/xen.h b/hw/xen.h
index 9f00c0b..6245b38 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -31,6 +31,15 @@ static inline int xen_enabled(void)
#endif
}
+static inline int xen_mapcache_enabled(void)
+{
+#ifdef CONFIG_XEN_MAPCACHE
+ return xen_enabled();
+#else
+ return 0;
+#endif
+}
+
int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
void xen_piix3_set_irq(void *opaque, int irq_num, int level);
void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len);
@@ -41,6 +50,10 @@ int xen_init(void);
int xen_hvm_init(void);
void xen_vcpu_init(void);
+#if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY)
+void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size);
+#endif
+
#if defined(CONFIG_XEN) && CONFIG_XEN_CTRL_INTERFACE_VERSION < 400
# define HVM_MAX_VCPUS 32
#endif
diff --git a/hw/xen_common.h b/hw/xen_common.h
index 47b8afe..dd3e896 100644
--- a/hw/xen_common.h
+++ b/hw/xen_common.h
@@ -63,6 +63,15 @@ static inline int xc_fd(int xen_xc)
}
+static inline int xc_domain_populate_physmap_exact
+ (XenXC xc_handle, uint32_t domid, unsigned long nr_extents,
+ unsigned int extent_order, unsigned int mem_flags, xen_pfn_t *extent_start)
+{
+ return xc_domain_memory_populate_physmap
+ (xc_handle, domid, nr_extents, extent_order, mem_flags, extent_start);
+}
+
+
/* Xen 4.1 */
#else
diff --git a/trace-events b/trace-events
index 4f965e2..d703347 100644
--- a/trace-events
+++ b/trace-events
@@ -361,3 +361,13 @@ disable milkymist_uart_pulse_irq_tx(void) "Pulse IRQ TX"
# hw/milkymist-vgafb.c
disable milkymist_vgafb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
disable milkymist_vgafb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
+
+# xen-all.c
+disable xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: %#lx, size %#lx"
+
+# xen-mapcache.c
+disable qemu_map_cache(uint64_t phys_addr) "want %#"PRIx64""
+disable qemu_remap_bucket(uint64_t index) "index %#"PRIx64""
+disable qemu_map_cache_return(void* ptr) "%p"
+disable xen_map_block(uint64_t phys_addr, uint64_t size) "%#"PRIx64", size %#"PRIx64""
+disable xen_unmap_block(void* addr, unsigned long size) "%p, size %#lx"
diff --git a/xen-all.c b/xen-all.c
index bb809ef..cb01ab9 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -10,6 +10,9 @@
#include "hw/xen_common.h"
#include "hw/xen_backend.h"
+#include "xen-mapcache.h"
+#include "trace.h"
+
/* Xen specific function for piix pci */
int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
@@ -52,6 +55,65 @@ qemu_irq *xen_interrupt_controller_init(void)
return qemu_allocate_irqs(xen_set_irq, NULL, 16);
}
+/* Memory Ops */
+
+static void xen_ram_init(ram_addr_t ram_size)
+{
+ RAMBlock *new_block;
+ ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
+
+ new_block = qemu_mallocz(sizeof (*new_block));
+ pstrcpy(new_block->idstr, sizeof (new_block->idstr), "xen.ram");
+ new_block->host = NULL;
+ new_block->offset = 0;
+ new_block->length = ram_size;
+
+ QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
+
+ ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
+ new_block->length >> TARGET_PAGE_BITS);
+ memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
+ 0xff, new_block->length >> TARGET_PAGE_BITS);
+
+ if (ram_size >= 0xe0000000 ) {
+ above_4g_mem_size = ram_size - 0xe0000000;
+ below_4g_mem_size = 0xe0000000;
+ } else {
+ below_4g_mem_size = ram_size;
+ }
+
+ cpu_register_physical_memory(0, below_4g_mem_size, new_block->offset);
+#if TARGET_PHYS_ADDR_BITS > 32
+ if (above_4g_mem_size > 0) {
+ cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
+ new_block->offset + below_4g_mem_size);
+ }
+#endif
+}
+
+void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
+{
+ unsigned long nr_pfn;
+ xen_pfn_t *pfn_list;
+ int i;
+
+ trace_xen_ram_alloc(ram_addr, size);
+
+ nr_pfn = size >> TARGET_PAGE_BITS;
+ pfn_list = qemu_malloc(sizeof (*pfn_list) * nr_pfn);
+
+ for (i = 0; i < nr_pfn; i++) {
+ pfn_list[i] = (ram_addr >> TARGET_PAGE_BITS) + i;
+ }
+
+ if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) {
+ hw_error("xen: failed to populate ram at %lx", ram_addr);
+ }
+
+ qemu_free(pfn_list);
+}
+
+
/* VCPU Operations, MMIO, IO ring ... */
static void xen_reset_vcpu(void *opaque)
@@ -86,5 +148,9 @@ int xen_init(void)
int xen_hvm_init(void)
{
+ /* Init RAM management */
+ qemu_map_cache_init();
+ xen_ram_init(ram_size);
+
return 0;
}
diff --git a/xen-mapcache-stub.c b/xen-mapcache-stub.c
new file mode 100644
index 0000000..7c14b3d
--- /dev/null
+++ b/xen-mapcache-stub.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "config.h"
+
+#include "exec-all.h"
+#include "qemu-common.h"
+#include "cpu-common.h"
+#include "xen-mapcache.h"
+
+void qemu_map_cache_init(void)
+{
+}
+
+uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, uint8_t lock)
+{
+ return qemu_get_ram_ptr(phys_addr);
+}
+
+void qemu_map_cache_unlock(void *buffer)
+{
+}
+
+ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
+{
+ return -1;
+}
+
+void qemu_invalidate_map_cache(void)
+{
+}
+
+void qemu_invalidate_entry(uint8_t *buffer)
+{
+}
+uint8_t *xen_map_block(target_phys_addr_t phys_addr, target_phys_addr_t size)
+{
+ return NULL;
+}
diff --git a/xen-mapcache.c b/xen-mapcache.c
new file mode 100644
index 0000000..a539358
--- /dev/null
+++ b/xen-mapcache.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2011 Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/resource.h>
+
+#include "hw/xen_backend.h"
+#include "blockdev.h"
+
+#include <xen/hvm/params.h>
+#include <sys/mman.h>
+
+#include "xen-mapcache.h"
+#include "trace.h"
+
+
+//#define MAPCACHE_DEBUG
+
+#ifdef MAPCACHE_DEBUG
+# define DPRINTF(fmt, ...) do { \
+ fprintf(stderr, "xen_mapcache: " fmt, ## __VA_ARGS__); \
+} while (0)
+#else
+# define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+#if defined(__i386__)
+# define MCACHE_BUCKET_SHIFT 16
+#elif defined(__x86_64__)
+# define MCACHE_BUCKET_SHIFT 20
+#endif
+#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT)
+
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define BITS_TO_LONGS(bits) (((bits) + BITS_PER_LONG - 1) / BITS_PER_LONG)
+#define DECLARE_BITMAP(name, bits) unsigned long name[BITS_TO_LONGS(bits)]
+
+typedef struct MapCacheEntry {
+ target_phys_addr_t paddr_index;
+ uint8_t *vaddr_base;
+ DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE >> XC_PAGE_SHIFT);
+ uint8_t lock;
+ struct MapCacheEntry *next;
+} MapCacheEntry;
+
+typedef struct MapCacheRev {
+ uint8_t *vaddr_req;
+ target_phys_addr_t paddr_index;
+ QTAILQ_ENTRY(MapCacheRev) next;
+} MapCacheRev;
+
+typedef struct MapCache {
+ MapCacheEntry *entry;
+ unsigned long nr_buckets;
+ QTAILQ_HEAD(map_cache_head, MapCacheRev) locked_entries;
+
+ /* For most cases (>99.9%), the page address is the same. */
+ target_phys_addr_t last_address_index;
+ uint8_t *last_address_vaddr;
+ unsigned long max_mcache_size;
+ unsigned int mcache_bucket_shift;
+} MapCache;
+
+static MapCache *mapcache;
+
+static inline int test_bit(unsigned int bit, const unsigned long *map)
+{
+ return !!((map)[(bit) / BITS_PER_LONG] & (1UL << ((bit) % BITS_PER_LONG)));
+}
+
+void qemu_map_cache_init(void)
+{
+ unsigned long size;
+ struct rlimit rlimit_as;
+
+ mapcache = qemu_mallocz(sizeof (MapCache));
+
+ QTAILQ_INIT(&mapcache->locked_entries);
+ mapcache->last_address_index = -1;
+
+ getrlimit(RLIMIT_AS, &rlimit_as);
+ rlimit_as.rlim_cur = rlimit_as.rlim_max;
+ setrlimit(RLIMIT_AS, &rlimit_as);
+ mapcache->max_mcache_size = rlimit_as.rlim_max;
+
+ mapcache->nr_buckets =
+ (((mapcache->max_mcache_size >> XC_PAGE_SHIFT) +
+ (1UL << (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)) - 1) >>
+ (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT));
+
+ size = mapcache->nr_buckets * sizeof (MapCacheEntry);
+ size = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1);
+ DPRINTF("qemu_map_cache_init, nr_buckets = %lx size %lu\n", mapcache->nr_buckets, size);
+ mapcache->entry = qemu_mallocz(size);
+}
+
+static void qemu_remap_bucket(MapCacheEntry *entry,
+ target_phys_addr_t size,
+ target_phys_addr_t address_index)
+{
+ uint8_t *vaddr_base;
+ xen_pfn_t *pfns;
+ int *err;
+ unsigned int i, j;
+ target_phys_addr_t nb_pfn = size >> XC_PAGE_SHIFT;
+
+ trace_qemu_remap_bucket(address_index);
+
+ pfns = qemu_mallocz(nb_pfn * sizeof (xen_pfn_t));
+ err = qemu_mallocz(nb_pfn * sizeof (int));
+
+ if (entry->vaddr_base != NULL) {
+ if (munmap(entry->vaddr_base, size) != 0) {
+ perror("unmap fails");
+ exit(-1);
+ }
+ }
+
+ for (i = 0; i < nb_pfn; i++) {
+ pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-XC_PAGE_SHIFT)) + i;
+ }
+
+ vaddr_base = xc_map_foreign_bulk(xen_xc, xen_domid, PROT_READ|PROT_WRITE,
+ pfns, err, nb_pfn);
+ if (vaddr_base == NULL) {
+ perror("xc_map_foreign_bulk");
+ exit(-1);
+ }
+
+ entry->vaddr_base = vaddr_base;
+ entry->paddr_index = address_index;
+
+ for (i = 0; i < nb_pfn; i += BITS_PER_LONG) {
+ unsigned long word = 0;
+ if ((i + BITS_PER_LONG) > nb_pfn) {
+ j = nb_pfn % BITS_PER_LONG;
+ } else {
+ j = BITS_PER_LONG;
+ }
+ while (j > 0) {
+ word = (word << 1) | !err[i + --j];
+ }
+ entry->valid_mapping[i / BITS_PER_LONG] = word;
+ }
+
+ qemu_free(pfns);
+ qemu_free(err);
+}
+
+uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, uint8_t lock)
+{
+ MapCacheEntry *entry, *pentry = NULL;
+ target_phys_addr_t address_index = phys_addr >> MCACHE_BUCKET_SHIFT;
+ target_phys_addr_t address_offset = phys_addr & (MCACHE_BUCKET_SIZE - 1);
+
+ trace_qemu_map_cache(phys_addr);
+
+ if (address_index == mapcache->last_address_index && !lock) {
+ trace_qemu_map_cache_return(mapcache->last_address_vaddr + address_offset);
+ return mapcache->last_address_vaddr + address_offset;
+ }
+
+ entry = &mapcache->entry[address_index % mapcache->nr_buckets];
+
+ while (entry && entry->lock && entry->paddr_index != address_index && entry->vaddr_base) {
+ pentry = entry;
+ entry = entry->next;
+ }
+ if (!entry) {
+ entry = qemu_mallocz(sizeof (MapCacheEntry));
+ pentry->next = entry;
+ qemu_remap_bucket(entry, size ? : MCACHE_BUCKET_SIZE, address_index);
+ } else if (!entry->lock) {
+ if (!entry->vaddr_base || entry->paddr_index != address_index ||
+ !test_bit(address_offset >> XC_PAGE_SHIFT, entry->valid_mapping)) {
+ qemu_remap_bucket(entry, size ? : MCACHE_BUCKET_SIZE, address_index);
+ }
+ }
+
+ if (!test_bit(address_offset >> XC_PAGE_SHIFT, entry->valid_mapping)) {
+ mapcache->last_address_index = -1;
+ trace_qemu_map_cache_return(NULL);
+ return NULL;
+ }
+
+ mapcache->last_address_index = address_index;
+ mapcache->last_address_vaddr = entry->vaddr_base;
+ if (lock) {
+ MapCacheRev *reventry = qemu_mallocz(sizeof(MapCacheRev));
+ entry->lock++;
+ reventry->vaddr_req = mapcache->last_address_vaddr + address_offset;
+ reventry->paddr_index = mapcache->last_address_index;
+ QTAILQ_INSERT_HEAD(&mapcache->locked_entries, reventry, next);
+ }
+
+ trace_qemu_map_cache_return(mapcache->last_address_vaddr + address_offset);
+ return mapcache->last_address_vaddr + address_offset;
+}
+
+ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
+{
+ MapCacheRev *reventry;
+ target_phys_addr_t paddr_index;
+ int found = 0;
+
+ QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
+ if (reventry->vaddr_req == ptr) {
+ paddr_index = reventry->paddr_index;
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ fprintf(stderr, "qemu_ram_addr_from_mapcache, could not find %p\n", ptr);
+ QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
+ DPRINTF(" "TARGET_FMT_plx" -> %p is present\n", reventry->paddr_index,
+ reventry->vaddr_req);
+ }
+ abort();
+ return 0;
+ }
+
+ return paddr_index << MCACHE_BUCKET_SHIFT;
+}
+
+void qemu_invalidate_entry(uint8_t *buffer)
+{
+ MapCacheEntry *entry = NULL, *pentry = NULL;
+ MapCacheRev *reventry;
+ target_phys_addr_t paddr_index;
+ int found = 0;
+
+ if (mapcache->last_address_vaddr == buffer) {
+ mapcache->last_address_index = -1;
+ }
+
+ QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
+ if (reventry->vaddr_req == buffer) {
+ paddr_index = reventry->paddr_index;
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ DPRINTF("qemu_invalidate_entry, could not find %p\n", buffer);
+ QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
+ DPRINTF(" "TARGET_FMT_plx" -> %p is present\n", reventry->paddr_index, reventry->vaddr_req);
+ }
+ return;
+ }
+ QTAILQ_REMOVE(&mapcache->locked_entries, reventry, next);
+ qemu_free(reventry);
+
+ entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
+ while (entry && entry->paddr_index != paddr_index) {
+ pentry = entry;
+ entry = entry->next;
+ }
+ if (!entry) {
+ DPRINTF("Trying to unmap address %p that is not in the mapcache!\n", buffer);
+ return;
+ }
+ entry->lock--;
+ if (entry->lock > 0 || pentry == NULL) {
+ return;
+ }
+
+ pentry->next = entry->next;
+ if (munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE) != 0) {
+ perror("unmap fails");
+ exit(-1);
+ }
+ qemu_free(entry);
+}
+
+void qemu_invalidate_map_cache(void)
+{
+ unsigned long i;
+ MapCacheRev *reventry;
+
+ /* Flush pending AIO before destroying the mapcache */
+ qemu_aio_flush();
+
+ QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
+ DPRINTF("There should be no locked mappings at this time, "
+ "but "TARGET_FMT_plx" -> %p is present\n",
+ reventry->paddr_index, reventry->vaddr_req);
+ }
+
+ mapcache_lock();
+
+ for (i = 0; i < mapcache->nr_buckets; i++) {
+ MapCacheEntry *entry = &mapcache->entry[i];
+
+ if (entry->vaddr_base == NULL) {
+ continue;
+ }
+
+ if (munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE) != 0) {
+ perror("unmap fails");
+ exit(-1);
+ }
+
+ entry->paddr_index = 0;
+ entry->vaddr_base = NULL;
+ }
+
+ mapcache->last_address_index = -1;
+ mapcache->last_address_vaddr = NULL;
+
+ mapcache_unlock();
+}
+
+uint8_t *xen_map_block(target_phys_addr_t phys_addr, target_phys_addr_t size)
+{
+ uint8_t *vaddr_base;
+ xen_pfn_t *pfns;
+ int *err;
+ unsigned int i;
+ target_phys_addr_t nb_pfn = size >> XC_PAGE_SHIFT;
+
+ trace_xen_map_block(phys_addr, size);
+ phys_addr >>= XC_PAGE_SHIFT;
+
+ pfns = qemu_mallocz(nb_pfn * sizeof (xen_pfn_t));
+ err = qemu_mallocz(nb_pfn * sizeof (int));
+
+ for (i = 0; i < nb_pfn; i++) {
+ pfns[i] = phys_addr + i;
+ }
+
+ vaddr_base = xc_map_foreign_bulk(xen_xc, xen_domid, PROT_READ|PROT_WRITE,
+ pfns, err, nb_pfn);
+ if (vaddr_base == NULL) {
+ perror("xc_map_foreign_bulk");
+ exit(-1);
+ }
+
+ qemu_free(pfns);
+ qemu_free(err);
+
+ return vaddr_base;
+}
diff --git a/xen-mapcache.h b/xen-mapcache.h
new file mode 100644
index 0000000..339444c
--- /dev/null
+++ b/xen-mapcache.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef XEN_MAPCACHE_H
+#define XEN_MAPCACHE_H
+
+#include <sys/mman.h>
+#include "trace.h"
+
+void qemu_map_cache_init(void);
+uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, uint8_t lock);
+void qemu_map_cache_unlock(void *phys_addr);
+ram_addr_t qemu_ram_addr_from_mapcache(void *ptr);
+void qemu_invalidate_entry(uint8_t *buffer);
+void qemu_invalidate_map_cache(void);
+
+uint8_t *xen_map_block(target_phys_addr_t phys_addr, target_phys_addr_t size);
+
+static inline void xen_unmap_block(void *addr, ram_addr_t size)
+{
+ trace_xen_unmap_block(addr, size);
+
+ if (munmap(addr, size) != 0) {
+ hw_error("xen_unmap_block: %s", strerror(errno));
+ }
+}
+
+
+#define mapcache_lock() ((void)0)
+#define mapcache_unlock() ((void)0)
+
+#endif /* !XEN_MAPCACHE_H */
diff --git a/xen-stub.c b/xen-stub.c
index 3a8449c..8d2fa54 100644
--- a/xen-stub.c
+++ b/xen-stub.c
@@ -22,6 +22,10 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
{
}
+void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
+{
+}
+
qemu_irq *xen_interrupt_controller_init(void)
{
return NULL;
commit 9c11a8ac886ccbb5f8e1b08e8ae12f045d783031
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Wed Jun 30 17:50:10 2010 +0100
xen: Introduce Xen Interrupt Controller
Every set_irq call makes a Xen hypercall.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 9353b91..62cdf71 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -110,8 +110,12 @@ static void pc_init1(ram_addr_t ram_size,
below_4g_mem_size, above_4g_mem_size);
}
- cpu_irq = pc_allocate_cpu_irq();
- i8259 = i8259_init(cpu_irq[0]);
+ if (!xen_enabled()) {
+ cpu_irq = pc_allocate_cpu_irq();
+ i8259 = i8259_init(cpu_irq[0]);
+ } else {
+ i8259 = xen_interrupt_controller_init();
+ }
isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
isa_irq_state->i8259 = i8259;
if (pci_enabled) {
diff --git a/hw/xen.h b/hw/xen.h
index a4096ca..9f00c0b 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -35,6 +35,8 @@ int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
void xen_piix3_set_irq(void *opaque, int irq_num, int level);
void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len);
+qemu_irq *xen_interrupt_controller_init(void);
+
int xen_init(void);
int xen_hvm_init(void);
void xen_vcpu_init(void);
diff --git a/xen-all.c b/xen-all.c
index acb051c..bb809ef 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -40,6 +40,18 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
}
}
+/* Xen Interrupt Controller */
+
+static void xen_set_irq(void *opaque, int irq, int level)
+{
+ xc_hvm_set_isa_irq_level(xen_xc, xen_domid, irq, level);
+}
+
+qemu_irq *xen_interrupt_controller_init(void)
+{
+ return qemu_allocate_irqs(xen_set_irq, NULL, 16);
+}
+
/* VCPU Operations, MMIO, IO ring ... */
static void xen_reset_vcpu(void *opaque)
diff --git a/xen-stub.c b/xen-stub.c
index dc90f10..3a8449c 100644
--- a/xen-stub.c
+++ b/xen-stub.c
@@ -22,6 +22,11 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
{
}
+qemu_irq *xen_interrupt_controller_init(void)
+{
+ return NULL;
+}
+
int xen_init(void)
{
return -ENOSYS;
commit 4144530012793e6cd479eaa90cceb1aef0de8158
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Fri Jul 16 14:55:39 2010 +0100
piix_pci: Introduces Xen specific call for irq.
This patch introduces Xen specific call in piix_pci.
The specific part for Xen is in write_config, set_irq and get_pirq.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/pc.h b/hw/pc.h
index 6d5730b..0dcbee7 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -176,6 +176,7 @@ struct PCII440FXState;
typedef struct PCII440FXState PCII440FXState;
PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, ram_addr_t ram_size);
+PCIBus *i440fx_xen_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic, ram_addr_t ram_size);
void i440fx_init_memory_mappings(PCII440FXState *d);
/* piix4.c */
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index e814f00..9353b91 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -120,7 +120,11 @@ static void pc_init1(ram_addr_t ram_size,
isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
if (pci_enabled) {
- pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
+ if (!xen_enabled()) {
+ pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
+ } else {
+ pci_bus = i440fx_xen_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
+ }
} else {
pci_bus = NULL;
i440fx_state = NULL;
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 5f0d92f..7f1c4cc 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -29,6 +29,7 @@
#include "isa.h"
#include "sysbus.h"
#include "range.h"
+#include "xen.h"
/*
* I440FX chipset data sheet.
@@ -172,6 +173,13 @@ static void i440fx_write_config(PCIDevice *dev,
}
}
+static void i440fx_write_config_xen(PCIDevice *dev,
+ uint32_t address, uint32_t val, int len)
+{
+ xen_piix_pci_write_config_client(address, val, len);
+ i440fx_write_config(dev, address, val, len);
+}
+
static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
{
PCII440FXState *d = opaque;
@@ -239,7 +247,10 @@ static int i440fx_initfn(PCIDevice *dev)
return 0;
}
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic, ram_addr_t ram_size)
+static PCIBus *i440fx_common_init(const char *device_name,
+ PCII440FXState **pi440fx_state,
+ int *piix3_devfn,
+ qemu_irq *pic, ram_addr_t ram_size)
{
DeviceState *dev;
PCIBus *b;
@@ -253,13 +264,13 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *
s->bus = b;
qdev_init_nofail(dev);
- d = pci_create_simple(b, 0, "i440FX");
+ d = pci_create_simple(b, 0, device_name);
*pi440fx_state = DO_UPCAST(PCII440FXState, dev, d);
piix3 = DO_UPCAST(PIIX3State, dev,
pci_create_simple_multifunction(b, -1, true, "PIIX3"));
piix3->pic = pic;
- pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, PIIX_NUM_PIRQS);
+
(*pi440fx_state)->piix3 = piix3;
*piix3_devfn = piix3->dev.devfn;
@@ -272,6 +283,30 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *
return b;
}
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
+ qemu_irq *pic, ram_addr_t ram_size)
+{
+ PCIBus *b;
+
+ b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic, ram_size);
+ pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, (*pi440fx_state)->piix3,
+ PIIX_NUM_PIRQS);
+
+ return b;
+}
+
+PCIBus *i440fx_xen_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
+ qemu_irq *pic, ram_addr_t ram_size)
+{
+ PCIBus *b;
+
+ b = i440fx_common_init("i440FX-xen", pi440fx_state, piix3_devfn, pic, ram_size);
+ pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq,
+ (*pi440fx_state)->piix3, PIIX_NUM_PIRQS);
+
+ return b;
+}
+
/* PIIX3 PCI to ISA bridge */
static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
{
@@ -430,6 +465,14 @@ static PCIDeviceInfo i440fx_info[] = {
.init = i440fx_initfn,
.config_write = i440fx_write_config,
},{
+ .qdev.name = "i440FX-xen",
+ .qdev.desc = "Host bridge",
+ .qdev.size = sizeof(PCII440FXState),
+ .qdev.vmsd = &vmstate_i440fx,
+ .qdev.no_user = 1,
+ .init = i440fx_initfn,
+ .config_write = i440fx_write_config_xen,
+ },{
.qdev.name = "PIIX3",
.qdev.desc = "ISA bridge",
.qdev.size = sizeof(PIIX3State),
diff --git a/hw/xen.h b/hw/xen.h
index bb4dcb5..a4096ca 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -8,6 +8,8 @@
*/
#include <inttypes.h>
+#include "qemu-common.h"
+
/* xen-machine.c */
enum xen_mode {
XEN_EMULATE = 0, // xen emulation, using xenner (default)
@@ -29,6 +31,10 @@ static inline int xen_enabled(void)
#endif
}
+int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
+void xen_piix3_set_irq(void *opaque, int irq_num, int level);
+void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len);
+
int xen_init(void);
int xen_hvm_init(void);
void xen_vcpu_init(void);
diff --git a/xen-all.c b/xen-all.c
index 0b984b2..acb051c 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -6,9 +6,40 @@
*
*/
+#include "hw/pci.h"
#include "hw/xen_common.h"
#include "hw/xen_backend.h"
+/* Xen specific function for piix pci */
+
+int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+ return irq_num + ((pci_dev->devfn >> 3) << 2);
+}
+
+void xen_piix3_set_irq(void *opaque, int irq_num, int level)
+{
+ xc_hvm_set_pci_intx_level(xen_xc, xen_domid, 0, 0, irq_num >> 2,
+ irq_num & 3, level);
+}
+
+void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
+{
+ int i;
+
+ /* Scan for updates to PCI link routes (0x60-0x63). */
+ for (i = 0; i < len; i++) {
+ uint8_t v = (val >> (8 * i)) & 0xff;
+ if (v & 0x80) {
+ v = 0;
+ }
+ v &= 0xf;
+ if (((address + i) >= 0x60) && ((address + i) <= 0x63)) {
+ xc_hvm_set_pci_link_route(xen_xc, xen_domid, address + i - 0x60, v);
+ }
+ }
+}
+
/* VCPU Operations, MMIO, IO ring ... */
static void xen_reset_vcpu(void *opaque)
diff --git a/xen-stub.c b/xen-stub.c
index beb982f..dc90f10 100644
--- a/xen-stub.c
+++ b/xen-stub.c
@@ -9,6 +9,19 @@
#include "qemu-common.h"
#include "hw/xen.h"
+int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+ return -1;
+}
+
+void xen_piix3_set_irq(void *opaque, int irq_num, int level)
+{
+}
+
+void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
+{
+}
+
int xen_init(void)
{
return -ENOSYS;
commit 1611977c3d8fdbdac6090cbd1f5555cee4aed6d9
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Tue May 3 17:06:54 2011 +0100
pc, Disable vmport initialisation with Xen.
This is because there is not synchronisation of the vcpu register
between Xen and QEMU, so vmport can't work properly.
This patch introduces no_vmport parameter to pc_basic_device_init.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/pc.c b/hw/pc.c
index ebdf3b0..8106197 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1082,7 +1082,8 @@ static void cpu_request_exit(void *opaque, int irq, int level)
}
void pc_basic_device_init(qemu_irq *isa_irq,
- ISADevice **rtc_state)
+ ISADevice **rtc_state,
+ bool no_vmport)
{
int i;
DriveInfo *fd[MAX_FD];
@@ -1127,8 +1128,12 @@ void pc_basic_device_init(qemu_irq *isa_irq,
a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
i8042 = isa_create_simple("i8042");
i8042_setup_a20_line(i8042, &a20_line[0]);
- vmport_init();
- vmmouse = isa_try_create("vmmouse");
+ if (!no_vmport) {
+ vmport_init();
+ vmmouse = isa_try_create("vmmouse");
+ } else {
+ vmmouse = NULL;
+ }
if (vmmouse) {
qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
qdev_init_nofail(&vmmouse->qdev);
diff --git a/hw/pc.h b/hw/pc.h
index b7ee7f8..6d5730b 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -137,7 +137,8 @@ void pc_memory_init(const char *kernel_filename,
qemu_irq *pc_allocate_cpu_irq(void);
void pc_vga_init(PCIBus *pci_bus);
void pc_basic_device_init(qemu_irq *isa_irq,
- ISADevice **rtc_state);
+ ISADevice **rtc_state,
+ bool no_vmport);
void pc_init_ne2k_isa(NICInfo *nd);
void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
const char *boot_device,
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index aba3d58..e814f00 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -133,7 +133,7 @@ static void pc_init1(ram_addr_t ram_size,
pc_vga_init(pci_enabled? pci_bus: NULL);
/* init basic PC hardware */
- pc_basic_device_init(isa_irq, &rtc_state);
+ pc_basic_device_init(isa_irq, &rtc_state, xen_enabled());
for(i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
commit 29d3ccde82a0d782b81da39342fb3e3bcf547537
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Wed Jun 30 12:58:34 2010 +0100
xen: Add xenfv machine
Introduce the Xen FV (Fully Virtualized) machine to Qemu, some more Xen
specific call will be added in further patches.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 23a6bfb..aba3d58 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -38,6 +38,10 @@
#include "arch_init.h"
#include "blockdev.h"
#include "smbus.h"
+#include "xen.h"
+#ifdef CONFIG_XEN
+# include <xen/hvm/hvm_info_table.h>
+#endif
#define MAX_IDE_BUS 2
@@ -101,8 +105,10 @@ static void pc_init1(ram_addr_t ram_size,
}
/* allocate ram and load rom/bios */
- pc_memory_init(kernel_filename, kernel_cmdline, initrd_filename,
- below_4g_mem_size, above_4g_mem_size);
+ if (!xen_enabled()) {
+ pc_memory_init(kernel_filename, kernel_cmdline, initrd_filename,
+ below_4g_mem_size, above_4g_mem_size);
+ }
cpu_irq = pc_allocate_cpu_irq();
i8259 = i8259_init(cpu_irq[0]);
@@ -221,6 +227,24 @@ static void pc_init_isa(ram_addr_t ram_size,
initrd_filename, cpu_model, 0, 1);
}
+#ifdef CONFIG_XEN
+static void pc_xen_hvm_init(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)
+{
+ if (xen_hvm_init() != 0) {
+ hw_error("xen hardware virtual machine initialisation failed");
+ }
+ pc_init_pci_no_kvmclock(ram_size, boot_device,
+ kernel_filename, kernel_cmdline,
+ initrd_filename, cpu_model);
+ xen_vcpu_init();
+}
+#endif
+
static QEMUMachine pc_machine = {
.name = "pc-0.14",
.alias = "pc",
@@ -385,6 +409,16 @@ static QEMUMachine isapc_machine = {
.max_cpus = 1,
};
+#ifdef CONFIG_XEN
+static QEMUMachine xenfv_machine = {
+ .name = "xenfv",
+ .desc = "Xen Fully-virtualized PC",
+ .init = pc_xen_hvm_init,
+ .max_cpus = HVM_MAX_VCPUS,
+ .default_machine_opts = "accel=xen",
+};
+#endif
+
static void pc_machine_init(void)
{
qemu_register_machine(&pc_machine);
@@ -393,6 +427,9 @@ static void pc_machine_init(void)
qemu_register_machine(&pc_machine_v0_11);
qemu_register_machine(&pc_machine_v0_10);
qemu_register_machine(&isapc_machine);
+#ifdef CONFIG_XEN
+ qemu_register_machine(&xenfv_machine);
+#endif
}
machine_init(pc_machine_init);
diff --git a/hw/xen.h b/hw/xen.h
index 1fefe3a..bb4dcb5 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -30,5 +30,11 @@ static inline int xen_enabled(void)
}
int xen_init(void);
+int xen_hvm_init(void);
+void xen_vcpu_init(void);
+
+#if defined(CONFIG_XEN) && CONFIG_XEN_CTRL_INTERFACE_VERSION < 400
+# define HVM_MAX_VCPUS 32
+#endif
#endif /* QEMU_HW_XEN_H */
diff --git a/xen-all.c b/xen-all.c
index e2872f9..0b984b2 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -9,6 +9,25 @@
#include "hw/xen_common.h"
#include "hw/xen_backend.h"
+/* VCPU Operations, MMIO, IO ring ... */
+
+static void xen_reset_vcpu(void *opaque)
+{
+ CPUState *env = opaque;
+
+ env->halted = 1;
+}
+
+void xen_vcpu_init(void)
+{
+ CPUState *first_cpu;
+
+ if ((first_cpu = qemu_get_cpu(0))) {
+ qemu_register_reset(xen_reset_vcpu, first_cpu);
+ xen_reset_vcpu(first_cpu);
+ }
+}
+
/* Initialise Xen */
int xen_init(void)
@@ -21,3 +40,8 @@ int xen_init(void)
return 0;
}
+
+int xen_hvm_init(void)
+{
+ return 0;
+}
commit e0e7e67b455afa254356acdac1254653f6eed47b
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Mon Apr 11 19:48:11 2011 +0100
pc_memory_init: Move memory calculation to the caller.
This patch moves above_4g_mem_size and below_4g_mem_size calculation in
the caller of pc_memory_init (pc_init1). And the prototype of
pc_memory_init is changed because there is no need anymore to have
variable pointer and the ram_size parameter.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/pc.c b/hw/pc.c
index 6939c04..ebdf3b0 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -957,29 +957,18 @@ void pc_cpus_init(const char *cpu_model)
}
}
-void pc_memory_init(ram_addr_t ram_size,
- const char *kernel_filename,
+void pc_memory_init(const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
- ram_addr_t *below_4g_mem_size_p,
- ram_addr_t *above_4g_mem_size_p)
+ ram_addr_t below_4g_mem_size,
+ ram_addr_t above_4g_mem_size)
{
char *filename;
int ret, linux_boot, i;
ram_addr_t ram_addr, bios_offset, option_rom_offset;
- ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
int bios_size, isa_bios_size;
void *fw_cfg;
- if (ram_size >= 0xe0000000 ) {
- above_4g_mem_size = ram_size - 0xe0000000;
- below_4g_mem_size = 0xe0000000;
- } else {
- below_4g_mem_size = ram_size;
- }
- *above_4g_mem_size_p = above_4g_mem_size;
- *below_4g_mem_size_p = below_4g_mem_size;
-
linux_boot = (kernel_filename != NULL);
/* allocate RAM */
diff --git a/hw/pc.h b/hw/pc.h
index feb8a7a..b7ee7f8 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -129,12 +129,11 @@ void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
void pc_cpus_init(const char *cpu_model);
-void pc_memory_init(ram_addr_t ram_size,
- const char *kernel_filename,
+void pc_memory_init(const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
- ram_addr_t *below_4g_mem_size_p,
- ram_addr_t *above_4g_mem_size_p);
+ ram_addr_t below_4g_mem_size,
+ ram_addr_t above_4g_mem_size);
qemu_irq *pc_allocate_cpu_irq(void);
void pc_vga_init(PCIBus *pci_bus);
void pc_basic_device_init(qemu_irq *isa_irq,
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index a85214b..23a6bfb 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -92,9 +92,17 @@ static void pc_init1(ram_addr_t ram_size,
kvmclock_create();
}
+ if (ram_size >= 0xe0000000 ) {
+ above_4g_mem_size = ram_size - 0xe0000000;
+ below_4g_mem_size = 0xe0000000;
+ } else {
+ above_4g_mem_size = 0;
+ below_4g_mem_size = ram_size;
+ }
+
/* allocate ram and load rom/bios */
- pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
- &below_4g_mem_size, &above_4g_mem_size);
+ pc_memory_init(kernel_filename, kernel_cmdline, initrd_filename,
+ below_4g_mem_size, above_4g_mem_size);
cpu_irq = pc_allocate_cpu_irq();
i8259 = i8259_init(cpu_irq[0]);
commit 3285cf4fe78b4b83b70b9306cc97968b414a6e9d
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Thu Aug 19 12:27:56 2010 +0100
xen: Add initialisation of Xen
The xenpv machine use the common init function.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/Makefile.target b/Makefile.target
index 6873f76..fd84d46 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -208,6 +208,15 @@ QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
# xen backend driver support
obj-i386-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
+ifeq ($(TARGET_BASE_ARCH), i386)
+ CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
+else
+ CONFIG_NO_XEN = y
+endif
+# xen support
+obj-i386-$(CONFIG_XEN) += xen-all.o
+obj-$(CONFIG_NO_XEN) += xen-stub.o
+
# Inter-VM PCI shared memory
CONFIG_IVSHMEM =
ifeq ($(CONFIG_KVM), y)
diff --git a/hw/xen.h b/hw/xen.h
index 780dcf7..1fefe3a 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -18,4 +18,17 @@ enum xen_mode {
extern uint32_t xen_domid;
extern enum xen_mode xen_mode;
+extern int xen_allowed;
+
+static inline int xen_enabled(void)
+{
+#ifdef CONFIG_XEN
+ return xen_allowed;
+#else
+ return 0;
+#endif
+}
+
+int xen_init(void);
+
#endif /* QEMU_HW_XEN_H */
diff --git a/hw/xen_backend.c b/hw/xen_backend.c
index 5f58a3f..d881fa2 100644
--- a/hw/xen_backend.c
+++ b/hw/xen_backend.c
@@ -665,9 +665,8 @@ int xen_be_init(void)
goto err;
}
- xen_xc = xen_xc_interface_open(0, 0, 0);
if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
- xen_be_printf(NULL, 0, "can't open xen interface\n");
+ /* Check if xen_init() have been called */
goto err;
}
return 0;
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 0d7f73e..7985d11 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -113,6 +113,7 @@ static QEMUMachine xenpv_machine = {
.desc = "Xen Para-virtualized PC",
.init = xen_init_pv,
.max_cpus = 1,
+ .default_machine_opts = "accel=xen",
};
static void xenpv_machine_init(void)
diff --git a/vl.c b/vl.c
index 4632469..3ed6855 100644
--- a/vl.c
+++ b/vl.c
@@ -259,6 +259,7 @@ static NotifierList machine_init_done_notifiers =
static int tcg_allowed = 1;
int kvm_allowed = 0;
+int xen_allowed = 0;
uint32_t xen_domid;
enum xen_mode xen_mode = XEN_EMULATE;
@@ -1890,6 +1891,7 @@ static struct {
int *allowed;
} accel_list[] = {
{ "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed },
+ { "xen", "Xen", xen_available, xen_init, &xen_allowed },
{ "kvm", "KVM", kvm_available, kvm_init, &kvm_allowed },
};
diff --git a/xen-all.c b/xen-all.c
new file mode 100644
index 0000000..e2872f9
--- /dev/null
+++ b/xen-all.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010 Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw/xen_common.h"
+#include "hw/xen_backend.h"
+
+/* Initialise Xen */
+
+int xen_init(void)
+{
+ xen_xc = xen_xc_interface_open(0, 0, 0);
+ if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
+ xen_be_printf(NULL, 0, "can't open xen interface\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/xen-stub.c b/xen-stub.c
new file mode 100644
index 0000000..beb982f
--- /dev/null
+++ b/xen-stub.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2010 Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "hw/xen.h"
+
+int xen_init(void)
+{
+ return -ENOSYS;
+}
commit d5b93ddfefe63d5869a8eb97ea3474867d3b105b
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Fri Feb 25 16:20:34 2011 +0000
xen: Support new libxc calls from xen unstable.
This patch updates the libxenctrl calls in Qemu to use the new interface,
otherwise Qemu wouldn't be able to build against new versions of the
library.
We check libxenctrl version in configure, from Xen 3.3.0 to Xen
unstable.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/configure b/configure
index 6f75e2e..5df84d2 100755
--- a/configure
+++ b/configure
@@ -127,6 +127,7 @@ vnc_jpeg=""
vnc_png=""
vnc_thread="no"
xen=""
+xen_ctrl_version=""
linux_aio=""
attr=""
vhost_net=""
@@ -1180,20 +1181,81 @@ fi
if test "$xen" != "no" ; then
xen_libs="-lxenstore -lxenctrl -lxenguest"
+
+ # Xen unstable
cat > $TMPC <<EOF
#include <xenctrl.h>
#include <xs.h>
-int main(void) { xs_daemon_open(); xc_interface_open(); return 0; }
+#include <stdint.h>
+#include <xen/hvm/hvm_info_table.h>
+#if !defined(HVM_MAX_VCPUS)
+# error HVM_MAX_VCPUS not defined
+#endif
+int main(void) {
+ xc_interface *xc;
+ xs_daemon_open();
+ xc = xc_interface_open(0, 0, 0);
+ xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
+ xc_gnttab_open(NULL, 0);
+ return 0;
+}
EOF
if compile_prog "" "$xen_libs" ; then
+ xen_ctrl_version=410
xen=yes
- libs_softmmu="$xen_libs $libs_softmmu"
+
+ # Xen 4.0.0
+ elif (
+ cat > $TMPC <<EOF
+#include <xenctrl.h>
+#include <xs.h>
+#include <stdint.h>
+#include <xen/hvm/hvm_info_table.h>
+#if !defined(HVM_MAX_VCPUS)
+# error HVM_MAX_VCPUS not defined
+#endif
+int main(void) {
+ xs_daemon_open();
+ xc_interface_open();
+ xc_gnttab_open();
+ xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
+ return 0;
+}
+EOF
+ compile_prog "" "$xen_libs"
+ ) ; then
+ xen_ctrl_version=400
+ xen=yes
+
+ # Xen 3.3.0, 3.4.0
+ elif (
+ cat > $TMPC <<EOF
+#include <xenctrl.h>
+#include <xs.h>
+int main(void) {
+ xs_daemon_open();
+ xc_interface_open();
+ xc_gnttab_open();
+ xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
+ return 0;
+}
+EOF
+ compile_prog "" "$xen_libs"
+ ) ; then
+ xen_ctrl_version=330
+ xen=yes
+
+ # Xen not found or unsupported
else
if test "$xen" = "yes" ; then
feature_not_found "xen"
fi
xen=no
fi
+
+ if test "$xen" = yes; then
+ libs_softmmu="$xen_libs $libs_softmmu"
+ fi
fi
##########################################
@@ -2855,6 +2917,7 @@ if test "$bluez" = "yes" ; then
fi
if test "$xen" = "yes" ; then
echo "CONFIG_XEN=y" >> $config_host_mak
+ echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak
fi
if test "$io_thread" = "yes" ; then
echo "CONFIG_IOTHREAD=y" >> $config_host_mak
diff --git a/hw/xen_backend.c b/hw/xen_backend.c
index 9f4ec4b..5f58a3f 100644
--- a/hw/xen_backend.c
+++ b/hw/xen_backend.c
@@ -43,7 +43,8 @@
/* ------------------------------------------------------------- */
/* public */
-int xen_xc;
+XenXC xen_xc = XC_HANDLER_INITIAL_VALUE;
+XenGnttab xen_xcg = XC_HANDLER_INITIAL_VALUE;
struct xs_handle *xenstore = NULL;
const char *xen_protocol;
@@ -214,8 +215,8 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
xendev->debug = debug;
xendev->local_port = -1;
- xendev->evtchndev = xc_evtchn_open();
- if (xendev->evtchndev < 0) {
+ xendev->evtchndev = xen_xc_evtchn_open(NULL, 0);
+ if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
xen_be_printf(NULL, 0, "can't open evtchn device\n");
qemu_free(xendev);
return NULL;
@@ -223,15 +224,15 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
- xendev->gnttabdev = xc_gnttab_open();
- if (xendev->gnttabdev < 0) {
+ xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
+ if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
xen_be_printf(NULL, 0, "can't open gnttab device\n");
xc_evtchn_close(xendev->evtchndev);
qemu_free(xendev);
return NULL;
}
} else {
- xendev->gnttabdev = -1;
+ xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
}
QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
@@ -277,10 +278,10 @@ static struct XenDevice *xen_be_del_xendev(int dom, int dev)
qemu_free(xendev->fe);
}
- if (xendev->evtchndev >= 0) {
+ if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
xc_evtchn_close(xendev->evtchndev);
}
- if (xendev->gnttabdev >= 0) {
+ if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
xc_gnttab_close(xendev->gnttabdev);
}
@@ -664,8 +665,8 @@ int xen_be_init(void)
goto err;
}
- xen_xc = xc_interface_open();
- if (xen_xc == -1) {
+ xen_xc = xen_xc_interface_open(0, 0, 0);
+ if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
xen_be_printf(NULL, 0, "can't open xen interface\n");
goto err;
}
diff --git a/hw/xen_backend.h b/hw/xen_backend.h
index 1b428e3..6401c85 100644
--- a/hw/xen_backend.h
+++ b/hw/xen_backend.h
@@ -45,8 +45,8 @@ struct XenDevice {
int remote_port;
int local_port;
- int evtchndev;
- int gnttabdev;
+ XenEvtchn evtchndev;
+ XenGnttab gnttabdev;
struct XenDevOps *ops;
QTAILQ_ENTRY(XenDevice) next;
@@ -55,7 +55,7 @@ struct XenDevice {
/* ------------------------------------------------------------- */
/* variables */
-extern int xen_xc;
+extern XenXC xen_xc;
extern struct xs_handle *xenstore;
extern const char *xen_protocol;
diff --git a/hw/xen_common.h b/hw/xen_common.h
index 8a55b44..47b8afe 100644
--- a/hw/xen_common.h
+++ b/hw/xen_common.h
@@ -1,6 +1,8 @@
#ifndef QEMU_HW_XEN_COMMON_H
#define QEMU_HW_XEN_COMMON_H 1
+#include "config-host.h"
+
#include <stddef.h>
#include <inttypes.h>
@@ -13,22 +15,87 @@
#include "qemu-queue.h"
/*
- * tweaks needed to build with different xen versions
- * 0x00030205 -> 3.1.0
- * 0x00030207 -> 3.2.0
- * 0x00030208 -> unstable
+ * We don't support Xen prior to 3.3.0.
*/
-#include <xen/xen-compat.h>
-#if __XEN_LATEST_INTERFACE_VERSION__ < 0x00030205
-# define evtchn_port_or_error_t int
-#endif
-#if __XEN_LATEST_INTERFACE_VERSION__ < 0x00030207
-# define xc_map_foreign_pages xc_map_foreign_batch
+
+/* Xen before 4.0 */
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 400
+static inline void *xc_map_foreign_bulk(int xc_handle, uint32_t dom, int prot,
+ xen_pfn_t *arr, int *err,
+ unsigned int num)
+{
+ return xc_map_foreign_batch(xc_handle, dom, prot, arr, num);
+}
#endif
-#if __XEN_LATEST_INTERFACE_VERSION__ < 0x00030208
-# define xen_mb() mb()
-# define xen_rmb() rmb()
-# define xen_wmb() wmb()
+
+
+/* Xen before 4.1 */
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
+
+typedef int XenXC;
+typedef int XenEvtchn;
+typedef int XenGnttab;
+
+# define XC_INTERFACE_FMT "%i"
+# define XC_HANDLER_INITIAL_VALUE -1
+
+static inline XenEvtchn xen_xc_evtchn_open(void *logger,
+ unsigned int open_flags)
+{
+ return xc_evtchn_open();
+}
+
+static inline XenGnttab xen_xc_gnttab_open(void *logger,
+ unsigned int open_flags)
+{
+ return xc_gnttab_open();
+}
+
+static inline XenXC xen_xc_interface_open(void *logger, void *dombuild_logger,
+ unsigned int open_flags)
+{
+ return xc_interface_open();
+}
+
+static inline int xc_fd(int xen_xc)
+{
+ return xen_xc;
+}
+
+
+/* Xen 4.1 */
+#else
+
+typedef xc_interface *XenXC;
+typedef xc_evtchn *XenEvtchn;
+typedef xc_gnttab *XenGnttab;
+
+# define XC_INTERFACE_FMT "%p"
+# define XC_HANDLER_INITIAL_VALUE NULL
+
+static inline XenEvtchn xen_xc_evtchn_open(void *logger,
+ unsigned int open_flags)
+{
+ return xc_evtchn_open(logger, open_flags);
+}
+
+static inline XenGnttab xen_xc_gnttab_open(void *logger,
+ unsigned int open_flags)
+{
+ return xc_gnttab_open(logger, open_flags);
+}
+
+static inline XenXC xen_xc_interface_open(void *logger, void *dombuild_logger,
+ unsigned int open_flags)
+{
+ return xc_interface_open(logger, dombuild_logger, open_flags);
+}
+
+/* FIXME There is now way to have the xen fd */
+static inline int xc_fd(xc_interface *xen_xc)
+{
+ return -1;
+}
#endif
#endif /* QEMU_HW_XEN_COMMON_H */
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 2b3a8fe..233c8c9 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -242,7 +242,7 @@ err:
static void ioreq_unmap(struct ioreq *ioreq)
{
- int gnt = ioreq->blkdev->xendev.gnttabdev;
+ XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
int i;
if (ioreq->v.niov == 0) {
@@ -275,7 +275,7 @@ static void ioreq_unmap(struct ioreq *ioreq)
static int ioreq_map(struct ioreq *ioreq)
{
- int gnt = ioreq->blkdev->xendev.gnttabdev;
+ XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
int i;
if (ioreq->v.niov == 0) {
diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c
index 4093587..a6a12e5 100644
--- a/hw/xen_domainbuild.c
+++ b/hw/xen_domainbuild.c
@@ -175,8 +175,9 @@ static int xen_domain_watcher(void)
for (i = 3; i < n; i++) {
if (i == fd[0])
continue;
- if (i == xen_xc)
+ if (i == xc_fd(xen_xc)) {
continue;
+ }
close(i);
}
commit ce6bc29458e9e0a95da8aa192fc117125132dc2a
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Tue Mar 29 18:39:00 2011 +0100
xen: Make Xen build once.
xen_domainbuild and xen_machine_pv are built only for i386 targets.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/Makefile.target b/Makefile.target
index 21f864a..6873f76 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -206,7 +206,7 @@ QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
# xen backend driver support
-obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
+obj-i386-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
# Inter-VM PCI shared memory
CONFIG_IVSHMEM =
commit 209cd7abe26cffe2cab680696771514757457f55
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Thu Sep 23 12:28:45 2010 +0100
xen: Replace some tab-indents with spaces (clean-up).
And put braces for blocks with a single statement.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/xen_backend.c b/hw/xen_backend.c
index a2e408f..9f4ec4b 100644
--- a/hw/xen_backend.c
+++ b/hw/xen_backend.c
@@ -58,8 +58,9 @@ int xenstore_write_str(const char *base, const char *node, const char *val)
char abspath[XEN_BUFSIZE];
snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
- if (!xs_write(xenstore, 0, abspath, val, strlen(val)))
- return -1;
+ if (!xs_write(xenstore, 0, abspath, val, strlen(val))) {
+ return -1;
+ }
return 0;
}
@@ -94,8 +95,9 @@ int xenstore_read_int(const char *base, const char *node, int *ival)
int rc = -1;
val = xenstore_read_str(base, node);
- if (val && 1 == sscanf(val, "%d", ival))
- rc = 0;
+ if (val && 1 == sscanf(val, "%d", ival)) {
+ rc = 0;
+ }
qemu_free(val);
return rc;
}
@@ -134,16 +136,16 @@ int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival)
const char *xenbus_strstate(enum xenbus_state state)
{
- static const char *const name[] = {
- [ XenbusStateUnknown ] = "Unknown",
- [ XenbusStateInitialising ] = "Initialising",
- [ XenbusStateInitWait ] = "InitWait",
- [ XenbusStateInitialised ] = "Initialised",
- [ XenbusStateConnected ] = "Connected",
- [ XenbusStateClosing ] = "Closing",
- [ XenbusStateClosed ] = "Closed",
- };
- return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
+ static const char *const name[] = {
+ [ XenbusStateUnknown ] = "Unknown",
+ [ XenbusStateInitialising ] = "Initialising",
+ [ XenbusStateInitWait ] = "InitWait",
+ [ XenbusStateInitialised ] = "Initialised",
+ [ XenbusStateConnected ] = "Connected",
+ [ XenbusStateClosing ] = "Closing",
+ [ XenbusStateClosed ] = "Closed",
+ };
+ return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
}
int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
@@ -151,10 +153,11 @@ int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
int rc;
rc = xenstore_write_be_int(xendev, "state", state);
- if (rc < 0)
- return rc;
+ if (rc < 0) {
+ return rc;
+ }
xen_be_printf(xendev, 1, "backend state: %s -> %s\n",
- xenbus_strstate(xendev->be_state), xenbus_strstate(state));
+ xenbus_strstate(xendev->be_state), xenbus_strstate(state));
xendev->be_state = state;
return 0;
}
@@ -166,13 +169,16 @@ struct XenDevice *xen_be_find_xendev(const char *type, int dom, int dev)
struct XenDevice *xendev;
QTAILQ_FOREACH(xendev, &xendevs, next) {
- if (xendev->dom != dom)
- continue;
- if (xendev->dev != dev)
- continue;
- if (strcmp(xendev->type, type) != 0)
- continue;
- return xendev;
+ if (xendev->dom != dom) {
+ continue;
+ }
+ if (xendev->dev != dev) {
+ continue;
+ }
+ if (strcmp(xendev->type, type) != 0) {
+ continue;
+ }
+ return xendev;
}
return NULL;
}
@@ -187,8 +193,9 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
char *dom0;
xendev = xen_be_find_xendev(type, dom, dev);
- if (xendev)
- return xendev;
+ if (xendev) {
+ return xendev;
+ }
/* init new xendev */
xendev = qemu_mallocz(ops->size);
@@ -199,9 +206,9 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
dom0 = xs_get_domain_path(xenstore, 0);
snprintf(xendev->be, sizeof(xendev->be), "%s/backend/%s/%d/%d",
- dom0, xendev->type, xendev->dom, xendev->dev);
+ dom0, xendev->type, xendev->dom, xendev->dev);
snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
- xendev->type, xendev->dev);
+ xendev->type, xendev->dev);
free(dom0);
xendev->debug = debug;
@@ -209,28 +216,29 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
xendev->evtchndev = xc_evtchn_open();
if (xendev->evtchndev < 0) {
- xen_be_printf(NULL, 0, "can't open evtchn device\n");
- qemu_free(xendev);
- return NULL;
+ xen_be_printf(NULL, 0, "can't open evtchn device\n");
+ qemu_free(xendev);
+ return NULL;
}
fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
- xendev->gnttabdev = xc_gnttab_open();
- if (xendev->gnttabdev < 0) {
- xen_be_printf(NULL, 0, "can't open gnttab device\n");
- xc_evtchn_close(xendev->evtchndev);
- qemu_free(xendev);
- return NULL;
- }
+ xendev->gnttabdev = xc_gnttab_open();
+ if (xendev->gnttabdev < 0) {
+ xen_be_printf(NULL, 0, "can't open gnttab device\n");
+ xc_evtchn_close(xendev->evtchndev);
+ qemu_free(xendev);
+ return NULL;
+ }
} else {
- xendev->gnttabdev = -1;
+ xendev->gnttabdev = -1;
}
QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
- if (xendev->ops->alloc)
- xendev->ops->alloc(xendev);
+ if (xendev->ops->alloc) {
+ xendev->ops->alloc(xendev);
+ }
return xendev;
}
@@ -251,28 +259,33 @@ static struct XenDevice *xen_be_del_xendev(int dom, int dev)
xendev = xnext;
xnext = xendev->next.tqe_next;
- if (xendev->dom != dom)
- continue;
- if (xendev->dev != dev && dev != -1)
- continue;
-
- if (xendev->ops->free)
- xendev->ops->free(xendev);
-
- if (xendev->fe) {
- char token[XEN_BUFSIZE];
- snprintf(token, sizeof(token), "fe:%p", xendev);
- xs_unwatch(xenstore, xendev->fe, token);
- qemu_free(xendev->fe);
- }
-
- if (xendev->evtchndev >= 0)
- xc_evtchn_close(xendev->evtchndev);
- if (xendev->gnttabdev >= 0)
- xc_gnttab_close(xendev->gnttabdev);
-
- QTAILQ_REMOVE(&xendevs, xendev, next);
- qemu_free(xendev);
+ if (xendev->dom != dom) {
+ continue;
+ }
+ if (xendev->dev != dev && dev != -1) {
+ continue;
+ }
+
+ if (xendev->ops->free) {
+ xendev->ops->free(xendev);
+ }
+
+ if (xendev->fe) {
+ char token[XEN_BUFSIZE];
+ snprintf(token, sizeof(token), "fe:%p", xendev);
+ xs_unwatch(xenstore, xendev->fe, token);
+ qemu_free(xendev->fe);
+ }
+
+ if (xendev->evtchndev >= 0) {
+ xc_evtchn_close(xendev->evtchndev);
+ }
+ if (xendev->gnttabdev >= 0) {
+ xc_gnttab_close(xendev->gnttabdev);
+ }
+
+ QTAILQ_REMOVE(&xendevs, xendev, next);
+ qemu_free(xendev);
}
return NULL;
}
@@ -285,14 +298,16 @@ static struct XenDevice *xen_be_del_xendev(int dom, int dev)
static void xen_be_backend_changed(struct XenDevice *xendev, const char *node)
{
if (node == NULL || strcmp(node, "online") == 0) {
- if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1)
- xendev->online = 0;
+ if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
+ xendev->online = 0;
+ }
}
if (node) {
- xen_be_printf(xendev, 2, "backend update: %s\n", node);
- if (xendev->ops->backend_changed)
- xendev->ops->backend_changed(xendev, node);
+ xen_be_printf(xendev, 2, "backend update: %s\n", node);
+ if (xendev->ops->backend_changed) {
+ xendev->ops->backend_changed(xendev, node);
+ }
}
}
@@ -301,25 +316,29 @@ static void xen_be_frontend_changed(struct XenDevice *xendev, const char *node)
int fe_state;
if (node == NULL || strcmp(node, "state") == 0) {
- if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1)
- fe_state = XenbusStateUnknown;
- if (xendev->fe_state != fe_state)
- xen_be_printf(xendev, 1, "frontend state: %s -> %s\n",
- xenbus_strstate(xendev->fe_state),
- xenbus_strstate(fe_state));
- xendev->fe_state = fe_state;
+ if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
+ fe_state = XenbusStateUnknown;
+ }
+ if (xendev->fe_state != fe_state) {
+ xen_be_printf(xendev, 1, "frontend state: %s -> %s\n",
+ xenbus_strstate(xendev->fe_state),
+ xenbus_strstate(fe_state));
+ }
+ xendev->fe_state = fe_state;
}
if (node == NULL || strcmp(node, "protocol") == 0) {
- qemu_free(xendev->protocol);
- xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
- if (xendev->protocol)
- xen_be_printf(xendev, 1, "frontend protocol: %s\n", xendev->protocol);
+ qemu_free(xendev->protocol);
+ xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
+ if (xendev->protocol) {
+ xen_be_printf(xendev, 1, "frontend protocol: %s\n", xendev->protocol);
+ }
}
if (node) {
- xen_be_printf(xendev, 2, "frontend update: %s\n", node);
- if (xendev->ops->frontend_changed)
- xendev->ops->frontend_changed(xendev, node);
+ xen_be_printf(xendev, 2, "frontend update: %s\n", node);
+ if (xendev->ops->frontend_changed) {
+ xendev->ops->frontend_changed(xendev, node);
+ }
}
}
@@ -340,28 +359,28 @@ static int xen_be_try_setup(struct XenDevice *xendev)
int be_state;
if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
- xen_be_printf(xendev, 0, "reading backend state failed\n");
- return -1;
+ xen_be_printf(xendev, 0, "reading backend state failed\n");
+ return -1;
}
if (be_state != XenbusStateInitialising) {
- xen_be_printf(xendev, 0, "initial backend state is wrong (%s)\n",
- xenbus_strstate(be_state));
- return -1;
+ xen_be_printf(xendev, 0, "initial backend state is wrong (%s)\n",
+ xenbus_strstate(be_state));
+ return -1;
}
xendev->fe = xenstore_read_be_str(xendev, "frontend");
if (xendev->fe == NULL) {
- xen_be_printf(xendev, 0, "reading frontend path failed\n");
- return -1;
+ xen_be_printf(xendev, 0, "reading frontend path failed\n");
+ return -1;
}
/* setup frontend watch */
snprintf(token, sizeof(token), "fe:%p", xendev);
if (!xs_watch(xenstore, xendev->fe, token)) {
- xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n",
- xendev->fe);
- return -1;
+ xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n",
+ xendev->fe);
+ return -1;
}
xen_be_set_state(xendev, XenbusStateInitialising);
@@ -383,15 +402,16 @@ static int xen_be_try_init(struct XenDevice *xendev)
int rc = 0;
if (!xendev->online) {
- xen_be_printf(xendev, 1, "not online\n");
- return -1;
+ xen_be_printf(xendev, 1, "not online\n");
+ return -1;
}
- if (xendev->ops->init)
- rc = xendev->ops->init(xendev);
+ if (xendev->ops->init) {
+ rc = xendev->ops->init(xendev);
+ }
if (rc != 0) {
- xen_be_printf(xendev, 1, "init() failed\n");
- return rc;
+ xen_be_printf(xendev, 1, "init() failed\n");
+ return rc;
}
xenstore_write_be_str(xendev, "hotplug-status", "connected");
@@ -411,20 +431,21 @@ static int xen_be_try_connect(struct XenDevice *xendev)
int rc = 0;
if (xendev->fe_state != XenbusStateInitialised &&
- xendev->fe_state != XenbusStateConnected) {
- if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
- xen_be_printf(xendev, 2, "frontend not ready, ignoring\n");
- } else {
- xen_be_printf(xendev, 2, "frontend not ready (yet)\n");
- return -1;
- }
+ xendev->fe_state != XenbusStateConnected) {
+ if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
+ xen_be_printf(xendev, 2, "frontend not ready, ignoring\n");
+ } else {
+ xen_be_printf(xendev, 2, "frontend not ready (yet)\n");
+ return -1;
+ }
}
- if (xendev->ops->connect)
- rc = xendev->ops->connect(xendev);
+ if (xendev->ops->connect) {
+ rc = xendev->ops->connect(xendev);
+ }
if (rc != 0) {
- xen_be_printf(xendev, 0, "connect() failed\n");
- return rc;
+ xen_be_printf(xendev, 0, "connect() failed\n");
+ return rc;
}
xen_be_set_state(xendev, XenbusStateConnected);
@@ -440,10 +461,12 @@ static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state)
{
if (xendev->be_state != XenbusStateClosing &&
xendev->be_state != XenbusStateClosed &&
- xendev->ops->disconnect)
- xendev->ops->disconnect(xendev);
- if (xendev->be_state != state)
+ xendev->ops->disconnect) {
+ xendev->ops->disconnect(xendev);
+ }
+ if (xendev->be_state != state) {
xen_be_set_state(xendev, state);
+ }
}
/*
@@ -451,8 +474,9 @@ static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state)
*/
static int xen_be_try_reset(struct XenDevice *xendev)
{
- if (xendev->fe_state != XenbusStateInitialising)
+ if (xendev->fe_state != XenbusStateInitialising) {
return -1;
+ }
xen_be_printf(xendev, 1, "device reset (for re-connect)\n");
xen_be_set_state(xendev, XenbusStateInitialising);
@@ -468,31 +492,32 @@ void xen_be_check_state(struct XenDevice *xendev)
/* frontend may request shutdown from almost anywhere */
if (xendev->fe_state == XenbusStateClosing ||
- xendev->fe_state == XenbusStateClosed) {
- xen_be_disconnect(xendev, xendev->fe_state);
- return;
+ xendev->fe_state == XenbusStateClosed) {
+ xen_be_disconnect(xendev, xendev->fe_state);
+ return;
}
/* check for possible backend state transitions */
for (;;) {
- switch (xendev->be_state) {
- case XenbusStateUnknown:
- rc = xen_be_try_setup(xendev);
- break;
- case XenbusStateInitialising:
- rc = xen_be_try_init(xendev);
- break;
- case XenbusStateInitWait:
- rc = xen_be_try_connect(xendev);
- break;
+ switch (xendev->be_state) {
+ case XenbusStateUnknown:
+ rc = xen_be_try_setup(xendev);
+ break;
+ case XenbusStateInitialising:
+ rc = xen_be_try_init(xendev);
+ break;
+ case XenbusStateInitWait:
+ rc = xen_be_try_connect(xendev);
+ break;
case XenbusStateClosed:
rc = xen_be_try_reset(xendev);
break;
- default:
- rc = -1;
- }
- if (rc != 0)
- break;
+ default:
+ rc = -1;
+ }
+ if (rc != 0) {
+ break;
+ }
}
}
@@ -511,26 +536,28 @@ static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
free(dom0);
if (!xs_watch(xenstore, path, token)) {
- xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
- return -1;
+ xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
+ return -1;
}
/* look for backends */
dev = xs_directory(xenstore, 0, path, &cdev);
- if (!dev)
- return 0;
+ if (!dev) {
+ return 0;
+ }
for (j = 0; j < cdev; j++) {
- xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
- if (xendev == NULL)
- continue;
- xen_be_check_state(xendev);
+ xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
+ if (xendev == NULL) {
+ continue;
+ }
+ xen_be_check_state(xendev);
}
free(dev);
return 0;
}
static void xenstore_update_be(char *watch, char *type, int dom,
- struct XenDevOps *ops)
+ struct XenDevOps *ops)
{
struct XenDevice *xendev;
char path[XEN_BUFSIZE], *dom0;
@@ -539,25 +566,28 @@ static void xenstore_update_be(char *watch, char *type, int dom,
dom0 = xs_get_domain_path(xenstore, 0);
len = snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
free(dom0);
- if (strncmp(path, watch, len) != 0)
- return;
+ if (strncmp(path, watch, len) != 0) {
+ return;
+ }
if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
- strcpy(path, "");
- if (sscanf(watch+len, "/%u", &dev) != 1)
- dev = -1;
+ strcpy(path, "");
+ if (sscanf(watch+len, "/%u", &dev) != 1) {
+ dev = -1;
+ }
+ }
+ if (dev == -1) {
+ return;
}
- if (dev == -1)
- return;
if (0) {
- /* FIXME: detect devices being deleted from xenstore ... */
- xen_be_del_xendev(dom, dev);
+ /* FIXME: detect devices being deleted from xenstore ... */
+ xen_be_del_xendev(dom, dev);
}
xendev = xen_be_get_xendev(type, dom, dev, ops);
if (xendev != NULL) {
- xen_be_backend_changed(xendev, path);
- xen_be_check_state(xendev);
+ xen_be_backend_changed(xendev, path);
+ xen_be_check_state(xendev);
}
}
@@ -567,10 +597,12 @@ static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
unsigned int len;
len = strlen(xendev->fe);
- if (strncmp(xendev->fe, watch, len) != 0)
- return;
- if (watch[len] != '/')
- return;
+ if (strncmp(xendev->fe, watch, len) != 0) {
+ return;
+ }
+ if (watch[len] != '/') {
+ return;
+ }
node = watch + len + 1;
xen_be_frontend_changed(xendev, node);
@@ -584,14 +616,17 @@ static void xenstore_update(void *unused)
unsigned int dom, count;
vec = xs_read_watch(xenstore, &count);
- if (vec == NULL)
- goto cleanup;
+ if (vec == NULL) {
+ goto cleanup;
+ }
if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
- &type, &dom, &ops) == 3)
- xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom, (void*)ops);
- if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1)
- xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
+ &type, &dom, &ops) == 3) {
+ xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom, (void*)ops);
+ }
+ if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
+ xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
+ }
cleanup:
free(vec);
@@ -604,14 +639,15 @@ static void xen_be_evtchn_event(void *opaque)
port = xc_evtchn_pending(xendev->evtchndev);
if (port != xendev->local_port) {
- xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
- port, xendev->local_port);
- return;
+ xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
+ port, xendev->local_port);
+ return;
}
xc_evtchn_unmask(xendev->evtchndev, port);
- if (xendev->ops->event)
- xendev->ops->event(xendev);
+ if (xendev->ops->event) {
+ xendev->ops->event(xendev);
+ }
}
/* -------------------------------------------------------------------- */
@@ -620,17 +656,18 @@ int xen_be_init(void)
{
xenstore = xs_daemon_open();
if (!xenstore) {
- xen_be_printf(NULL, 0, "can't connect to xenstored\n");
- return -1;
+ xen_be_printf(NULL, 0, "can't connect to xenstored\n");
+ return -1;
}
- if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0)
- goto err;
+ if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0) {
+ goto err;
+ }
xen_xc = xc_interface_open();
if (xen_xc == -1) {
- xen_be_printf(NULL, 0, "can't open xen interface\n");
- goto err;
+ xen_be_printf(NULL, 0, "can't open xen interface\n");
+ goto err;
}
return 0;
@@ -649,24 +686,26 @@ int xen_be_register(const char *type, struct XenDevOps *ops)
int xen_be_bind_evtchn(struct XenDevice *xendev)
{
- if (xendev->local_port != -1)
- return 0;
+ if (xendev->local_port != -1) {
+ return 0;
+ }
xendev->local_port = xc_evtchn_bind_interdomain
- (xendev->evtchndev, xendev->dom, xendev->remote_port);
+ (xendev->evtchndev, xendev->dom, xendev->remote_port);
if (xendev->local_port == -1) {
- xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
- return -1;
+ xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
+ return -1;
}
xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
- xen_be_evtchn_event, NULL, xendev);
+ xen_be_evtchn_event, NULL, xendev);
return 0;
}
void xen_be_unbind_evtchn(struct XenDevice *xendev)
{
- if (xendev->local_port == -1)
- return;
+ if (xendev->local_port == -1) {
+ return;
+ }
qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
xc_evtchn_unbind(xendev->evtchndev, xendev->local_port);
xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
@@ -690,17 +729,21 @@ void xen_be_printf(struct XenDevice *xendev, int msg_level, const char *fmt, ...
va_list args;
if (xendev) {
- if (msg_level > xendev->debug)
+ if (msg_level > xendev->debug) {
return;
+ }
qemu_log("xen be: %s: ", xendev->name);
- if (msg_level == 0)
+ if (msg_level == 0) {
fprintf(stderr, "xen be: %s: ", xendev->name);
+ }
} else {
- if (msg_level > debug)
+ if (msg_level > debug) {
return;
+ }
qemu_log("xen be core: ");
- if (msg_level == 0)
+ if (msg_level == 0) {
fprintf(stderr, "xen be core: ");
+ }
}
va_start(args, fmt);
qemu_log_vprintf(fmt, args);
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 558bf8a..2b3a8fe 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -120,17 +120,18 @@ static struct ioreq *ioreq_start(struct XenBlkDev *blkdev)
struct ioreq *ioreq = NULL;
if (QLIST_EMPTY(&blkdev->freelist)) {
- if (blkdev->requests_total >= max_requests)
- goto out;
- /* allocate new struct */
- ioreq = qemu_mallocz(sizeof(*ioreq));
- ioreq->blkdev = blkdev;
- blkdev->requests_total++;
+ if (blkdev->requests_total >= max_requests) {
+ goto out;
+ }
+ /* allocate new struct */
+ ioreq = qemu_mallocz(sizeof(*ioreq));
+ ioreq->blkdev = blkdev;
+ blkdev->requests_total++;
qemu_iovec_init(&ioreq->v, BLKIF_MAX_SEGMENTS_PER_REQUEST);
} else {
- /* get one from freelist */
- ioreq = QLIST_FIRST(&blkdev->freelist);
- QLIST_REMOVE(ioreq, list);
+ /* get one from freelist */
+ ioreq = QLIST_FIRST(&blkdev->freelist);
+ QLIST_REMOVE(ioreq, list);
qemu_iovec_reset(&ioreq->v);
}
QLIST_INSERT_HEAD(&blkdev->inflight, ioreq, list);
@@ -173,30 +174,32 @@ static int ioreq_parse(struct ioreq *ioreq)
int i;
xen_be_printf(&blkdev->xendev, 3,
- "op %d, nr %d, handle %d, id %" PRId64 ", sector %" PRId64 "\n",
- ioreq->req.operation, ioreq->req.nr_segments,
- ioreq->req.handle, ioreq->req.id, ioreq->req.sector_number);
+ "op %d, nr %d, handle %d, id %" PRId64 ", sector %" PRId64 "\n",
+ ioreq->req.operation, ioreq->req.nr_segments,
+ ioreq->req.handle, ioreq->req.id, ioreq->req.sector_number);
switch (ioreq->req.operation) {
case BLKIF_OP_READ:
- ioreq->prot = PROT_WRITE; /* to memory */
- break;
+ ioreq->prot = PROT_WRITE; /* to memory */
+ break;
case BLKIF_OP_WRITE_BARRIER:
if (!ioreq->req.nr_segments) {
ioreq->presync = 1;
return 0;
}
- if (!syncwrite)
- ioreq->presync = ioreq->postsync = 1;
- /* fall through */
+ if (!syncwrite) {
+ ioreq->presync = ioreq->postsync = 1;
+ }
+ /* fall through */
case BLKIF_OP_WRITE:
- ioreq->prot = PROT_READ; /* from memory */
- if (syncwrite)
- ioreq->postsync = 1;
- break;
+ ioreq->prot = PROT_READ; /* from memory */
+ if (syncwrite) {
+ ioreq->postsync = 1;
+ }
+ break;
default:
- xen_be_printf(&blkdev->xendev, 0, "error: unknown operation (%d)\n",
- ioreq->req.operation);
- goto err;
+ xen_be_printf(&blkdev->xendev, 0, "error: unknown operation (%d)\n",
+ ioreq->req.operation);
+ goto err;
};
if (ioreq->req.operation != BLKIF_OP_READ && blkdev->mode[0] != 'w') {
@@ -206,29 +209,29 @@ static int ioreq_parse(struct ioreq *ioreq)
ioreq->start = ioreq->req.sector_number * blkdev->file_blk;
for (i = 0; i < ioreq->req.nr_segments; i++) {
- if (i == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
- xen_be_printf(&blkdev->xendev, 0, "error: nr_segments too big\n");
- goto err;
- }
- if (ioreq->req.seg[i].first_sect > ioreq->req.seg[i].last_sect) {
- xen_be_printf(&blkdev->xendev, 0, "error: first > last sector\n");
- goto err;
- }
- if (ioreq->req.seg[i].last_sect * BLOCK_SIZE >= XC_PAGE_SIZE) {
- xen_be_printf(&blkdev->xendev, 0, "error: page crossing\n");
- goto err;
- }
-
- ioreq->domids[i] = blkdev->xendev.dom;
- ioreq->refs[i] = ioreq->req.seg[i].gref;
-
- mem = ioreq->req.seg[i].first_sect * blkdev->file_blk;
- len = (ioreq->req.seg[i].last_sect - ioreq->req.seg[i].first_sect + 1) * blkdev->file_blk;
+ if (i == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+ xen_be_printf(&blkdev->xendev, 0, "error: nr_segments too big\n");
+ goto err;
+ }
+ if (ioreq->req.seg[i].first_sect > ioreq->req.seg[i].last_sect) {
+ xen_be_printf(&blkdev->xendev, 0, "error: first > last sector\n");
+ goto err;
+ }
+ if (ioreq->req.seg[i].last_sect * BLOCK_SIZE >= XC_PAGE_SIZE) {
+ xen_be_printf(&blkdev->xendev, 0, "error: page crossing\n");
+ goto err;
+ }
+
+ ioreq->domids[i] = blkdev->xendev.dom;
+ ioreq->refs[i] = ioreq->req.seg[i].gref;
+
+ mem = ioreq->req.seg[i].first_sect * blkdev->file_blk;
+ len = (ioreq->req.seg[i].last_sect - ioreq->req.seg[i].first_sect + 1) * blkdev->file_blk;
qemu_iovec_add(&ioreq->v, (void*)mem, len);
}
if (ioreq->start + ioreq->v.size > blkdev->file_size) {
- xen_be_printf(&blkdev->xendev, 0, "error: access beyond end of file\n");
- goto err;
+ xen_be_printf(&blkdev->xendev, 0, "error: access beyond end of file\n");
+ goto err;
}
return 0;
@@ -242,26 +245,31 @@ static void ioreq_unmap(struct ioreq *ioreq)
int gnt = ioreq->blkdev->xendev.gnttabdev;
int i;
- if (ioreq->v.niov == 0)
+ if (ioreq->v.niov == 0) {
return;
+ }
if (batch_maps) {
- if (!ioreq->pages)
- return;
- if (xc_gnttab_munmap(gnt, ioreq->pages, ioreq->v.niov) != 0)
- xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n",
- strerror(errno));
- ioreq->blkdev->cnt_map -= ioreq->v.niov;
- ioreq->pages = NULL;
+ if (!ioreq->pages) {
+ return;
+ }
+ if (xc_gnttab_munmap(gnt, ioreq->pages, ioreq->v.niov) != 0) {
+ xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n",
+ strerror(errno));
+ }
+ ioreq->blkdev->cnt_map -= ioreq->v.niov;
+ ioreq->pages = NULL;
} else {
- for (i = 0; i < ioreq->v.niov; i++) {
- if (!ioreq->page[i])
- continue;
- if (xc_gnttab_munmap(gnt, ioreq->page[i], 1) != 0)
- xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n",
- strerror(errno));
- ioreq->blkdev->cnt_map--;
- ioreq->page[i] = NULL;
- }
+ for (i = 0; i < ioreq->v.niov; i++) {
+ if (!ioreq->page[i]) {
+ continue;
+ }
+ if (xc_gnttab_munmap(gnt, ioreq->page[i], 1) != 0) {
+ xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n",
+ strerror(errno));
+ }
+ ioreq->blkdev->cnt_map--;
+ ioreq->page[i] = NULL;
+ }
}
}
@@ -270,35 +278,37 @@ static int ioreq_map(struct ioreq *ioreq)
int gnt = ioreq->blkdev->xendev.gnttabdev;
int i;
- if (ioreq->v.niov == 0)
+ if (ioreq->v.niov == 0) {
return 0;
+ }
if (batch_maps) {
- ioreq->pages = xc_gnttab_map_grant_refs
- (gnt, ioreq->v.niov, ioreq->domids, ioreq->refs, ioreq->prot);
- if (ioreq->pages == NULL) {
- xen_be_printf(&ioreq->blkdev->xendev, 0,
- "can't map %d grant refs (%s, %d maps)\n",
- ioreq->v.niov, strerror(errno), ioreq->blkdev->cnt_map);
- return -1;
- }
- for (i = 0; i < ioreq->v.niov; i++)
- ioreq->v.iov[i].iov_base = ioreq->pages + i * XC_PAGE_SIZE +
- (uintptr_t)ioreq->v.iov[i].iov_base;
- ioreq->blkdev->cnt_map += ioreq->v.niov;
+ ioreq->pages = xc_gnttab_map_grant_refs
+ (gnt, ioreq->v.niov, ioreq->domids, ioreq->refs, ioreq->prot);
+ if (ioreq->pages == NULL) {
+ xen_be_printf(&ioreq->blkdev->xendev, 0,
+ "can't map %d grant refs (%s, %d maps)\n",
+ ioreq->v.niov, strerror(errno), ioreq->blkdev->cnt_map);
+ return -1;
+ }
+ for (i = 0; i < ioreq->v.niov; i++) {
+ ioreq->v.iov[i].iov_base = ioreq->pages + i * XC_PAGE_SIZE +
+ (uintptr_t)ioreq->v.iov[i].iov_base;
+ }
+ ioreq->blkdev->cnt_map += ioreq->v.niov;
} else {
- for (i = 0; i < ioreq->v.niov; i++) {
- ioreq->page[i] = xc_gnttab_map_grant_ref
- (gnt, ioreq->domids[i], ioreq->refs[i], ioreq->prot);
- if (ioreq->page[i] == NULL) {
- xen_be_printf(&ioreq->blkdev->xendev, 0,
- "can't map grant ref %d (%s, %d maps)\n",
- ioreq->refs[i], strerror(errno), ioreq->blkdev->cnt_map);
- ioreq_unmap(ioreq);
- return -1;
- }
- ioreq->v.iov[i].iov_base = ioreq->page[i] + (uintptr_t)ioreq->v.iov[i].iov_base;
- ioreq->blkdev->cnt_map++;
- }
+ for (i = 0; i < ioreq->v.niov; i++) {
+ ioreq->page[i] = xc_gnttab_map_grant_ref
+ (gnt, ioreq->domids[i], ioreq->refs[i], ioreq->prot);
+ if (ioreq->page[i] == NULL) {
+ xen_be_printf(&ioreq->blkdev->xendev, 0,
+ "can't map grant ref %d (%s, %d maps)\n",
+ ioreq->refs[i], strerror(errno), ioreq->blkdev->cnt_map);
+ ioreq_unmap(ioreq);
+ return -1;
+ }
+ ioreq->v.iov[i].iov_base = ioreq->page[i] + (uintptr_t)ioreq->v.iov[i].iov_base;
+ ioreq->blkdev->cnt_map++;
+ }
}
return 0;
}
@@ -309,54 +319,58 @@ static int ioreq_runio_qemu_sync(struct ioreq *ioreq)
int i, rc, len = 0;
off_t pos;
- if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1)
- goto err_no_map;
- if (ioreq->presync)
- bdrv_flush(blkdev->bs);
+ if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) {
+ goto err_no_map;
+ }
+ if (ioreq->presync) {
+ bdrv_flush(blkdev->bs);
+ }
switch (ioreq->req.operation) {
case BLKIF_OP_READ:
- pos = ioreq->start;
- for (i = 0; i < ioreq->v.niov; i++) {
- rc = bdrv_read(blkdev->bs, pos / BLOCK_SIZE,
- ioreq->v.iov[i].iov_base,
- ioreq->v.iov[i].iov_len / BLOCK_SIZE);
- if (rc != 0) {
- xen_be_printf(&blkdev->xendev, 0, "rd I/O error (%p, len %zd)\n",
- ioreq->v.iov[i].iov_base,
- ioreq->v.iov[i].iov_len);
- goto err;
- }
- len += ioreq->v.iov[i].iov_len;
- pos += ioreq->v.iov[i].iov_len;
- }
- break;
+ pos = ioreq->start;
+ for (i = 0; i < ioreq->v.niov; i++) {
+ rc = bdrv_read(blkdev->bs, pos / BLOCK_SIZE,
+ ioreq->v.iov[i].iov_base,
+ ioreq->v.iov[i].iov_len / BLOCK_SIZE);
+ if (rc != 0) {
+ xen_be_printf(&blkdev->xendev, 0, "rd I/O error (%p, len %zd)\n",
+ ioreq->v.iov[i].iov_base,
+ ioreq->v.iov[i].iov_len);
+ goto err;
+ }
+ len += ioreq->v.iov[i].iov_len;
+ pos += ioreq->v.iov[i].iov_len;
+ }
+ break;
case BLKIF_OP_WRITE:
case BLKIF_OP_WRITE_BARRIER:
- if (!ioreq->req.nr_segments)
+ if (!ioreq->req.nr_segments) {
break;
- pos = ioreq->start;
- for (i = 0; i < ioreq->v.niov; i++) {
- rc = bdrv_write(blkdev->bs, pos / BLOCK_SIZE,
- ioreq->v.iov[i].iov_base,
- ioreq->v.iov[i].iov_len / BLOCK_SIZE);
- if (rc != 0) {
- xen_be_printf(&blkdev->xendev, 0, "wr I/O error (%p, len %zd)\n",
- ioreq->v.iov[i].iov_base,
- ioreq->v.iov[i].iov_len);
- goto err;
- }
- len += ioreq->v.iov[i].iov_len;
- pos += ioreq->v.iov[i].iov_len;
- }
- break;
+ }
+ pos = ioreq->start;
+ for (i = 0; i < ioreq->v.niov; i++) {
+ rc = bdrv_write(blkdev->bs, pos / BLOCK_SIZE,
+ ioreq->v.iov[i].iov_base,
+ ioreq->v.iov[i].iov_len / BLOCK_SIZE);
+ if (rc != 0) {
+ xen_be_printf(&blkdev->xendev, 0, "wr I/O error (%p, len %zd)\n",
+ ioreq->v.iov[i].iov_base,
+ ioreq->v.iov[i].iov_len);
+ goto err;
+ }
+ len += ioreq->v.iov[i].iov_len;
+ pos += ioreq->v.iov[i].iov_len;
+ }
+ break;
default:
- /* unknown operation (shouldn't happen -- parse catches this) */
- goto err;
+ /* unknown operation (shouldn't happen -- parse catches this) */
+ goto err;
}
- if (ioreq->postsync)
- bdrv_flush(blkdev->bs);
+ if (ioreq->postsync) {
+ bdrv_flush(blkdev->bs);
+ }
ioreq->status = BLKIF_RSP_OKAY;
ioreq_unmap(ioreq);
@@ -382,8 +396,9 @@ static void qemu_aio_complete(void *opaque, int ret)
}
ioreq->aio_inflight--;
- if (ioreq->aio_inflight > 0)
+ if (ioreq->aio_inflight > 0) {
return;
+ }
ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
ioreq_unmap(ioreq);
@@ -395,12 +410,14 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
{
struct XenBlkDev *blkdev = ioreq->blkdev;
- if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1)
- goto err_no_map;
+ if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) {
+ goto err_no_map;
+ }
ioreq->aio_inflight++;
- if (ioreq->presync)
- bdrv_flush(blkdev->bs); /* FIXME: aio_flush() ??? */
+ if (ioreq->presync) {
+ bdrv_flush(blkdev->bs); /* FIXME: aio_flush() ??? */
+ }
switch (ioreq->req.operation) {
case BLKIF_OP_READ:
@@ -408,23 +425,25 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
bdrv_aio_readv(blkdev->bs, ioreq->start / BLOCK_SIZE,
&ioreq->v, ioreq->v.size / BLOCK_SIZE,
qemu_aio_complete, ioreq);
- break;
+ break;
case BLKIF_OP_WRITE:
case BLKIF_OP_WRITE_BARRIER:
- if (!ioreq->req.nr_segments)
+ if (!ioreq->req.nr_segments) {
break;
+ }
ioreq->aio_inflight++;
bdrv_aio_writev(blkdev->bs, ioreq->start / BLOCK_SIZE,
&ioreq->v, ioreq->v.size / BLOCK_SIZE,
qemu_aio_complete, ioreq);
- break;
+ break;
default:
- /* unknown operation (shouldn't happen -- parse catches this) */
- goto err;
+ /* unknown operation (shouldn't happen -- parse catches this) */
+ goto err;
}
- if (ioreq->postsync)
- bdrv_flush(blkdev->bs); /* FIXME: aio_flush() ??? */
+ if (ioreq->postsync) {
+ bdrv_flush(blkdev->bs); /* FIXME: aio_flush() ??? */
+ }
qemu_aio_complete(ioreq, 0);
return 0;
@@ -452,36 +471,37 @@ static int blk_send_response_one(struct ioreq *ioreq)
/* Place on the response ring for the relevant domain. */
switch (blkdev->protocol) {
case BLKIF_PROTOCOL_NATIVE:
- dst = RING_GET_RESPONSE(&blkdev->rings.native, blkdev->rings.native.rsp_prod_pvt);
- break;
+ dst = RING_GET_RESPONSE(&blkdev->rings.native, blkdev->rings.native.rsp_prod_pvt);
+ break;
case BLKIF_PROTOCOL_X86_32:
dst = RING_GET_RESPONSE(&blkdev->rings.x86_32_part,
blkdev->rings.x86_32_part.rsp_prod_pvt);
- break;
+ break;
case BLKIF_PROTOCOL_X86_64:
dst = RING_GET_RESPONSE(&blkdev->rings.x86_64_part,
blkdev->rings.x86_64_part.rsp_prod_pvt);
- break;
+ break;
default:
- dst = NULL;
+ dst = NULL;
}
memcpy(dst, &resp, sizeof(resp));
blkdev->rings.common.rsp_prod_pvt++;
RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blkdev->rings.common, send_notify);
if (blkdev->rings.common.rsp_prod_pvt == blkdev->rings.common.req_cons) {
- /*
- * Tail check for pending requests. Allows frontend to avoid
- * notifications if requests are already in flight (lower
- * overheads and promotes batching).
- */
- RING_FINAL_CHECK_FOR_REQUESTS(&blkdev->rings.common, have_requests);
+ /*
+ * Tail check for pending requests. Allows frontend to avoid
+ * notifications if requests are already in flight (lower
+ * overheads and promotes batching).
+ */
+ RING_FINAL_CHECK_FOR_REQUESTS(&blkdev->rings.common, have_requests);
} else if (RING_HAS_UNCONSUMED_REQUESTS(&blkdev->rings.common)) {
- have_requests = 1;
+ have_requests = 1;
}
- if (have_requests)
- blkdev->more_work++;
+ if (have_requests) {
+ blkdev->more_work++;
+ }
return send_notify;
}
@@ -493,28 +513,29 @@ static void blk_send_response_all(struct XenBlkDev *blkdev)
while (!QLIST_EMPTY(&blkdev->finished)) {
ioreq = QLIST_FIRST(&blkdev->finished);
- send_notify += blk_send_response_one(ioreq);
- ioreq_release(ioreq);
+ send_notify += blk_send_response_one(ioreq);
+ ioreq_release(ioreq);
+ }
+ if (send_notify) {
+ xen_be_send_notify(&blkdev->xendev);
}
- if (send_notify)
- xen_be_send_notify(&blkdev->xendev);
}
static int blk_get_request(struct XenBlkDev *blkdev, struct ioreq *ioreq, RING_IDX rc)
{
switch (blkdev->protocol) {
case BLKIF_PROTOCOL_NATIVE:
- memcpy(&ioreq->req, RING_GET_REQUEST(&blkdev->rings.native, rc),
- sizeof(ioreq->req));
- break;
+ memcpy(&ioreq->req, RING_GET_REQUEST(&blkdev->rings.native, rc),
+ sizeof(ioreq->req));
+ break;
case BLKIF_PROTOCOL_X86_32:
blkif_get_x86_32_req(&ioreq->req,
RING_GET_REQUEST(&blkdev->rings.x86_32_part, rc));
- break;
+ break;
case BLKIF_PROTOCOL_X86_64:
blkif_get_x86_64_req(&ioreq->req,
RING_GET_REQUEST(&blkdev->rings.x86_64_part, rc));
- break;
+ break;
}
return 0;
}
@@ -530,12 +551,14 @@ static void blk_handle_requests(struct XenBlkDev *blkdev)
rp = blkdev->rings.common.sring->req_prod;
xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
- if (use_aio)
+ if (use_aio) {
blk_send_response_all(blkdev);
+ }
while (rc != rp) {
/* pull request from ring */
- if (RING_REQUEST_CONS_OVERFLOW(&blkdev->rings.common, rc))
+ if (RING_REQUEST_CONS_OVERFLOW(&blkdev->rings.common, rc)) {
break;
+ }
ioreq = ioreq_start(blkdev);
if (ioreq == NULL) {
blkdev->more_work++;
@@ -546,8 +569,9 @@ static void blk_handle_requests(struct XenBlkDev *blkdev)
/* parse them */
if (ioreq_parse(ioreq) != 0) {
- if (blk_send_response_one(ioreq))
+ if (blk_send_response_one(ioreq)) {
xen_be_send_notify(&blkdev->xendev);
+ }
ioreq_release(ioreq);
continue;
}
@@ -560,11 +584,13 @@ static void blk_handle_requests(struct XenBlkDev *blkdev)
ioreq_runio_qemu_sync(ioreq);
}
}
- if (!use_aio)
+ if (!use_aio) {
blk_send_response_all(blkdev);
+ }
- if (blkdev->more_work && blkdev->requests_inflight < max_requests)
+ if (blkdev->more_work && blkdev->requests_inflight < max_requests) {
qemu_bh_schedule(blkdev->bh);
+ }
}
/* ------------------------------------------------------------- */
@@ -583,8 +609,9 @@ static void blk_alloc(struct XenDevice *xendev)
QLIST_INIT(&blkdev->finished);
QLIST_INIT(&blkdev->freelist);
blkdev->bh = qemu_bh_new(blk_bh, blkdev);
- if (xen_mode != XEN_EMULATE)
+ if (xen_mode != XEN_EMULATE) {
batch_maps = 1;
+ }
}
static int blk_init(struct XenDevice *xendev)
@@ -595,44 +622,50 @@ static int blk_init(struct XenDevice *xendev)
/* read xenstore entries */
if (blkdev->params == NULL) {
- blkdev->params = xenstore_read_be_str(&blkdev->xendev, "params");
+ blkdev->params = xenstore_read_be_str(&blkdev->xendev, "params");
h = strchr(blkdev->params, ':');
- if (h != NULL) {
- blkdev->fileproto = blkdev->params;
- blkdev->filename = h+1;
- *h = 0;
- } else {
- blkdev->fileproto = "<unset>";
- blkdev->filename = blkdev->params;
- }
- }
- if (blkdev->mode == NULL)
- blkdev->mode = xenstore_read_be_str(&blkdev->xendev, "mode");
- if (blkdev->type == NULL)
- blkdev->type = xenstore_read_be_str(&blkdev->xendev, "type");
- if (blkdev->dev == NULL)
- blkdev->dev = xenstore_read_be_str(&blkdev->xendev, "dev");
- if (blkdev->devtype == NULL)
- blkdev->devtype = xenstore_read_be_str(&blkdev->xendev, "device-type");
+ if (h != NULL) {
+ blkdev->fileproto = blkdev->params;
+ blkdev->filename = h+1;
+ *h = 0;
+ } else {
+ blkdev->fileproto = "<unset>";
+ blkdev->filename = blkdev->params;
+ }
+ }
+ if (blkdev->mode == NULL) {
+ blkdev->mode = xenstore_read_be_str(&blkdev->xendev, "mode");
+ }
+ if (blkdev->type == NULL) {
+ blkdev->type = xenstore_read_be_str(&blkdev->xendev, "type");
+ }
+ if (blkdev->dev == NULL) {
+ blkdev->dev = xenstore_read_be_str(&blkdev->xendev, "dev");
+ }
+ if (blkdev->devtype == NULL) {
+ blkdev->devtype = xenstore_read_be_str(&blkdev->xendev, "device-type");
+ }
/* do we have all we need? */
if (blkdev->params == NULL ||
- blkdev->mode == NULL ||
- blkdev->type == NULL ||
- blkdev->dev == NULL)
- return -1;
+ blkdev->mode == NULL ||
+ blkdev->type == NULL ||
+ blkdev->dev == NULL) {
+ return -1;
+ }
/* read-only ? */
if (strcmp(blkdev->mode, "w") == 0) {
- qflags = BDRV_O_RDWR;
+ qflags = BDRV_O_RDWR;
} else {
- qflags = 0;
- info |= VDISK_READONLY;
+ qflags = 0;
+ info |= VDISK_READONLY;
}
/* cdrom ? */
- if (blkdev->devtype && !strcmp(blkdev->devtype, "cdrom"))
- info |= VDISK_CDROM;
+ if (blkdev->devtype && !strcmp(blkdev->devtype, "cdrom")) {
+ info |= VDISK_CDROM;
+ }
/* init qemu block driver */
index = (blkdev->xendev.dev - 202 * 256) / 16;
@@ -649,7 +682,7 @@ static int blk_init(struct XenDevice *xendev)
} else {
/* setup via qemu cmdline -> already setup for us */
xen_be_printf(&blkdev->xendev, 2, "get configured bdrv (cmdline setup)\n");
- blkdev->bs = blkdev->dinfo->bdrv;
+ blkdev->bs = blkdev->dinfo->bdrv;
}
blkdev->file_blk = BLOCK_SIZE;
blkdev->file_size = bdrv_getlength(blkdev->bs);
@@ -657,21 +690,21 @@ static int blk_init(struct XenDevice *xendev)
xen_be_printf(&blkdev->xendev, 1, "bdrv_getlength: %d (%s) | drv %s\n",
(int)blkdev->file_size, strerror(-blkdev->file_size),
blkdev->bs->drv ? blkdev->bs->drv->format_name : "-");
- blkdev->file_size = 0;
+ blkdev->file_size = 0;
}
have_barriers = blkdev->bs->drv && blkdev->bs->drv->bdrv_flush ? 1 : 0;
xen_be_printf(xendev, 1, "type \"%s\", fileproto \"%s\", filename \"%s\","
- " size %" PRId64 " (%" PRId64 " MB)\n",
- blkdev->type, blkdev->fileproto, blkdev->filename,
- blkdev->file_size, blkdev->file_size >> 20);
+ " size %" PRId64 " (%" PRId64 " MB)\n",
+ blkdev->type, blkdev->fileproto, blkdev->filename,
+ blkdev->file_size, blkdev->file_size >> 20);
/* fill info */
xenstore_write_be_int(&blkdev->xendev, "feature-barrier", have_barriers);
xenstore_write_be_int(&blkdev->xendev, "info", info);
xenstore_write_be_int(&blkdev->xendev, "sector-size", blkdev->file_blk);
xenstore_write_be_int(&blkdev->xendev, "sectors",
- blkdev->file_size / blkdev->file_blk);
+ blkdev->file_size / blkdev->file_blk);
return 0;
}
@@ -679,57 +712,62 @@ static int blk_connect(struct XenDevice *xendev)
{
struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
- if (xenstore_read_fe_int(&blkdev->xendev, "ring-ref", &blkdev->ring_ref) == -1)
- return -1;
+ if (xenstore_read_fe_int(&blkdev->xendev, "ring-ref", &blkdev->ring_ref) == -1) {
+ return -1;
+ }
if (xenstore_read_fe_int(&blkdev->xendev, "event-channel",
- &blkdev->xendev.remote_port) == -1)
- return -1;
+ &blkdev->xendev.remote_port) == -1) {
+ return -1;
+ }
blkdev->protocol = BLKIF_PROTOCOL_NATIVE;
if (blkdev->xendev.protocol) {
- if (strcmp(blkdev->xendev.protocol, XEN_IO_PROTO_ABI_X86_32) == 0)
+ if (strcmp(blkdev->xendev.protocol, XEN_IO_PROTO_ABI_X86_32) == 0) {
blkdev->protocol = BLKIF_PROTOCOL_X86_32;
- if (strcmp(blkdev->xendev.protocol, XEN_IO_PROTO_ABI_X86_64) == 0)
+ }
+ if (strcmp(blkdev->xendev.protocol, XEN_IO_PROTO_ABI_X86_64) == 0) {
blkdev->protocol = BLKIF_PROTOCOL_X86_64;
+ }
}
blkdev->sring = xc_gnttab_map_grant_ref(blkdev->xendev.gnttabdev,
- blkdev->xendev.dom,
- blkdev->ring_ref,
- PROT_READ | PROT_WRITE);
- if (!blkdev->sring)
- return -1;
+ blkdev->xendev.dom,
+ blkdev->ring_ref,
+ PROT_READ | PROT_WRITE);
+ if (!blkdev->sring) {
+ return -1;
+ }
blkdev->cnt_map++;
switch (blkdev->protocol) {
case BLKIF_PROTOCOL_NATIVE:
{
- blkif_sring_t *sring_native = blkdev->sring;
- BACK_RING_INIT(&blkdev->rings.native, sring_native, XC_PAGE_SIZE);
- break;
+ blkif_sring_t *sring_native = blkdev->sring;
+ BACK_RING_INIT(&blkdev->rings.native, sring_native, XC_PAGE_SIZE);
+ break;
}
case BLKIF_PROTOCOL_X86_32:
{
- blkif_x86_32_sring_t *sring_x86_32 = blkdev->sring;
+ blkif_x86_32_sring_t *sring_x86_32 = blkdev->sring;
BACK_RING_INIT(&blkdev->rings.x86_32_part, sring_x86_32, XC_PAGE_SIZE);
- break;
+ break;
}
case BLKIF_PROTOCOL_X86_64:
{
- blkif_x86_64_sring_t *sring_x86_64 = blkdev->sring;
+ blkif_x86_64_sring_t *sring_x86_64 = blkdev->sring;
BACK_RING_INIT(&blkdev->rings.x86_64_part, sring_x86_64, XC_PAGE_SIZE);
- break;
+ break;
}
}
xen_be_bind_evtchn(&blkdev->xendev);
xen_be_printf(&blkdev->xendev, 1, "ok: proto %s, ring-ref %d, "
- "remote port %d, local port %d\n",
- blkdev->xendev.protocol, blkdev->ring_ref,
- blkdev->xendev.remote_port, blkdev->xendev.local_port);
+ "remote port %d, local port %d\n",
+ blkdev->xendev.protocol, blkdev->ring_ref,
+ blkdev->xendev.remote_port, blkdev->xendev.local_port);
return 0;
}
@@ -743,14 +781,14 @@ static void blk_disconnect(struct XenDevice *xendev)
bdrv_close(blkdev->bs);
bdrv_delete(blkdev->bs);
}
- blkdev->bs = NULL;
+ blkdev->bs = NULL;
}
xen_be_unbind_evtchn(&blkdev->xendev);
if (blkdev->sring) {
- xc_gnttab_munmap(blkdev->xendev.gnttabdev, blkdev->sring, 1);
- blkdev->cnt_map--;
- blkdev->sring = NULL;
+ xc_gnttab_munmap(blkdev->xendev.gnttabdev, blkdev->sring, 1);
+ blkdev->cnt_map--;
+ blkdev->sring = NULL;
}
}
@@ -760,10 +798,10 @@ static int blk_free(struct XenDevice *xendev)
struct ioreq *ioreq;
while (!QLIST_EMPTY(&blkdev->freelist)) {
- ioreq = QLIST_FIRST(&blkdev->freelist);
+ ioreq = QLIST_FIRST(&blkdev->freelist);
QLIST_REMOVE(ioreq, list);
qemu_iovec_destroy(&ioreq->v);
- qemu_free(ioreq);
+ qemu_free(ioreq);
}
qemu_free(blkdev->params);
diff --git a/hw/xen_nic.c b/hw/xen_nic.c
index 08055b8..ff86491 100644
--- a/hw/xen_nic.c
+++ b/hw/xen_nic.c
@@ -74,20 +74,23 @@ static void net_tx_response(struct XenNetDev *netdev, netif_tx_request_t *txp, i
resp->status = st;
#if 0
- if (txp->flags & NETTXF_extra_info)
- RING_GET_RESPONSE(&netdev->tx_ring, ++i)->status = NETIF_RSP_NULL;
+ if (txp->flags & NETTXF_extra_info) {
+ RING_GET_RESPONSE(&netdev->tx_ring, ++i)->status = NETIF_RSP_NULL;
+ }
#endif
netdev->tx_ring.rsp_prod_pvt = ++i;
RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netdev->tx_ring, notify);
- if (notify)
- xen_be_send_notify(&netdev->xendev);
+ if (notify) {
+ xen_be_send_notify(&netdev->xendev);
+ }
if (i == netdev->tx_ring.req_cons) {
- int more_to_do;
- RING_FINAL_CHECK_FOR_REQUESTS(&netdev->tx_ring, more_to_do);
- if (more_to_do)
- netdev->tx_work++;
+ int more_to_do;
+ RING_FINAL_CHECK_FOR_REQUESTS(&netdev->tx_ring, more_to_do);
+ if (more_to_do) {
+ netdev->tx_work++;
+ }
}
}
@@ -101,10 +104,11 @@ static void net_tx_error(struct XenNetDev *netdev, netif_tx_request_t *txp, RING
RING_IDX cons = netdev->tx_ring.req_cons;
do {
- make_tx_response(netif, txp, NETIF_RSP_ERROR);
- if (cons >= end)
- break;
- txp = RING_GET_REQUEST(&netdev->tx_ring, cons++);
+ make_tx_response(netif, txp, NETIF_RSP_ERROR);
+ if (cons >= end) {
+ break;
+ }
+ txp = RING_GET_REQUEST(&netdev->tx_ring, cons++);
} while (1);
netdev->tx_ring.req_cons = cons;
netif_schedule_work(netif);
@@ -122,75 +126,78 @@ static void net_tx_packets(struct XenNetDev *netdev)
void *tmpbuf = NULL;
for (;;) {
- rc = netdev->tx_ring.req_cons;
- rp = netdev->tx_ring.sring->req_prod;
- xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
+ rc = netdev->tx_ring.req_cons;
+ rp = netdev->tx_ring.sring->req_prod;
+ xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
- while ((rc != rp)) {
- if (RING_REQUEST_CONS_OVERFLOW(&netdev->tx_ring, rc))
- break;
- memcpy(&txreq, RING_GET_REQUEST(&netdev->tx_ring, rc), sizeof(txreq));
- netdev->tx_ring.req_cons = ++rc;
+ while ((rc != rp)) {
+ if (RING_REQUEST_CONS_OVERFLOW(&netdev->tx_ring, rc)) {
+ break;
+ }
+ memcpy(&txreq, RING_GET_REQUEST(&netdev->tx_ring, rc), sizeof(txreq));
+ netdev->tx_ring.req_cons = ++rc;
#if 1
- /* should not happen in theory, we don't announce the *
- * feature-{sg,gso,whatelse} flags in xenstore (yet?) */
- if (txreq.flags & NETTXF_extra_info) {
- xen_be_printf(&netdev->xendev, 0, "FIXME: extra info flag\n");
- net_tx_error(netdev, &txreq, rc);
- continue;
- }
- if (txreq.flags & NETTXF_more_data) {
- xen_be_printf(&netdev->xendev, 0, "FIXME: more data flag\n");
- net_tx_error(netdev, &txreq, rc);
- continue;
- }
+ /* should not happen in theory, we don't announce the *
+ * feature-{sg,gso,whatelse} flags in xenstore (yet?) */
+ if (txreq.flags & NETTXF_extra_info) {
+ xen_be_printf(&netdev->xendev, 0, "FIXME: extra info flag\n");
+ net_tx_error(netdev, &txreq, rc);
+ continue;
+ }
+ if (txreq.flags & NETTXF_more_data) {
+ xen_be_printf(&netdev->xendev, 0, "FIXME: more data flag\n");
+ net_tx_error(netdev, &txreq, rc);
+ continue;
+ }
#endif
- if (txreq.size < 14) {
- xen_be_printf(&netdev->xendev, 0, "bad packet size: %d\n", txreq.size);
- net_tx_error(netdev, &txreq, rc);
- continue;
- }
-
- if ((txreq.offset + txreq.size) > XC_PAGE_SIZE) {
- xen_be_printf(&netdev->xendev, 0, "error: page crossing\n");
- net_tx_error(netdev, &txreq, rc);
- continue;
- }
-
- xen_be_printf(&netdev->xendev, 3, "tx packet ref %d, off %d, len %d, flags 0x%x%s%s%s%s\n",
- txreq.gref, txreq.offset, txreq.size, txreq.flags,
- (txreq.flags & NETTXF_csum_blank) ? " csum_blank" : "",
- (txreq.flags & NETTXF_data_validated) ? " data_validated" : "",
- (txreq.flags & NETTXF_more_data) ? " more_data" : "",
- (txreq.flags & NETTXF_extra_info) ? " extra_info" : "");
-
- page = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
- netdev->xendev.dom,
- txreq.gref, PROT_READ);
- if (page == NULL) {
- xen_be_printf(&netdev->xendev, 0, "error: tx gref dereference failed (%d)\n",
+ if (txreq.size < 14) {
+ xen_be_printf(&netdev->xendev, 0, "bad packet size: %d\n", txreq.size);
+ net_tx_error(netdev, &txreq, rc);
+ continue;
+ }
+
+ if ((txreq.offset + txreq.size) > XC_PAGE_SIZE) {
+ xen_be_printf(&netdev->xendev, 0, "error: page crossing\n");
+ net_tx_error(netdev, &txreq, rc);
+ continue;
+ }
+
+ xen_be_printf(&netdev->xendev, 3, "tx packet ref %d, off %d, len %d, flags 0x%x%s%s%s%s\n",
+ txreq.gref, txreq.offset, txreq.size, txreq.flags,
+ (txreq.flags & NETTXF_csum_blank) ? " csum_blank" : "",
+ (txreq.flags & NETTXF_data_validated) ? " data_validated" : "",
+ (txreq.flags & NETTXF_more_data) ? " more_data" : "",
+ (txreq.flags & NETTXF_extra_info) ? " extra_info" : "");
+
+ page = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
+ netdev->xendev.dom,
+ txreq.gref, PROT_READ);
+ if (page == NULL) {
+ xen_be_printf(&netdev->xendev, 0, "error: tx gref dereference failed (%d)\n",
txreq.gref);
- net_tx_error(netdev, &txreq, rc);
- continue;
- }
- if (txreq.flags & NETTXF_csum_blank) {
+ net_tx_error(netdev, &txreq, rc);
+ continue;
+ }
+ if (txreq.flags & NETTXF_csum_blank) {
/* have read-only mapping -> can't fill checksum in-place */
- if (!tmpbuf)
+ if (!tmpbuf) {
tmpbuf = qemu_malloc(XC_PAGE_SIZE);
+ }
memcpy(tmpbuf, page + txreq.offset, txreq.size);
- net_checksum_calculate(tmpbuf, txreq.size);
+ net_checksum_calculate(tmpbuf, txreq.size);
qemu_send_packet(&netdev->nic->nc, tmpbuf, txreq.size);
} else {
qemu_send_packet(&netdev->nic->nc, page + txreq.offset, txreq.size);
}
- xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1);
- net_tx_response(netdev, &txreq, NETIF_RSP_OKAY);
- }
- if (!netdev->tx_work)
- break;
- netdev->tx_work = 0;
+ xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1);
+ net_tx_response(netdev, &txreq, NETIF_RSP_OKAY);
+ }
+ if (!netdev->tx_work) {
+ break;
+ }
+ netdev->tx_work = 0;
}
qemu_free(tmpbuf);
}
@@ -198,9 +205,9 @@ static void net_tx_packets(struct XenNetDev *netdev)
/* ------------------------------------------------------------- */
static void net_rx_response(struct XenNetDev *netdev,
- netif_rx_request_t *req, int8_t st,
- uint16_t offset, uint16_t size,
- uint16_t flags)
+ netif_rx_request_t *req, int8_t st,
+ uint16_t offset, uint16_t size,
+ uint16_t flags)
{
RING_IDX i = netdev->rx_ring.rsp_prod_pvt;
netif_rx_response_t *resp;
@@ -211,16 +218,18 @@ static void net_rx_response(struct XenNetDev *netdev,
resp->flags = flags;
resp->id = req->id;
resp->status = (int16_t)size;
- if (st < 0)
- resp->status = (int16_t)st;
+ if (st < 0) {
+ resp->status = (int16_t)st;
+ }
xen_be_printf(&netdev->xendev, 3, "rx response: idx %d, status %d, flags 0x%x\n",
- i, resp->status, resp->flags);
+ i, resp->status, resp->flags);
netdev->rx_ring.rsp_prod_pvt = ++i;
RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netdev->rx_ring, notify);
- if (notify)
- xen_be_send_notify(&netdev->xendev);
+ if (notify) {
+ xen_be_send_notify(&netdev->xendev);
+ }
}
#define NET_IP_ALIGN 2
@@ -230,17 +239,18 @@ static int net_rx_ok(VLANClientState *nc)
struct XenNetDev *netdev = DO_UPCAST(NICState, nc, nc)->opaque;
RING_IDX rc, rp;
- if (netdev->xendev.be_state != XenbusStateConnected)
- return 0;
+ if (netdev->xendev.be_state != XenbusStateConnected) {
+ return 0;
+ }
rc = netdev->rx_ring.req_cons;
rp = netdev->rx_ring.sring->req_prod;
xen_rmb();
if (rc == rp || RING_REQUEST_CONS_OVERFLOW(&netdev->rx_ring, rc)) {
- xen_be_printf(&netdev->xendev, 2, "%s: no rx buffers (%d/%d)\n",
- __FUNCTION__, rc, rp);
- return 0;
+ xen_be_printf(&netdev->xendev, 2, "%s: no rx buffers (%d/%d)\n",
+ __FUNCTION__, rc, rp);
+ return 0;
}
return 1;
}
@@ -252,34 +262,35 @@ static ssize_t net_rx_packet(VLANClientState *nc, const uint8_t *buf, size_t siz
RING_IDX rc, rp;
void *page;
- if (netdev->xendev.be_state != XenbusStateConnected)
- return -1;
+ if (netdev->xendev.be_state != XenbusStateConnected) {
+ return -1;
+ }
rc = netdev->rx_ring.req_cons;
rp = netdev->rx_ring.sring->req_prod;
xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
if (rc == rp || RING_REQUEST_CONS_OVERFLOW(&netdev->rx_ring, rc)) {
- xen_be_printf(&netdev->xendev, 2, "no buffer, drop packet\n");
- return -1;
+ xen_be_printf(&netdev->xendev, 2, "no buffer, drop packet\n");
+ return -1;
}
if (size > XC_PAGE_SIZE - NET_IP_ALIGN) {
- xen_be_printf(&netdev->xendev, 0, "packet too big (%lu > %ld)",
- (unsigned long)size, XC_PAGE_SIZE - NET_IP_ALIGN);
- return -1;
+ xen_be_printf(&netdev->xendev, 0, "packet too big (%lu > %ld)",
+ (unsigned long)size, XC_PAGE_SIZE - NET_IP_ALIGN);
+ return -1;
}
memcpy(&rxreq, RING_GET_REQUEST(&netdev->rx_ring, rc), sizeof(rxreq));
netdev->rx_ring.req_cons = ++rc;
page = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
- netdev->xendev.dom,
- rxreq.gref, PROT_WRITE);
+ netdev->xendev.dom,
+ rxreq.gref, PROT_WRITE);
if (page == NULL) {
- xen_be_printf(&netdev->xendev, 0, "error: rx gref dereference failed (%d)\n",
+ xen_be_printf(&netdev->xendev, 0, "error: rx gref dereference failed (%d)\n",
rxreq.gref);
- net_rx_response(netdev, &rxreq, NETIF_RSP_ERROR, 0, 0, 0);
- return -1;
+ net_rx_response(netdev, &rxreq, NETIF_RSP_ERROR, 0, 0, 0);
+ return -1;
}
memcpy(page + NET_IP_ALIGN, buf, size);
xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1);
@@ -302,15 +313,18 @@ static int net_init(struct XenDevice *xendev)
struct XenNetDev *netdev = container_of(xendev, struct XenNetDev, xendev);
/* read xenstore entries */
- if (netdev->mac == NULL)
- netdev->mac = xenstore_read_be_str(&netdev->xendev, "mac");
+ if (netdev->mac == NULL) {
+ netdev->mac = xenstore_read_be_str(&netdev->xendev, "mac");
+ }
/* do we have all we need? */
- if (netdev->mac == NULL)
- return -1;
+ if (netdev->mac == NULL) {
+ return -1;
+ }
- if (net_parse_macaddr(netdev->conf.macaddr.a, netdev->mac) < 0)
+ if (net_parse_macaddr(netdev->conf.macaddr.a, netdev->mac) < 0) {
return -1;
+ }
netdev->conf.vlan = qemu_find_vlan(netdev->xendev.dev, 1);
netdev->conf.peer = NULL;
@@ -334,41 +348,46 @@ static int net_connect(struct XenDevice *xendev)
int rx_copy;
if (xenstore_read_fe_int(&netdev->xendev, "tx-ring-ref",
- &netdev->tx_ring_ref) == -1)
- return -1;
+ &netdev->tx_ring_ref) == -1) {
+ return -1;
+ }
if (xenstore_read_fe_int(&netdev->xendev, "rx-ring-ref",
- &netdev->rx_ring_ref) == -1)
- return 1;
+ &netdev->rx_ring_ref) == -1) {
+ return 1;
+ }
if (xenstore_read_fe_int(&netdev->xendev, "event-channel",
- &netdev->xendev.remote_port) == -1)
- return -1;
+ &netdev->xendev.remote_port) == -1) {
+ return -1;
+ }
- if (xenstore_read_fe_int(&netdev->xendev, "request-rx-copy", &rx_copy) == -1)
- rx_copy = 0;
+ if (xenstore_read_fe_int(&netdev->xendev, "request-rx-copy", &rx_copy) == -1) {
+ rx_copy = 0;
+ }
if (rx_copy == 0) {
- xen_be_printf(&netdev->xendev, 0, "frontend doesn't support rx-copy.\n");
- return -1;
+ xen_be_printf(&netdev->xendev, 0, "frontend doesn't support rx-copy.\n");
+ return -1;
}
netdev->txs = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
- netdev->xendev.dom,
- netdev->tx_ring_ref,
- PROT_READ | PROT_WRITE);
+ netdev->xendev.dom,
+ netdev->tx_ring_ref,
+ PROT_READ | PROT_WRITE);
netdev->rxs = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
- netdev->xendev.dom,
- netdev->rx_ring_ref,
- PROT_READ | PROT_WRITE);
- if (!netdev->txs || !netdev->rxs)
- return -1;
+ netdev->xendev.dom,
+ netdev->rx_ring_ref,
+ PROT_READ | PROT_WRITE);
+ if (!netdev->txs || !netdev->rxs) {
+ return -1;
+ }
BACK_RING_INIT(&netdev->tx_ring, netdev->txs, XC_PAGE_SIZE);
BACK_RING_INIT(&netdev->rx_ring, netdev->rxs, XC_PAGE_SIZE);
xen_be_bind_evtchn(&netdev->xendev);
xen_be_printf(&netdev->xendev, 1, "ok: tx-ring-ref %d, rx-ring-ref %d, "
- "remote port %d, local port %d\n",
- netdev->tx_ring_ref, netdev->rx_ring_ref,
- netdev->xendev.remote_port, netdev->xendev.local_port);
+ "remote port %d, local port %d\n",
+ netdev->tx_ring_ref, netdev->rx_ring_ref,
+ netdev->xendev.remote_port, netdev->xendev.local_port);
net_tx_packets(netdev);
return 0;
@@ -381,12 +400,12 @@ static void net_disconnect(struct XenDevice *xendev)
xen_be_unbind_evtchn(&netdev->xendev);
if (netdev->txs) {
- xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->txs, 1);
- netdev->txs = NULL;
+ xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->txs, 1);
+ netdev->txs = NULL;
}
if (netdev->rxs) {
- xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->rxs, 1);
- netdev->rxs = NULL;
+ xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->rxs, 1);
+ netdev->rxs = NULL;
}
if (netdev->nic) {
qemu_del_vlan_client(&netdev->nic->nc);
commit 67b724e69e8d65a4ac4355e3673969b5a3f26afd
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Mon Nov 22 15:44:15 2010 +0000
machine, Add default_machine_opts to QEMUMachine.
With this new field, we can specified which accelerator use to run the
machine, if the accelerator is not already specified by either a
configuration file or the command line options.
Currently, the only use will be made in the xenfv machine.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/hw/boards.h b/hw/boards.h
index 6f0f0d7..716fd7b 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -27,6 +27,7 @@ typedef struct QEMUMachine {
no_cdrom:1,
no_sdcard:1;
int is_default;
+ const char *default_machine_opts;
GlobalProperty *compat_props;
struct QEMUMachine *next;
} QEMUMachine;
diff --git a/vl.c b/vl.c
index a44556e..4632469 100644
--- a/vl.c
+++ b/vl.c
@@ -2914,6 +2914,28 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
+ /*
+ * Get the default machine options from the machine if it is not already
+ * specified either by the configuration file or by the command line.
+ */
+ if (machine->default_machine_opts) {
+ QemuOptsList *list = qemu_find_opts("machine");
+ const char *p = NULL;
+
+ if (!QTAILQ_EMPTY(&list->head)) {
+ p = qemu_opt_get(QTAILQ_FIRST(&list->head), "accel");
+ }
+ if (p == NULL) {
+ opts = qemu_opts_parse(qemu_find_opts("machine"),
+ machine->default_machine_opts, 0);
+ if (!opts) {
+ fprintf(stderr, "parse error for machine %s: %s\n",
+ machine->name, machine->default_machine_opts);
+ exit(1);
+ }
+ }
+ }
+
qemu_opts_foreach(qemu_find_opts("device"), default_driver_check, NULL, 0);
qemu_opts_foreach(qemu_find_opts("global"), default_driver_check, NULL, 0);
commit 303d4e865b74402b49f52e975c396c952f063e58
Author: Anthony PERARD <anthony.perard at citrix.com>
Date: Tue Sep 21 20:05:31 2010 +0100
Introduce -machine command option.
This option gives the ability to switch one "accelerator" like kvm, xen
or the default one tcg. We can specify more than one accelerator by
separate them by a colon. QEMU will try each one and use the first whose
works.
So,
./qemu -machine accel=xen:kvm:tcg
which would try Xen support first, then KVM and finally TCG if none of
the other works.
By default, QEMU will use TCG. But we can specify another default in the
global configuration file.
Signed-off-by: Anthony PERARD <anthony.perard at citrix.com>
Signed-off-by: Alexander Graf <agraf at suse.de>
diff --git a/arch_init.c b/arch_init.c
index 0c09f91..484b39d 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -709,6 +709,11 @@ int audio_available(void)
#endif
}
+int tcg_available(void)
+{
+ return 1;
+}
+
int kvm_available(void)
{
#ifdef CONFIG_KVM
diff --git a/arch_init.h b/arch_init.h
index 86ebc14..2de9f08 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -27,6 +27,7 @@ void do_smbios_option(const char *optarg);
void cpudef_init(void);
int audio_available(void);
void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus);
+int tcg_available(void);
int kvm_available(void);
int xen_available(void);
diff --git a/qemu-config.c b/qemu-config.c
index 14d3419..5d7ffa2 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -450,6 +450,19 @@ QemuOptsList qemu_option_rom_opts = {
},
};
+static QemuOptsList qemu_machine_opts = {
+ .name = "machine",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head),
+ .desc = {
+ {
+ .name = "accel",
+ .type = QEMU_OPT_STRING,
+ .help = "accelerator list",
+ },
+ { /* End of list */ }
+ },
+};
+
static QemuOptsList *vm_config_groups[32] = {
&qemu_drive_opts,
&qemu_chardev_opts,
@@ -464,6 +477,7 @@ static QemuOptsList *vm_config_groups[32] = {
&qemu_trace_opts,
#endif
&qemu_option_rom_opts,
+ &qemu_machine_opts,
NULL,
};
diff --git a/qemu-options.hx b/qemu-options.hx
index 489df10..9f121ad 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2030,6 +2030,16 @@ Enable KVM full virtualization support. This option is only available
if KVM support is enabled when compiling.
ETEXI
+DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
+ "-machine accel=accel1[:accel2] use an accelerator (kvm,xen,tcg), default is tcg\n", QEMU_ARCH_ALL)
+STEXI
+ at item -machine accel=@var{accels}
+ at findex -machine
+This is use to enable an accelerator, in kvm,xen,tcg.
+By default, it use only tcg. If there a more than one accelerator
+specified, the next one is used if the first don't work.
+ETEXI
+
DEF("xen-domid", HAS_ARG, QEMU_OPTION_xen_domid,
"-xen-domid id specify xen guest domain id\n", QEMU_ARCH_ALL)
DEF("xen-create", 0, QEMU_OPTION_xen_create,
diff --git a/vl.c b/vl.c
index 6b9a2f6..a44556e 100644
--- a/vl.c
+++ b/vl.c
@@ -257,6 +257,7 @@ static NotifierList exit_notifiers =
static NotifierList machine_init_done_notifiers =
NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
+static int tcg_allowed = 1;
int kvm_allowed = 0;
uint32_t xen_domid;
enum xen_mode xen_mode = XEN_EMULATE;
@@ -1876,6 +1877,82 @@ static int debugcon_parse(const char *devname)
return 0;
}
+static int tcg_init(void)
+{
+ return 0;
+}
+
+static struct {
+ const char *opt_name;
+ const char *name;
+ int (*available)(void);
+ int (*init)(void);
+ int *allowed;
+} accel_list[] = {
+ { "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed },
+ { "kvm", "KVM", kvm_available, kvm_init, &kvm_allowed },
+};
+
+static int configure_accelerator(void)
+{
+ const char *p = NULL;
+ char buf[10];
+ int i, ret;
+ bool accel_initalised = 0;
+ bool init_failed = 0;
+
+ QemuOptsList *list = qemu_find_opts("machine");
+ if (!QTAILQ_EMPTY(&list->head)) {
+ p = qemu_opt_get(QTAILQ_FIRST(&list->head), "accel");
+ }
+
+ if (p == NULL) {
+ /* Use the default "accelerator", tcg */
+ p = "tcg";
+ }
+
+ while (!accel_initalised && *p != '\0') {
+ if (*p == ':') {
+ p++;
+ }
+ p = get_opt_name(buf, sizeof (buf), p, ':');
+ for (i = 0; i < ARRAY_SIZE(accel_list); i++) {
+ if (strcmp(accel_list[i].opt_name, buf) == 0) {
+ ret = accel_list[i].init();
+ if (ret < 0) {
+ init_failed = 1;
+ if (!accel_list[i].available()) {
+ printf("%s not supported for this target\n",
+ accel_list[i].name);
+ } else {
+ fprintf(stderr, "failed to initialize %s: %s\n",
+ accel_list[i].name,
+ strerror(-ret));
+ }
+ } else {
+ accel_initalised = 1;
+ *(accel_list[i].allowed) = 1;
+ }
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(accel_list)) {
+ fprintf(stderr, "\"%s\" accelerator does not exist.\n", buf);
+ }
+ }
+
+ if (!accel_initalised) {
+ fprintf(stderr, "No accelerator found!\n");
+ exit(1);
+ }
+
+ if (init_failed) {
+ fprintf(stderr, "Back to %s accelerator.\n", accel_list[i].name);
+ }
+
+ return !accel_initalised;
+}
+
void qemu_add_exit_notifier(Notifier *notify)
{
notifier_list_add(&exit_notifiers, notify);
@@ -2576,7 +2653,18 @@ int main(int argc, char **argv, char **envp)
do_smbios_option(optarg);
break;
case QEMU_OPTION_enable_kvm:
- kvm_allowed = 1;
+ olist = qemu_find_opts("machine");
+ qemu_opts_reset(olist);
+ qemu_opts_parse(olist, "accel=kvm", 0);
+ break;
+ case QEMU_OPTION_machine:
+ olist = qemu_find_opts("machine");
+ qemu_opts_reset(olist);
+ opts = qemu_opts_parse(olist, optarg, 0);
+ if (!opts) {
+ fprintf(stderr, "parse error: %s\n", optarg);
+ exit(1);
+ }
break;
case QEMU_OPTION_usb:
usb_enabled = 1;
@@ -2896,17 +2984,7 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
- if (kvm_allowed) {
- int ret = kvm_init();
- if (ret < 0) {
- if (!kvm_available()) {
- printf("KVM not supported for this target\n");
- } else {
- fprintf(stderr, "failed to initialize KVM: %s\n", strerror(-ret));
- }
- exit(1);
- }
- }
+ configure_accelerator();
if (qemu_init_main_loop()) {
fprintf(stderr, "qemu_init_main_loop failed\n");
commit ebabb67a17b58c729e12523cb21b2d6c1d93abc6
Author: Stefan Weil <weil at mail.berlios.de>
Date: Tue Apr 26 10:29:36 2011 +0200
Fix typo in code and comments
Replace writeable -> writable
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/block.c b/block.c
index f731c7a..8767d31 100644
--- a/block.c
+++ b/block.c
@@ -455,7 +455,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
/*
- * Snapshots should be writeable.
+ * Snapshots should be writable.
*/
if (bs->is_temporary) {
open_flags |= BDRV_O_RDWR;
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 98946d7..0392ca8 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -196,7 +196,7 @@ static inline uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
return hval;
}
-static inline int is_data_obj_writeable(SheepdogInode *inode, unsigned int idx)
+static inline int is_data_obj_writable(SheepdogInode *inode, unsigned int idx)
{
return inode->vdi_id == inode->data_vdi_id[idx];
}
@@ -1577,7 +1577,7 @@ static void sd_readv_writev_bh_cb(void *p)
create = 1;
} else if (acb->aiocb_type == AIOCB_WRITE_UDATA
- && !is_data_obj_writeable(inode, idx)) {
+ && !is_data_obj_writable(inode, idx)) {
/* Copy-On-Write */
create = 1;
old_oid = oid;
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 05450e8..9f16efd 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1126,7 +1126,7 @@ static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val)
{
TRACE(EEPROM, logout("val=0x%02x\n", val));
- /* mask unwriteable bits */
+ /* mask unwritable bits */
#if 0
val = SET_MASKED(val, 0x31, eeprom->value);
#endif
diff --git a/hw/eeprom93xx.c b/hw/eeprom93xx.c
index 660b28f..7b21f98 100644
--- a/hw/eeprom93xx.c
+++ b/hw/eeprom93xx.c
@@ -75,7 +75,7 @@ struct _eeprom_t {
uint8_t tick;
uint8_t address;
uint8_t command;
- uint8_t writeable;
+ uint8_t writable;
uint8_t eecs;
uint8_t eesk;
@@ -130,7 +130,7 @@ static const VMStateDescription vmstate_eeprom = {
VMSTATE_UINT8(tick, eeprom_t),
VMSTATE_UINT8(address, eeprom_t),
VMSTATE_UINT8(command, eeprom_t),
- VMSTATE_UINT8(writeable, eeprom_t),
+ VMSTATE_UINT8(writable, eeprom_t),
VMSTATE_UINT8(eecs, eeprom_t),
VMSTATE_UINT8(eesk, eeprom_t),
@@ -165,7 +165,7 @@ void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
address = 0x0;
} else if (eeprom->eecs && ! eecs) {
/* End chip select cycle. This triggers write / erase. */
- if (eeprom->writeable) {
+ if (eeprom->writable) {
uint8_t subcommand = address >> (eeprom->addrbits - 2);
if (command == 0 && subcommand == 2) {
/* Erase all. */
@@ -232,7 +232,7 @@ void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
switch (address >> (eeprom->addrbits - 2)) {
case 0:
logout("write disable command\n");
- eeprom->writeable = 0;
+ eeprom->writable = 0;
break;
case 1:
logout("write all command\n");
@@ -242,7 +242,7 @@ void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
break;
case 3:
logout("write enable command\n");
- eeprom->writeable = 1;
+ eeprom->writable = 1;
break;
}
} else {
diff --git a/hw/msi.c b/hw/msi.c
index b0795bd..b087fe5 100644
--- a/hw/msi.c
+++ b/hw/msi.c
@@ -155,7 +155,7 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
pci_set_word(dev->wmask + msi_data_off(dev, msi64bit), 0xffff);
if (msi_per_vector_mask) {
- /* Make mask bits 0 to nr_vectors - 1 writeable. */
+ /* Make mask bits 0 to nr_vectors - 1 writable. */
pci_set_long(dev->wmask + msi_mask_off(dev, msi64bit),
0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors));
}
diff --git a/hw/msix.c b/hw/msix.c
index daaf9b7..af40e26 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -87,7 +87,7 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
pci_set_long(config + MSIX_PBA_OFFSET, (bar_size + MSIX_PAGE_PENDING) |
bar_nr);
pdev->msix_cap = config_offset;
- /* Make flags bit writeable. */
+ /* Make flags bit writable. */
pdev->wmask[config_offset + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
MSIX_MASKALL_MASK;
return 0;
diff --git a/hw/pci.c b/hw/pci.c
index 0875654..20dfa72 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -168,7 +168,7 @@ void pci_device_reset(PCIDevice *dev)
dev->irq_state = 0;
pci_update_irq_status(dev);
pci_device_deassert_intx(dev);
- /* Clear all writeable bits */
+ /* Clear all writable bits */
pci_word_test_and_clear_mask(dev->config + PCI_COMMAND,
pci_get_word(dev->wmask + PCI_COMMAND) |
pci_get_word(dev->w1cmask + PCI_COMMAND));
@@ -871,7 +871,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
wmask = ~(size - 1);
addr = pci_bar(pci_dev, region_num);
if (region_num == PCI_ROM_SLOT) {
- /* ROM enable bit is writeable */
+ /* ROM enable bit is writable */
wmask |= PCI_ROM_ADDRESS_ENABLE;
}
pci_set_long(pci_dev->config + addr, type);
@@ -1975,7 +1975,7 @@ void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
if (!offset)
return;
pdev->config[prev] = pdev->config[offset + PCI_CAP_LIST_NEXT];
- /* Make capability writeable again */
+ /* Make capability writable again */
memset(pdev->wmask + offset, 0xff, size);
memset(pdev->w1cmask + offset, 0, size);
/* Clear cmask as device-specific registers can't be checked */
diff --git a/hw/pci.h b/hw/pci.h
index c6a6eb6..0d288ce 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -132,7 +132,7 @@ struct PCIDevice {
/* PCI config space */
uint8_t *config;
- /* Used to enable config checks on load. Note that writeable bits are
+ /* Used to enable config checks on load. Note that writable bits are
* never checked even if set in cmask. */
uint8_t *cmask;
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index c7c7a3c..2f8db58 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -1399,7 +1399,7 @@ static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val)
s->currCPlusTxDesc = 0;
}
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0xe3, s->bChipCmdState);
/* Deassert reset pin before next read */
@@ -1443,7 +1443,7 @@ static void rtl8139_CpCmd_write(RTL8139State *s, uint32_t val)
s->cplus_enabled = 1;
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0xff84, s->CpCmd);
s->CpCmd = val;
@@ -1472,7 +1472,7 @@ static uint32_t rtl8139_IntrMitigate_read(RTL8139State *s)
return ret;
}
-static int rtl8139_config_writeable(RTL8139State *s)
+static int rtl8139_config_writable(RTL8139State *s)
{
if (s->Cfg9346 & Cfg9346_Unlock)
{
@@ -1490,10 +1490,10 @@ static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val)
DPRINTF("BasicModeCtrl register write(w) val=0x%04x\n", val);
- /* mask unwriteable bits */
+ /* mask unwritable bits */
uint32_t mask = 0x4cff;
- if (1 || !rtl8139_config_writeable(s))
+ if (1 || !rtl8139_config_writable(s))
{
/* Speed setting and autonegotiation enable bits are read-only */
mask |= 0x3000;
@@ -1521,7 +1521,7 @@ static void rtl8139_BasicModeStatus_write(RTL8139State *s, uint32_t val)
DPRINTF("BasicModeStatus register write(w) val=0x%04x\n", val);
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0xff3f, s->BasicModeStatus);
s->BasicModeStatus = val;
@@ -1542,7 +1542,7 @@ static void rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val)
DPRINTF("Cfg9346 write val=0x%02x\n", val);
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0x31, s->Cfg9346);
uint32_t opmode = val & 0xc0;
@@ -1594,10 +1594,11 @@ static void rtl8139_Config0_write(RTL8139State *s, uint32_t val)
DPRINTF("Config0 write val=0x%02x\n", val);
- if (!rtl8139_config_writeable(s))
+ if (!rtl8139_config_writable(s)) {
return;
+ }
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0xf8, s->Config0);
s->Config0 = val;
@@ -1618,10 +1619,11 @@ static void rtl8139_Config1_write(RTL8139State *s, uint32_t val)
DPRINTF("Config1 write val=0x%02x\n", val);
- if (!rtl8139_config_writeable(s))
+ if (!rtl8139_config_writable(s)) {
return;
+ }
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0xC, s->Config1);
s->Config1 = val;
@@ -1642,10 +1644,11 @@ static void rtl8139_Config3_write(RTL8139State *s, uint32_t val)
DPRINTF("Config3 write val=0x%02x\n", val);
- if (!rtl8139_config_writeable(s))
+ if (!rtl8139_config_writable(s)) {
return;
+ }
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0x8F, s->Config3);
s->Config3 = val;
@@ -1666,10 +1669,11 @@ static void rtl8139_Config4_write(RTL8139State *s, uint32_t val)
DPRINTF("Config4 write val=0x%02x\n", val);
- if (!rtl8139_config_writeable(s))
+ if (!rtl8139_config_writable(s)) {
return;
+ }
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0x0a, s->Config4);
s->Config4 = val;
@@ -1690,7 +1694,7 @@ static void rtl8139_Config5_write(RTL8139State *s, uint32_t val)
DPRINTF("Config5 write val=0x%02x\n", val);
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0x80, s->Config5);
s->Config5 = val;
@@ -1743,7 +1747,7 @@ static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val)
{
DPRINTF("RxConfig write val=0x%08x\n", val);
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0xf0fc0040, s->RxConfig);
s->RxConfig = val;
@@ -2610,7 +2614,7 @@ static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val)
{
DPRINTF("IntrMask write(w) val=0x%04x\n", val);
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0x1e00, s->IntrMask);
s->IntrMask = val;
@@ -2642,7 +2646,7 @@ static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val)
#else
uint16_t newStatus = s->IntrStatus & ~val;
- /* mask unwriteable bits */
+ /* mask unwritable bits */
newStatus = SET_MASKED(newStatus, 0x1e00, s->IntrStatus);
/* writing 1 to interrupt status register bit clears it */
@@ -2686,7 +2690,7 @@ static void rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val)
{
DPRINTF("MultiIntr write(w) val=0x%04x\n", val);
- /* mask unwriteable bits */
+ /* mask unwritable bits */
val = SET_MASKED(val, 0xf000, s->MultiIntr);
s->MultiIntr = val;
diff --git a/hw/sun4m_iommu.c b/hw/sun4m_iommu.c
index bba69ee..7f5dad5 100644
--- a/hw/sun4m_iommu.c
+++ b/hw/sun4m_iommu.c
@@ -118,7 +118,7 @@
#define IOPTE_PAGE 0xffffff00 /* Physical page number (PA[35:12]) */
#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or
Viking/MXCC) */
-#define IOPTE_WRITE 0x00000004 /* Writeable */
+#define IOPTE_WRITE 0x00000004 /* Writable */
#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
#define IOPTE_WAZ 0x00000001 /* Write as zeros */
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 590e092..8d9b5b9 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -477,7 +477,7 @@ static const mips_def_t mips_defs[] =
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
.SYNCI_Step = 16,
.CCRes = 2,
- .CP0_Status_rw_bitmask = 0xF5D0FF1F, /*bit5:7 not writeable*/
+ .CP0_Status_rw_bitmask = 0xF5D0FF1F, /*bit5:7 not writable*/
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
.SEGBITS = 40,
.PABITS = 40,
commit 3964f535c35c08470ac69bd553282af500bc8bb0
Merge: a69fb35... 5300f1a...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Thu May 5 13:05:32 2011 -0500
Merge remote-tracking branch 'mst/for_anthony' into staging
commit a69fb35079f682f99dd4d077b76232763d832d42
Merge: 196a778... ef0bdf7...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Thu May 5 13:04:57 2011 -0500
Merge remote-tracking branch 'kraxel/usb.7.pull' into staging
commit 5300f1a5487f67f0bde8ee1081b799108668cb1d
Merge: 8d4c78e... d2d979c...
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Thu May 5 16:39:47 2011 +0300
Merge remote branch 'origin/master' into pci
Conflicts:
exec.c
diff --cc exec.c
index 0c773a8,a718d74..308a86d
--- a/exec.c
+++ b/exec.c
@@@ -2621,7 -2618,8 +2628,8 @@@ void cpu_register_physical_memory_log(t
ram_addr_t orig_size = size;
subpage_t *subpage;
+ assert(size);
- cpu_notify_set_memory(start_addr, size, phys_offset);
+ cpu_notify_set_memory(start_addr, size, phys_offset, log_dirty);
if (phys_offset == IO_MEM_UNASSIGNED) {
region_offset = start_addr;
commit 8d4c78e7c8adf0a4440a8de92738b3820fc8215a
Author: Alex Williamson <alex.williamson at redhat.com>
Date: Tue May 3 12:36:46 2011 -0600
CPUPhysMemoryClient: Pass guest physical address not region offset
When we're trying to get a newly registered phys memory client updated
with the current page mappings, we end up passing the region offset
(a ram_addr_t) as the start address rather than the actual guest
physical memory address (target_phys_addr_t). If your guest has less
than 3.5G of memory, these are coincidentally the same thing. If
there's more, the region offset for the memory above 4G starts over
at 0, so the set_memory client will overwrite it's lower memory entries.
Instead, keep track of the guest phsyical address as we're walking the
tables and pass that to the set_memory client.
Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
Acked-by: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/exec.c b/exec.c
index 9823e35..0c773a8 100644
--- a/exec.c
+++ b/exec.c
@@ -1743,8 +1743,14 @@ static int cpu_notify_migration_log(int enable)
return 0;
}
+/* The l1_phys_map provides the upper P_L1_BITs of the guest physical
+ * address. Each intermediate table provides the next L2_BITs of guest
+ * physical address space. The number of levels vary based on host and
+ * guest configuration, making it efficient to build the final guest
+ * physical address by seeding the L1 offset and shifting and adding in
+ * each L2 offset as we recurse through them. */
static void phys_page_for_each_1(CPUPhysMemoryClient *client,
- int level, void **lp)
+ int level, void **lp, target_phys_addr_t addr)
{
int i;
@@ -1753,16 +1759,18 @@ static void phys_page_for_each_1(CPUPhysMemoryClient *client,
}
if (level == 0) {
PhysPageDesc *pd = *lp;
+ addr <<= L2_BITS + TARGET_PAGE_BITS;
for (i = 0; i < L2_SIZE; ++i) {
if (pd[i].phys_offset != IO_MEM_UNASSIGNED) {
- client->set_memory(client, pd[i].region_offset,
+ client->set_memory(client, addr | i << TARGET_PAGE_BITS,
TARGET_PAGE_SIZE, pd[i].phys_offset, false);
}
}
} else {
void **pp = *lp;
for (i = 0; i < L2_SIZE; ++i) {
- phys_page_for_each_1(client, level - 1, pp + i);
+ phys_page_for_each_1(client, level - 1, pp + i,
+ (addr << L2_BITS) | i);
}
}
}
@@ -1772,7 +1780,7 @@ static void phys_page_for_each(CPUPhysMemoryClient *client)
int i;
for (i = 0; i < P_L1_SIZE; ++i) {
phys_page_for_each_1(client, P_L1_SHIFT / L2_BITS - 1,
- l1_phys_map + i);
+ l1_phys_map + i, i);
}
}
commit c2f42bf003eac96ee4093faaf44cbf784ac64398
Author: Alex Williamson <alex.williamson at redhat.com>
Date: Tue May 3 12:36:32 2011 -0600
CPUPhysMemoryClient: Fix typo in phys memory client registration
When we register a physical memory client, we try to walk the page
tables, calling the set_memory hook for every entry. Effectively
playing catchup for the client for everything already registered.
With this type, we only walk the 2nd entry of the l1 table,
typically missing all of the registered memory.
Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/exec.c b/exec.c
index d1a066c..9823e35 100644
--- a/exec.c
+++ b/exec.c
@@ -1772,7 +1772,7 @@ static void phys_page_for_each(CPUPhysMemoryClient *client)
int i;
for (i = 0; i < P_L1_SIZE; ++i) {
phys_page_for_each_1(client, P_L1_SHIFT / L2_BITS - 1,
- l1_phys_map + 1);
+ l1_phys_map + i);
}
}
commit 602ef4d917f78cee8e1057ca85bdc8888a1f7087
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Mon May 2 20:01:37 2011 +0200
pci: Add class 0x403 as 'audio controller'
Used by HD audio controllers like our intel-hda.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/pci.c b/hw/pci.c
index 410b67b..0875654 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1169,6 +1169,7 @@ static const pci_class_desc pci_class_descriptions[] =
{ 0x0400, "Video controller", "video"},
{ 0x0401, "Audio controller", "sound"},
{ 0x0402, "Phone"},
+ { 0x0403, "Audio controller", "sound"},
{ 0x0480, "Multimedia controller"},
{ 0x0500, "RAM controller", "memory"},
{ 0x0501, "Flash controller", "flash"},
commit 45fe15c25a5c9feea6e0f78434f5e9f632de9d94
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Mon May 2 20:00:47 2011 +0200
MSI: Robust resource release
msi_init may fail, so we need to check on uninit if the cap was
actually installed. This also avoids that the users need to check.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index eb00f03..fd3537e 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -110,10 +110,7 @@ static int pci_ich9_uninit(PCIDevice *dev)
struct AHCIPCIState *d;
d = DO_UPCAST(struct AHCIPCIState, card, dev);
- if (msi_enabled(dev)) {
- msi_uninit(dev);
- }
-
+ msi_uninit(dev);
qemu_unregister_reset(ahci_reset, d);
ahci_uninit(&d->ahci);
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index 7f83745..5485745 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -1165,9 +1165,7 @@ static int intel_hda_exit(PCIDevice *pci)
{
IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
- if (d->msi) {
- msi_uninit(&d->pci);
- }
+ msi_uninit(&d->pci);
cpu_unregister_io_memory(d->mmio_addr);
return 0;
}
diff --git a/hw/msi.c b/hw/msi.c
index 3dc3a24..b0795bd 100644
--- a/hw/msi.c
+++ b/hw/msi.c
@@ -164,9 +164,17 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
void msi_uninit(struct PCIDevice *dev)
{
- uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
- uint8_t cap_size = msi_cap_sizeof(flags);
+ uint16_t flags;
+ uint8_t cap_size;
+
+ if (!(dev->cap_present & QEMU_PCI_CAP_MSI)) {
+ return;
+ }
+ flags = pci_get_word(dev->config + msi_flags_off(dev));
+ cap_size = msi_cap_sizeof(flags);
pci_del_capability(dev, PCI_CAP_ID_MSIX, cap_size);
+ dev->cap_present &= ~QEMU_PCI_CAP_MSI;
+
MSI_DEV_PRINTF(dev, "uninit\n");
}
commit 072476ea08dcffe89b0bd6e2053f01dd89c54861
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat Apr 30 22:40:13 2011 +0200
eepro100: Support 32 bit read/write access to flash register
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 726d402..1781c8e 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1443,6 +1443,10 @@ static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr)
val = eepro100_read_port(s);
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
break;
+ case SCBflash:
+ val = eepro100_read_eeprom(s);
+ TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
+ break;
case SCBCtrlMDI:
val = eepro100_read_mdi(s);
break;
@@ -1579,6 +1583,11 @@ static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
eepro100_write_port(s);
break;
+ case SCBflash:
+ TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
+ val = val >> 16;
+ eepro100_write_eeprom(s->eeprom, val);
+ break;
case SCBCtrlMDI:
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
eepro100_write_mdi(s);
commit a39bd01713b9e4e12bffe835b95edbc0ea5f0b16
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat Apr 30 22:40:12 2011 +0200
eepro100: Support byte read access to general control register
The general control register is a byte register.
Add support for byte reads.
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/eepro100.c b/hw/eepro100.c
index c612fe1..726d402 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1382,6 +1382,9 @@ static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr)
val = 0;
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
break;
+ case SCBgctrl: /* General Control Register */
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
+ break;
case SCBgstat: /* General Status Register */
/* 100 Mbps full duplex, valid link */
val = 0x07;
commit 0113f48df6cb8209df9d85e4f92c79aa3be1b5c5
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat Apr 30 22:40:11 2011 +0200
eepro100: Support byte/word read/write access to MDI control register
MDI control is a 32 bit register, but may be read or written using
8 or 16 bit access. Data is latched when the MSB is written.
Add support for byte/word read/write access.
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 634be59..c612fe1 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1193,8 +1193,9 @@ static uint32_t eepro100_read_mdi(EEPRO100State * s)
return val;
}
-static void eepro100_write_mdi(EEPRO100State * s, uint32_t val)
+static void eepro100_write_mdi(EEPRO100State *s)
{
+ uint32_t val = e100_read_reg4(s, SCBCtrlMDI);
uint8_t raiseint = (val & BIT(29)) >> 29;
uint8_t opcode = (val & BITS(27, 26)) >> 26;
uint8_t phy = (val & BITS(25, 21)) >> 21;
@@ -1370,6 +1371,13 @@ static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr)
case SCBeeprom:
val = eepro100_read_eeprom(s);
break;
+ case SCBCtrlMDI:
+ case SCBCtrlMDI + 1:
+ case SCBCtrlMDI + 2:
+ case SCBCtrlMDI + 3:
+ val = (uint8_t)(eepro100_read_mdi(s) >> (8 * (addr & 3)));
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
+ break;
case SCBpmdr: /* Power Management Driver Register */
val = 0;
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
@@ -1402,6 +1410,11 @@ static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr)
val = eepro100_read_eeprom(s);
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
break;
+ case SCBCtrlMDI:
+ case SCBCtrlMDI + 2:
+ val = (uint16_t)(eepro100_read_mdi(s) >> (8 * (addr & 3)));
+ TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
+ break;
default:
logout("addr=%s val=0x%04x\n", regname(addr), val);
missing("unknown word read");
@@ -1488,6 +1501,15 @@ static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
eepro100_write_eeprom(s->eeprom, val);
break;
+ case SCBCtrlMDI:
+ case SCBCtrlMDI + 1:
+ case SCBCtrlMDI + 2:
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
+ break;
+ case SCBCtrlMDI + 3:
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
+ eepro100_write_mdi(s);
+ break;
default:
logout("addr=%s val=0x%02x\n", regname(addr), val);
missing("unknown byte write");
@@ -1527,6 +1549,13 @@ static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
eepro100_write_eeprom(s->eeprom, val);
break;
+ case SCBCtrlMDI:
+ TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
+ break;
+ case SCBCtrlMDI + 2:
+ TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
+ eepro100_write_mdi(s);
+ break;
default:
logout("addr=%s val=0x%04x\n", regname(addr), val);
missing("unknown word write");
@@ -1548,7 +1577,8 @@ static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
eepro100_write_port(s);
break;
case SCBCtrlMDI:
- eepro100_write_mdi(s, val);
+ TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
+ eepro100_write_mdi(s);
break;
default:
logout("addr=%s val=0x%08x\n", regname(addr), val);
commit 27a05006e03eed00d72d943c06224fd8bd349e54
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat Apr 30 22:40:10 2011 +0200
eepro100: Support byte/word writes to pointer register
pointer is a 32 bit register, but may be written using 8 or 16 bit writes.
Add support for byte/word writes.
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 37d6fb7..634be59 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -240,7 +240,6 @@ typedef struct {
uint16_t mdimem[32];
eeprom_t *eeprom;
uint32_t device; /* device variant */
- uint32_t pointer;
/* (cu_base + cu_offset) address the next command block in the command block list. */
uint32_t cu_base; /* CU base address */
uint32_t cu_offset; /* CU address offset */
@@ -991,7 +990,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
logout("unexpected CU state is %u\n", cu_state);
}
set_cu_state(s, cu_active);
- s->cu_offset = s->pointer;
+ s->cu_offset = e100_read_reg4(s, SCBPointer);
action_command(s);
break;
case CU_RESUME:
@@ -1012,7 +1011,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
break;
case CU_STATSADDR:
/* Load dump counters address. */
- s->statsaddr = s->pointer;
+ s->statsaddr = e100_read_reg4(s, SCBPointer);
TRACE(OTHER, logout("val=0x%02x (status address)\n", val));
break;
case CU_SHOWSTATS:
@@ -1024,7 +1023,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
case CU_CMD_BASE:
/* Load CU base. */
TRACE(OTHER, logout("val=0x%02x (CU base address)\n", val));
- s->cu_base = s->pointer;
+ s->cu_base = e100_read_reg4(s, SCBPointer);
break;
case CU_DUMPSTATS:
/* Dump and reset statistical counters. */
@@ -1057,7 +1056,7 @@ static void eepro100_ru_command(EEPRO100State * s, uint8_t val)
#endif
}
set_ru_state(s, ru_ready);
- s->ru_offset = s->pointer;
+ s->ru_offset = e100_read_reg4(s, SCBPointer);
TRACE(OTHER, logout("val=0x%02x (rx start)\n", val));
break;
case RX_RESUME:
@@ -1081,7 +1080,7 @@ static void eepro100_ru_command(EEPRO100State * s, uint8_t val)
case RX_ADDR_LOAD:
/* Load RU base. */
TRACE(OTHER, logout("val=0x%02x (RU base address)\n", val));
- s->ru_base = s->pointer;
+ s->ru_base = e100_read_reg4(s, SCBPointer);
break;
default:
logout("val=0x%02x (undefined RU command)\n", val);
@@ -1138,12 +1137,6 @@ static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val)
eeprom93xx_write(eeprom, eecs, eesk, eedi);
}
-static void eepro100_write_pointer(EEPRO100State * s, uint32_t val)
-{
- s->pointer = le32_to_cpu(val);
- TRACE(OTHER, logout("val=0x%08x\n", val));
-}
-
/*****************************************************************************
*
* MDI emulation.
@@ -1428,9 +1421,6 @@ static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr)
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
break;
case SCBPointer:
-#if 0
- val = eepro100_read_pointer(s);
-#endif
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
break;
case SCBPort:
@@ -1473,6 +1463,12 @@ static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
}
eepro100_interrupt(s, 0);
break;
+ case SCBPointer:
+ case SCBPointer + 1:
+ case SCBPointer + 2:
+ case SCBPointer + 3:
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
+ break;
case SCBPort:
case SCBPort + 1:
case SCBPort + 2:
@@ -1516,6 +1512,10 @@ static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
eepro100_write_command(s, val);
eepro100_write1(s, SCBIntmask, val >> 8);
break;
+ case SCBPointer:
+ case SCBPointer + 2:
+ TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
+ break;
case SCBPort:
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
break;
@@ -1541,7 +1541,7 @@ static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
switch (addr) {
case SCBPointer:
- eepro100_write_pointer(s, val);
+ TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
break;
case SCBPort:
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
@@ -1881,7 +1881,6 @@ static const VMStateDescription vmstate_eepro100 = {
/* The eeprom should be saved and restored by its own routines. */
VMSTATE_UINT32(device, EEPRO100State),
/* TODO check device. */
- VMSTATE_UINT32(pointer, EEPRO100State),
VMSTATE_UINT32(cu_base, EEPRO100State),
VMSTATE_UINT32(cu_offset, EEPRO100State),
VMSTATE_UINT32(ru_base, EEPRO100State),
commit 3fd3d0b463d5c959c3a08a665eed1a2cd4e1d3da
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat Apr 30 22:40:09 2011 +0200
eepro100: Support byte/word writes to port address
port is a 32 bit register, but may be written using 8 or 16 bit writes.
Add support for byte/word writes.
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 6315fe8..37d6fb7 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1317,8 +1317,9 @@ static uint32_t eepro100_read_port(EEPRO100State * s)
return 0;
}
-static void eepro100_write_port(EEPRO100State * s, uint32_t val)
+static void eepro100_write_port(EEPRO100State *s)
{
+ uint32_t val = e100_read_reg4(s, SCBPort);
uint32_t address = (val & ~PORT_SELECTION_MASK);
uint8_t selection = (val & PORT_SELECTION_MASK);
switch (selection) {
@@ -1472,7 +1473,15 @@ static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
}
eepro100_interrupt(s, 0);
break;
+ case SCBPort:
+ case SCBPort + 1:
+ case SCBPort + 2:
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
+ break;
case SCBPort + 3:
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
+ eepro100_write_port(s);
+ break;
case SCBFlow: /* does not exist on 82557 */
case SCBFlow + 1:
case SCBFlow + 2:
@@ -1507,6 +1516,13 @@ static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
eepro100_write_command(s, val);
eepro100_write1(s, SCBIntmask, val >> 8);
break;
+ case SCBPort:
+ TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
+ break;
+ case SCBPort + 2:
+ TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
+ eepro100_write_port(s);
+ break;
case SCBeeprom:
TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
eepro100_write_eeprom(s->eeprom, val);
@@ -1529,7 +1545,7 @@ static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
break;
case SCBPort:
TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
- eepro100_write_port(s, val);
+ eepro100_write_port(s);
break;
case SCBCtrlMDI:
eepro100_write_mdi(s, val);
commit e5e23ab83bfaf07c1a5bf685b1adf311e2326b74
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat Apr 30 22:40:08 2011 +0200
eepro100: Fix endianness issues
Like other Intel devices, e100 (eepro100) uses little endian byte order.
This patch was tested with these combinations:
i386 host, i386 + mipsel guests (le-le)
mipsel host, i386 guest (le-le)
i386 host, mips + ppc guests (le-be)
mips host, i386 guest (be-le)
mips and mipsel hosts were emulated machines.
v2:
Use prefix for new functions. Add the same prefix to stl_le_phys.
Fix alignment of mem (needed for word/dword reads/writes).
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/eepro100.c b/hw/eepro100.c
index ab5c699..6315fe8 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -20,11 +20,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Tested features (i82559):
- * PXE boot (i386) ok
+ * PXE boot (i386 guest, i386 / mips / mipsel / ppc host) ok
* Linux networking (i386) ok
*
* Untested:
- * non-i386 platforms
* Windows networking
*
* References:
@@ -139,7 +138,7 @@ typedef struct {
/* Offsets to the various registers.
All accesses need not be longword aligned. */
-enum speedo_offsets {
+typedef enum {
SCBStatus = 0, /* Status Word. */
SCBAck = 1,
SCBCmd = 2, /* Rx/Command Unit command and status. */
@@ -154,7 +153,7 @@ enum speedo_offsets {
SCBpmdr = 27, /* Power Management Driver. */
SCBgctrl = 28, /* General Control. */
SCBgstat = 29, /* General Status. */
-};
+} E100RegisterOffset;
/* A speedo3 transmit buffer descriptor with two buffers... */
typedef struct {
@@ -258,11 +257,13 @@ typedef struct {
/* Statistical counters. Also used for wake-up packet (i82559). */
eepro100_stats_t statistics;
+ /* Data in mem is always in the byte order of the controller (le).
+ * It must be dword aligned to allow direct access to 32 bit values. */
+ uint8_t mem[PCI_MEM_SIZE] __attribute__((aligned(8)));;
+
/* Configuration bytes. */
uint8_t configuration[22];
- /* Data in mem is always in the byte order of the controller (le). */
- uint8_t mem[PCI_MEM_SIZE];
/* vmstate for each particular nic */
VMStateDescription *vmstate;
@@ -316,8 +317,33 @@ static const uint16_t eepro100_mdi_mask[] = {
0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
};
-/* XXX: optimize */
-static void stl_le_phys(target_phys_addr_t addr, uint32_t val)
+/* Read a 16 bit little endian value from physical memory. */
+static uint16_t e100_ldw_le_phys(target_phys_addr_t addr)
+{
+ /* Load 16 bit (little endian) word from emulated hardware. */
+ uint16_t val;
+ cpu_physical_memory_read(addr, &val, sizeof(val));
+ return le16_to_cpu(val);
+}
+
+/* Read a 32 bit little endian value from physical memory. */
+static uint32_t e100_ldl_le_phys(target_phys_addr_t addr)
+{
+ /* Load 32 bit (little endian) word from emulated hardware. */
+ uint32_t val;
+ cpu_physical_memory_read(addr, &val, sizeof(val));
+ return le32_to_cpu(val);
+}
+
+/* Write a 16 bit little endian value to physical memory. */
+static void e100_stw_le_phys(target_phys_addr_t addr, uint16_t val)
+{
+ val = cpu_to_le16(val);
+ cpu_physical_memory_write(addr, &val, sizeof(val));
+}
+
+/* Write a 32 bit little endian value to physical memory. */
+static void e100_stl_le_phys(target_phys_addr_t addr, uint32_t val)
{
val = cpu_to_le32(val);
cpu_physical_memory_write(addr, &val, sizeof(val));
@@ -348,6 +374,36 @@ static unsigned compute_mcast_idx(const uint8_t * ep)
return (crc & BITS(7, 2)) >> 2;
}
+/* Read a 16 bit control/status (CSR) register. */
+static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr)
+{
+ assert(!((uintptr_t)&s->mem[addr] & 1));
+ return le16_to_cpup((uint16_t *)&s->mem[addr]);
+}
+
+/* Read a 32 bit control/status (CSR) register. */
+static uint32_t e100_read_reg4(EEPRO100State *s, E100RegisterOffset addr)
+{
+ assert(!((uintptr_t)&s->mem[addr] & 3));
+ return le32_to_cpup((uint32_t *)&s->mem[addr]);
+}
+
+/* Write a 16 bit control/status (CSR) register. */
+static void e100_write_reg2(EEPRO100State *s, E100RegisterOffset addr,
+ uint16_t val)
+{
+ assert(!((uintptr_t)&s->mem[addr] & 1));
+ cpu_to_le16w((uint16_t *)&s->mem[addr], val);
+}
+
+/* Read a 32 bit control/status (CSR) register. */
+static void e100_write_reg4(EEPRO100State *s, E100RegisterOffset addr,
+ uint32_t val)
+{
+ assert(!((uintptr_t)&s->mem[addr] & 3));
+ cpu_to_le32w((uint32_t *)&s->mem[addr], val);
+}
+
#if defined(DEBUG_EEPRO100)
static const char *nic_dump(const uint8_t * buf, unsigned size)
{
@@ -599,8 +655,7 @@ static void nic_selective_reset(EEPRO100State * s)
TRACE(EEPROM, logout("checksum=0x%04x\n", eeprom_contents[EEPROM_SIZE - 1]));
memset(s->mem, 0, sizeof(s->mem));
- uint32_t val = BIT(21);
- memcpy(&s->mem[SCBCtrlMDI], &val, sizeof(val));
+ e100_write_reg4(s, SCBCtrlMDI, BIT(21));
assert(sizeof(s->mdimem) == sizeof(eepro100_mdi_default));
memcpy(&s->mdimem[0], &eepro100_mdi_default[0], sizeof(s->mdimem));
@@ -704,13 +759,13 @@ static void dump_statistics(EEPRO100State * s)
* Number of data should check configuration!!!
*/
cpu_physical_memory_write(s->statsaddr, &s->statistics, s->stats_size);
- stl_le_phys(s->statsaddr + 0, s->statistics.tx_good_frames);
- stl_le_phys(s->statsaddr + 36, s->statistics.rx_good_frames);
- stl_le_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);
- stl_le_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors);
+ e100_stl_le_phys(s->statsaddr + 0, s->statistics.tx_good_frames);
+ e100_stl_le_phys(s->statsaddr + 36, s->statistics.rx_good_frames);
+ e100_stl_le_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);
+ e100_stl_le_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors);
#if 0
- stw_le_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);
- stw_le_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);
+ e100_stw_le_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);
+ e100_stw_le_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);
missing("CU dump statistical counters");
#endif
}
@@ -747,10 +802,10 @@ static void tx_command(EEPRO100State *s)
}
assert(tcb_bytes <= sizeof(buf));
while (size < tcb_bytes) {
- uint32_t tx_buffer_address = ldl_phys(tbd_address);
- uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
+ uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
+ uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
#if 0
- uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
+ uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
#endif
tbd_address += 8;
TRACE(RXTX, logout
@@ -769,9 +824,9 @@ static void tx_command(EEPRO100State *s)
if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
/* Extended Flexible TCB. */
for (; tbd_count < 2; tbd_count++) {
- uint32_t tx_buffer_address = ldl_phys(tbd_address);
- uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
- uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
+ uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
+ uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
+ uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
tbd_address += 8;
TRACE(RXTX, logout
("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
@@ -787,9 +842,9 @@ static void tx_command(EEPRO100State *s)
}
tbd_address = tbd_array;
for (; tbd_count < s->tx.tbd_count; tbd_count++) {
- uint32_t tx_buffer_address = ldl_phys(tbd_address);
- uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
- uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
+ uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
+ uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
+ uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
tbd_address += 8;
TRACE(RXTX, logout
("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
@@ -897,7 +952,7 @@ static void action_command(EEPRO100State *s)
break;
}
/* Write new status. */
- stw_phys(s->cb_address, s->tx.status | ok_status | STATUS_C);
+ e100_stw_le_phys(s->cb_address, s->tx.status | ok_status | STATUS_C);
if (bit_i) {
/* CU completed action. */
eepro100_cx_interrupt(s);
@@ -964,7 +1019,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
/* Dump statistical counters. */
TRACE(OTHER, logout("val=0x%02x (dump stats)\n", val));
dump_statistics(s);
- stl_le_phys(s->statsaddr + s->stats_size, 0xa005);
+ e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa005);
break;
case CU_CMD_BASE:
/* Load CU base. */
@@ -975,7 +1030,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
/* Dump and reset statistical counters. */
TRACE(OTHER, logout("val=0x%02x (dump stats and reset)\n", val));
dump_statistics(s);
- stl_le_phys(s->statsaddr + s->stats_size, 0xa007);
+ e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa007);
memset(&s->statistics, 0, sizeof(s->statistics));
break;
case CU_SRESUME:
@@ -1058,8 +1113,7 @@ static void eepro100_write_command(EEPRO100State * s, uint8_t val)
static uint16_t eepro100_read_eeprom(EEPRO100State * s)
{
- uint16_t val;
- memcpy(&val, &s->mem[SCBeeprom], sizeof(val));
+ uint16_t val = e100_read_reg2(s, SCBeeprom);
if (eeprom93xx_read(s->eeprom)) {
val |= EEPROM_DO;
} else {
@@ -1129,8 +1183,7 @@ static const char *reg2name(uint8_t reg)
static uint32_t eepro100_read_mdi(EEPRO100State * s)
{
- uint32_t val;
- memcpy(&val, &s->mem[0x10], sizeof(val));
+ uint32_t val = e100_read_reg4(s, SCBCtrlMDI);
#ifdef DEBUG_EEPRO100
uint8_t raiseint = (val & BIT(29)) >> 29;
@@ -1239,7 +1292,7 @@ static void eepro100_write_mdi(EEPRO100State * s, uint32_t val)
}
}
val = (val & 0xffff0000) + data;
- memcpy(&s->mem[0x10], &val, sizeof(val));
+ e100_write_reg4(s, SCBCtrlMDI, val);
}
/*****************************************************************************
@@ -1266,7 +1319,6 @@ static uint32_t eepro100_read_port(EEPRO100State * s)
static void eepro100_write_port(EEPRO100State * s, uint32_t val)
{
- val = le32_to_cpu(val);
uint32_t address = (val & ~PORT_SELECTION_MASK);
uint8_t selection = (val & PORT_SELECTION_MASK);
switch (selection) {
@@ -1301,7 +1353,7 @@ static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr)
{
uint8_t val = 0;
if (addr <= sizeof(s->mem) - sizeof(val)) {
- memcpy(&val, &s->mem[addr], sizeof(val));
+ val = s->mem[addr];
}
switch (addr) {
@@ -1344,7 +1396,7 @@ static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr)
{
uint16_t val = 0;
if (addr <= sizeof(s->mem) - sizeof(val)) {
- memcpy(&val, &s->mem[addr], sizeof(val));
+ val = e100_read_reg2(s, addr);
}
switch (addr) {
@@ -1367,7 +1419,7 @@ static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr)
{
uint32_t val = 0;
if (addr <= sizeof(s->mem) - sizeof(val)) {
- memcpy(&val, &s->mem[addr], sizeof(val));
+ val = e100_read_reg4(s, addr);
}
switch (addr) {
@@ -1398,7 +1450,7 @@ static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
{
/* SCBStatus is readonly. */
if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
- memcpy(&s->mem[addr], &val, sizeof(val));
+ s->mem[addr] = val;
}
switch (addr) {
@@ -1441,7 +1493,7 @@ static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
{
/* SCBStatus is readonly. */
if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
- memcpy(&s->mem[addr], &val, sizeof(val));
+ e100_write_reg2(s, addr, val);
}
switch (addr) {
@@ -1468,7 +1520,7 @@ static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
{
if (addr <= sizeof(s->mem) - sizeof(val)) {
- memcpy(&s->mem[addr], &val, sizeof(val));
+ e100_write_reg4(s, addr, val);
}
switch (addr) {
@@ -1760,9 +1812,10 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
#endif
TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n",
rfd_command, rx.link, rx.rx_buf_addr, rfd_size));
- stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status),
- rfd_status);
- stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, count), size);
+ e100_stw_le_phys(s->ru_base + s->ru_offset +
+ offsetof(eepro100_rx_t, status), rfd_status);
+ e100_stw_le_phys(s->ru_base + s->ru_offset +
+ offsetof(eepro100_rx_t, count), size);
/* Early receive interrupt not supported. */
#if 0
eepro100_er_interrupt(s);
@@ -1891,7 +1944,7 @@ static int e100_nic_init(PCIDevice *pci_dev)
/* Handler for memory-mapped I/O */
s->mmio_index =
cpu_register_io_memory(pci_mmio_read, pci_mmio_write, s,
- DEVICE_NATIVE_ENDIAN);
+ DEVICE_LITTLE_ENDIAN);
pci_register_bar_simple(&s->dev, 0, PCI_MEM_SIZE,
PCI_BASE_ADDRESS_MEM_PREFETCH, s->mmio_index);
commit 792f1d639443c3895df82306e13bb144627ad6bc
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat Apr 30 22:40:07 2011 +0200
eepro100: Pad received short frames
QEMU sends frames smaller than 60 bytes to ethernet nics.
Such frames are rejected by real NICs and their emulations.
To avoid this behaviour, other NIC emulations pad received
frames. This patch enables this workaround for eepro100, too.
All related code is marked with CONFIG_PAD_RECEIVED_FRAMES,
so we can drop this in case QEMU's networking code is
ever changed.
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 848bf79..ab5c699 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -48,6 +48,15 @@
#include "eeprom93xx.h"
#include "sysemu.h"
+/* QEMU sends frames smaller than 60 bytes to ethernet nics.
+ * Such frames are rejected by real nics and their emulations.
+ * To avoid this behaviour, other nic emulations pad received
+ * frames. The following definition enables this padding for
+ * eepro100, too. We keep the define around in case it might
+ * become useful the future if the core networking is ever
+ * changed to pad short packets itself. */
+#define CONFIG_PAD_RECEIVED_FRAMES
+
#define KiB 1024
/* Debug EEPRO100 card. */
@@ -1640,19 +1649,32 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
*/
EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
uint16_t rfd_status = 0xa000;
+#if defined(CONFIG_PAD_RECEIVED_FRAMES)
+ uint8_t min_buf[60];
+#endif
static const uint8_t broadcast_macaddr[6] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+#if defined(CONFIG_PAD_RECEIVED_FRAMES)
+ /* Pad to minimum Ethernet frame length */
+ if (size < sizeof(min_buf)) {
+ memcpy(min_buf, buf, size);
+ memset(&min_buf[size], 0, sizeof(min_buf) - size);
+ buf = min_buf;
+ size = sizeof(min_buf);
+ }
+#endif
+
if (s->configuration[8] & 0x80) {
/* CSMA is disabled. */
logout("%p received while CSMA is disabled\n", s);
return -1;
+#if !defined(CONFIG_PAD_RECEIVED_FRAMES)
} else if (size < 64 && (s->configuration[7] & BIT(0))) {
/* Short frame and configuration byte 7/0 (discard short receive) set:
* Short frame is discarded */
logout("%p received short frame (%zu byte)\n", s, size);
s->statistics.rx_short_frame_errors++;
-#if 0
return -1;
#endif
} else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & BIT(3))) {
@@ -1731,9 +1753,11 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
"(%zu bytes); data truncated\n", rfd_size, size);
size = rfd_size;
}
+#if !defined(CONFIG_PAD_RECEIVED_FRAMES)
if (size < 64) {
rfd_status |= 0x0080;
}
+#endif
TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n",
rfd_command, rx.link, rx.rx_buf_addr, rfd_size));
stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status),
commit 27112f18f9025d537f3e6f6df3e574e7f0902cda
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat Apr 30 22:40:06 2011 +0200
eepro100: Remove unused structure element
cppcheck reports that 'packet' is unused.
It was only used to calculate the size of the preceding data.
Removing it saves a lot of stack space (local variable rx).
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 9e1883e..848bf79 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -173,7 +173,7 @@ typedef struct {
uint32_t rx_buf_addr; /* void * */
uint16_t count;
uint16_t size;
- char packet[MAX_ETH_FRAME_SIZE + 4];
+ /* Ethernet frame data follows. */
} eepro100_rx_t;
typedef enum {
@@ -1722,7 +1722,7 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
/* !!! */
eepro100_rx_t rx;
cpu_physical_memory_read(s->ru_base + s->ru_offset, &rx,
- offsetof(eepro100_rx_t, packet));
+ sizeof(eepro100_rx_t));
uint16_t rfd_command = le16_to_cpu(rx.command);
uint16_t rfd_size = le16_to_cpu(rx.size);
@@ -1753,7 +1753,7 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
assert(!(s->configuration[17] & BIT(0)));
#endif
cpu_physical_memory_write(s->ru_base + s->ru_offset +
- offsetof(eepro100_rx_t, packet), buf, size);
+ sizeof(eepro100_rx_t), buf, size);
s->statistics.rx_good_frames++;
eepro100_fr_interrupt(s);
s->ru_offset = le32_to_cpu(rx.link);
commit 77bee84e6a05f086ce40088e4dbadf28e14e4eed
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat Apr 30 22:40:05 2011 +0200
eepro100: Remove type casts which are no longer needed
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 7c24e1a..9e1883e 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -311,7 +311,7 @@ static const uint16_t eepro100_mdi_mask[] = {
static void stl_le_phys(target_phys_addr_t addr, uint32_t val)
{
val = cpu_to_le32(val);
- cpu_physical_memory_write(addr, (const uint8_t *)&val, sizeof(val));
+ cpu_physical_memory_write(addr, &val, sizeof(val));
}
#define POLYNOMIAL 0x04c11db6
@@ -694,8 +694,7 @@ static void dump_statistics(EEPRO100State * s)
* values which really matter.
* Number of data should check configuration!!!
*/
- cpu_physical_memory_write(s->statsaddr,
- (uint8_t *) & s->statistics, s->stats_size);
+ cpu_physical_memory_write(s->statsaddr, &s->statistics, s->stats_size);
stl_le_phys(s->statsaddr + 0, s->statistics.tx_good_frames);
stl_le_phys(s->statsaddr + 36, s->statistics.rx_good_frames);
stl_le_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);
@@ -709,7 +708,7 @@ static void dump_statistics(EEPRO100State * s)
static void read_cb(EEPRO100State *s)
{
- cpu_physical_memory_read(s->cb_address, (uint8_t *) &s->tx, sizeof(s->tx));
+ cpu_physical_memory_read(s->cb_address, &s->tx, sizeof(s->tx));
s->tx.status = le16_to_cpu(s->tx.status);
s->tx.command = le16_to_cpu(s->tx.command);
s->tx.link = le32_to_cpu(s->tx.link);
@@ -1268,10 +1267,10 @@ static void eepro100_write_port(EEPRO100State * s, uint32_t val)
case PORT_SELFTEST:
TRACE(OTHER, logout("selftest address=0x%08x\n", address));
eepro100_selftest_t data;
- cpu_physical_memory_read(address, (uint8_t *) & data, sizeof(data));
+ cpu_physical_memory_read(address, &data, sizeof(data));
data.st_sign = 0xffffffff;
data.st_result = 0;
- cpu_physical_memory_write(address, (uint8_t *) & data, sizeof(data));
+ cpu_physical_memory_write(address, &data, sizeof(data));
break;
case PORT_SELECTIVE_RESET:
TRACE(OTHER, logout("selective reset, selftest address=0x%08x\n", address));
@@ -1722,7 +1721,7 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size
}
/* !!! */
eepro100_rx_t rx;
- cpu_physical_memory_read(s->ru_base + s->ru_offset, (uint8_t *) & rx,
+ cpu_physical_memory_read(s->ru_base + s->ru_offset, &rx,
offsetof(eepro100_rx_t, packet));
uint16_t rfd_command = le16_to_cpu(rx.command);
uint16_t rfd_size = le16_to_cpu(rx.size);
commit 1b4f97d62e3b3d220130f1b0f59d43c042fddb89
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat Apr 30 22:40:04 2011 +0200
eepro100: Avoid duplicate debug messages
When DEBUG_EEPRO100 was enabled, unsupported writes were logged twice.
Now logging in eepro100_write1 and eepro100_write2 is similar to the
logging in eepro100_write4 (which already was correct).
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/eepro100.c b/hw/eepro100.c
index f2505e4..7c24e1a 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1,7 +1,7 @@
/*
* QEMU i8255x (PRO100) emulation
*
- * Copyright (C) 2006-2010 Stefan Weil
+ * Copyright (C) 2006-2011 Stefan Weil
*
* Portions of the code are copies from grub / etherboot eepro100.c
* and linux e100.c.
@@ -1393,18 +1393,20 @@ static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
memcpy(&s->mem[addr], &val, sizeof(val));
}
- TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
-
switch (addr) {
case SCBStatus:
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
break;
case SCBAck:
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
eepro100_acknowledge(s);
break;
case SCBCmd:
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
eepro100_write_command(s, val);
break;
case SCBIntmask:
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
if (val & BIT(1)) {
eepro100_swi_interrupt(s);
}
@@ -1418,6 +1420,7 @@ static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
break;
case SCBeeprom:
+ TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
eepro100_write_eeprom(s->eeprom, val);
break;
default:
@@ -1433,18 +1436,19 @@ static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
memcpy(&s->mem[addr], &val, sizeof(val));
}
- TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
-
switch (addr) {
case SCBStatus:
+ TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
s->mem[SCBAck] = (val >> 8);
eepro100_acknowledge(s);
break;
case SCBCmd:
+ TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
eepro100_write_command(s, val);
eepro100_write1(s, SCBIntmask, val >> 8);
break;
case SCBeeprom:
+ TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
eepro100_write_eeprom(s->eeprom, val);
break;
default:
commit ef0bdf77d7070494692cbccd80c4c8f08c85c240
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed May 4 16:49:56 2011 +0200
usb: mass storage fix
Initialize scsi_len with zero when starting a new request, so any
stuff leftover from the previous request is cleared out. This may
happen in case the data returned by the scsi command doesn't fit
into the buffer provided by the guest.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 93f4b78..bd1c3a4 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -364,6 +364,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
s->tag, cbw.flags, cbw.cmd_len, s->data_len);
s->residue = 0;
+ s->scsi_len = 0;
s->scsi_dev->info->send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
/* ??? Should check that USB and SCSI data transfer
directions match. */
commit 13a9a0d3e253e272744b523e39642c9b6d564f4d
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu Dec 16 17:03:44 2010 +0100
usb: move complete callback to port ops
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 3dd31ba..e0588f8 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -256,6 +256,19 @@ static void usb_hub_wakeup(USBDevice *dev)
}
}
+static void usb_hub_complete(USBDevice *dev, USBPacket *packet)
+{
+ USBHubState *s = dev->port->opaque;
+
+ /*
+ * Just pass it along upstream for now.
+ *
+ * If we ever inplement usb 2.0 split transactions this will
+ * become a little more complicated ...
+ */
+ usb_packet_complete(&s->dev, packet);
+}
+
static void usb_hub_handle_attach(USBDevice *dev)
{
USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
@@ -524,6 +537,7 @@ static USBPortOps usb_hub_port_ops = {
.attach = usb_hub_attach,
.detach = usb_hub_detach,
.wakeup = usb_hub_wakeup,
+ .complete = usb_hub_complete,
};
static int usb_hub_initfn(USBDevice *dev)
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 947fd3f..93f4b78 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -241,7 +241,7 @@ static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
s->mode = USB_MSDM_CSW;
}
s->packet = NULL;
- usb_packet_complete(p);
+ usb_packet_complete(&s->dev, p);
} else if (s->data_len == 0) {
s->mode = USB_MSDM_CSW;
}
@@ -257,7 +257,7 @@ static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
usb_packet_complete returns. */
DPRINTF("Packet complete %p\n", p);
s->packet = NULL;
- usb_packet_complete(p);
+ usb_packet_complete(&s->dev, p);
}
}
}
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 30148e7..b30caeb 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -261,10 +261,12 @@
static void musb_attach(USBPort *port);
static void musb_detach(USBPort *port);
+static void musb_schedule_cb(USBDevice *dev, USBPacket *p);
static USBPortOps musb_port_ops = {
.attach = musb_attach,
.detach = musb_detach,
+ .complete = musb_schedule_cb,
};
typedef struct MUSBPacket MUSBPacket;
@@ -511,9 +513,11 @@ static inline void musb_cb_tick1(void *opaque)
#define musb_cb_tick (dir ? musb_cb_tick1 : musb_cb_tick0)
-static inline void musb_schedule_cb(USBPacket *packey, void *opaque, int dir)
+static inline void musb_schedule_cb(USBDevice *dev, USBPacket *packey)
{
- MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
+ MUSBPacket *p = container_of(packey, MUSBPacket, p);
+ MUSBEndPoint *ep = p->ep;
+ int dir = p->dir;
int timeout = 0;
if (ep->status[dir] == USB_RET_NAK)
@@ -521,25 +525,15 @@ static inline void musb_schedule_cb(USBPacket *packey, void *opaque, int dir)
else if (ep->interrupt[dir])
timeout = 8;
else
- return musb_cb_tick(opaque);
+ return musb_cb_tick(ep);
if (!ep->intv_timer[dir])
- ep->intv_timer[dir] = qemu_new_timer_ns(vm_clock, musb_cb_tick, opaque);
+ ep->intv_timer[dir] = qemu_new_timer_ns(vm_clock, musb_cb_tick, ep);
qemu_mod_timer(ep->intv_timer[dir], qemu_get_clock_ns(vm_clock) +
muldiv64(timeout, get_ticks_per_sec(), 8000));
}
-static void musb_schedule0_cb(USBPacket *packey, void *opaque)
-{
- return musb_schedule_cb(packey, opaque, 0);
-}
-
-static void musb_schedule1_cb(USBPacket *packey, void *opaque)
-{
- return musb_schedule_cb(packey, opaque, 1);
-}
-
static int musb_timeout(int ttype, int speed, int val)
{
#if 1
@@ -596,7 +590,6 @@ static inline void musb_packet(MUSBState *s, MUSBEndPoint *ep,
ep->type[idx] >> 6, ep->interval[idx]);
ep->interrupt[dir] = ttype == USB_ENDPOINT_XFER_INT;
ep->delayed_cb[dir] = cb;
- cb = dir ? musb_schedule1_cb : musb_schedule0_cb;
ep->packey[dir].p.pid = pid;
/* A wild guess on the FADDR semantics... */
@@ -604,8 +597,6 @@ static inline void musb_packet(MUSBState *s, MUSBEndPoint *ep,
ep->packey[dir].p.devep = ep->type[idx] & 0xf;
ep->packey[dir].p.data = (void *) ep->buf[idx];
ep->packey[dir].p.len = len;
- ep->packey[dir].p.complete_cb = cb;
- ep->packey[dir].p.complete_opaque = ep;
ep->packey[dir].ep = ep;
ep->packey[dir].dir = dir;
@@ -620,7 +611,7 @@ static inline void musb_packet(MUSBState *s, MUSBEndPoint *ep,
}
ep->status[dir] = ret;
- usb_packet_complete(&ep->packey[dir].p);
+ usb_packet_complete(s->port.dev, &ep->packey[dir].p);
}
static void musb_tx_packet_complete(USBPacket *packey, void *opaque)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 7678cdb..8090c17 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -575,7 +575,7 @@ static void ohci_copy_iso_td(OHCIState *ohci,
static void ohci_process_lists(OHCIState *ohci, int completion);
-static void ohci_async_complete_packet(USBPacket *packet, void *opaque)
+static void ohci_async_complete_packet(USBDevice *dev, USBPacket *packet)
{
OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
#ifdef DEBUG_PACKET
@@ -748,8 +748,6 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
ohci->usb_packet.devep = OHCI_BM(ed->flags, ED_EN);
ohci->usb_packet.data = ohci->usb_buf;
ohci->usb_packet.len = len;
- ohci->usb_packet.complete_cb = ohci_async_complete_packet;
- ohci->usb_packet.complete_opaque = ohci;
ret = dev->info->handle_packet(dev, &ohci->usb_packet);
if (ret != USB_RET_NODEV)
break;
@@ -946,8 +944,6 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
ohci->usb_packet.devep = OHCI_BM(ed->flags, ED_EN);
ohci->usb_packet.data = ohci->usb_buf;
ohci->usb_packet.len = len;
- ohci->usb_packet.complete_cb = ohci_async_complete_packet;
- ohci->usb_packet.complete_opaque = ohci;
ret = dev->info->handle_packet(dev, &ohci->usb_packet);
if (ret != USB_RET_NODEV)
break;
@@ -1665,6 +1661,7 @@ static CPUWriteMemoryFunc * const ohci_writefn[3]={
static USBPortOps ohci_port_ops = {
.attach = ohci_attach,
.detach = ohci_detach,
+ .complete = ohci_async_complete_packet,
};
static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 2b63b3f..a65e0b3 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -642,7 +642,7 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
return ret;
}
-static void uhci_async_complete(USBPacket * packet, void *opaque);
+static void uhci_async_complete(USBDevice *dev, USBPacket *packet);
static void uhci_process_frame(UHCIState *s);
/* return -1 if fatal error (frame must be stopped)
@@ -795,8 +795,6 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *in
async->packet.devep = (td->token >> 15) & 0xf;
async->packet.data = async->buffer;
async->packet.len = max_len;
- async->packet.complete_cb = uhci_async_complete;
- async->packet.complete_opaque = s;
switch(pid) {
case USB_TOKEN_OUT:
@@ -832,7 +830,7 @@ done:
return len;
}
-static void uhci_async_complete(USBPacket *packet, void *opaque)
+static void uhci_async_complete(USBDevice *dev, USBPacket *packet)
{
UHCIAsync *async = container_of(packet, UHCIAsync, packet);
UHCIState *s = async->uhci;
@@ -1083,6 +1081,7 @@ static USBPortOps uhci_port_ops = {
.attach = uhci_attach,
.detach = uhci_detach,
.wakeup = uhci_wakeup,
+ .complete = uhci_async_complete,
};
static int usb_uhci_common_initfn(UHCIState *s)
diff --git a/hw/usb.h b/hw/usb.h
index 22bb338..7e46141 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -235,6 +235,7 @@ typedef struct USBPortOps {
void (*attach)(USBPort *port);
void (*detach)(USBPort *port);
void (*wakeup)(USBDevice *dev);
+ void (*complete)(USBDevice *dev, USBPacket *p);
} USBPortOps;
/* USB port on which a device can be connected */
@@ -259,8 +260,6 @@ struct USBPacket {
uint8_t *data;
int len;
/* Internal use by the USB layer. */
- USBCallback *complete_cb;
- void *complete_opaque;
USBCallback *cancel_cb;
void *cancel_opaque;
};
@@ -278,9 +277,9 @@ static inline void usb_defer_packet(USBPacket *p, USBCallback *cancel,
/* Notify the controller that an async packet is complete. This should only
be called for packets previously deferred with usb_defer_packet, and
should never be called from within handle_packet. */
-static inline void usb_packet_complete(USBPacket *p)
+static inline void usb_packet_complete(USBDevice *dev, USBPacket *p)
{
- p->complete_cb(p, p->complete_opaque);
+ dev->port->ops->complete(dev, p);
}
/* Cancel an active packet. The packed must have been deferred with
diff --git a/usb-linux.c b/usb-linux.c
index 730eac2..36a01ea 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -348,7 +348,7 @@ static void async_complete(void *opaque)
break;
}
- usb_packet_complete(p);
+ usb_packet_complete(&s->dev, p);
}
async_free(aurb);
commit 5dc1672b279344b5e4e1ba5526a8e45466b953a8
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu Dec 16 13:23:13 2010 +0100
musb: get musb state via container_of()
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 15bc549..30148e7 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -267,7 +267,16 @@ static USBPortOps musb_port_ops = {
.detach = musb_detach,
};
-typedef struct {
+typedef struct MUSBPacket MUSBPacket;
+typedef struct MUSBEndPoint MUSBEndPoint;
+
+struct MUSBPacket {
+ USBPacket p;
+ MUSBEndPoint *ep;
+ int dir;
+};
+
+struct MUSBEndPoint {
uint16_t faddr[2];
uint8_t haddr[2];
uint8_t hport[2];
@@ -284,7 +293,7 @@ typedef struct {
int fifolen[2];
int fifostart[2];
int fifoaddr[2];
- USBPacket packey[2];
+ MUSBPacket packey[2];
int status[2];
int ext_size[2];
@@ -294,7 +303,7 @@ typedef struct {
MUSBState *musb;
USBCallback *delayed_cb[2];
QEMUTimer *intv_timer[2];
-} MUSBEndPoint;
+};
struct MUSBState {
qemu_irq *irqs;
@@ -321,7 +330,9 @@ struct MUSBState {
/* Duplicating the world since 2008!... probably we should have 32
* logical, single endpoints instead. */
MUSBEndPoint ep[16];
-} *musb_init(qemu_irq *irqs)
+};
+
+struct MUSBState *musb_init(qemu_irq *irqs)
{
MUSBState *s = qemu_mallocz(sizeof(*s));
int i;
@@ -488,14 +499,14 @@ static inline void musb_cb_tick0(void *opaque)
{
MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
- ep->delayed_cb[0](&ep->packey[0], opaque);
+ ep->delayed_cb[0](&ep->packey[0].p, opaque);
}
static inline void musb_cb_tick1(void *opaque)
{
MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
- ep->delayed_cb[1](&ep->packey[1], opaque);
+ ep->delayed_cb[1](&ep->packey[1].p, opaque);
}
#define musb_cb_tick (dir ? musb_cb_tick1 : musb_cb_tick0)
@@ -587,17 +598,19 @@ static inline void musb_packet(MUSBState *s, MUSBEndPoint *ep,
ep->delayed_cb[dir] = cb;
cb = dir ? musb_schedule1_cb : musb_schedule0_cb;
- ep->packey[dir].pid = pid;
+ ep->packey[dir].p.pid = pid;
/* A wild guess on the FADDR semantics... */
- ep->packey[dir].devaddr = ep->faddr[idx];
- ep->packey[dir].devep = ep->type[idx] & 0xf;
- ep->packey[dir].data = (void *) ep->buf[idx];
- ep->packey[dir].len = len;
- ep->packey[dir].complete_cb = cb;
- ep->packey[dir].complete_opaque = ep;
+ ep->packey[dir].p.devaddr = ep->faddr[idx];
+ ep->packey[dir].p.devep = ep->type[idx] & 0xf;
+ ep->packey[dir].p.data = (void *) ep->buf[idx];
+ ep->packey[dir].p.len = len;
+ ep->packey[dir].p.complete_cb = cb;
+ ep->packey[dir].p.complete_opaque = ep;
+ ep->packey[dir].ep = ep;
+ ep->packey[dir].dir = dir;
if (s->port.dev)
- ret = s->port.dev->info->handle_packet(s->port.dev, &ep->packey[dir]);
+ ret = s->port.dev->info->handle_packet(s->port.dev, &ep->packey[dir].p);
else
ret = USB_RET_NODEV;
@@ -607,7 +620,7 @@ static inline void musb_packet(MUSBState *s, MUSBEndPoint *ep,
}
ep->status[dir] = ret;
- usb_packet_complete(&ep->packey[dir]);
+ usb_packet_complete(&ep->packey[dir].p);
}
static void musb_tx_packet_complete(USBPacket *packey, void *opaque)
@@ -821,14 +834,14 @@ static void musb_rx_req(MUSBState *s, int epnum)
/* If we already have a packet, which didn't fit into the
* 64 bytes of the FIFO, only move the FIFO start and return. (Obsolete) */
- if (ep->packey[1].pid == USB_TOKEN_IN && ep->status[1] >= 0 &&
+ if (ep->packey[1].p.pid == USB_TOKEN_IN && ep->status[1] >= 0 &&
(ep->fifostart[1]) + ep->rxcount <
- ep->packey[1].len) {
+ ep->packey[1].p.len) {
TRACE("0x%08x, %d", ep->fifostart[1], ep->rxcount );
ep->fifostart[1] += ep->rxcount;
ep->fifolen[1] = 0;
- ep->rxcount = MIN(ep->packey[0].len - (ep->fifostart[1]),
+ ep->rxcount = MIN(ep->packey[0].p.len - (ep->fifostart[1]),
ep->maxp[1]);
ep->csr[1] &= ~MGC_M_RXCSR_H_REQPKT;
@@ -866,10 +879,11 @@ static void musb_rx_req(MUSBState *s, int epnum)
#ifdef SETUPLEN_HACK
/* Why should *we* do that instead of Linux? */
if (!epnum) {
- if (ep->packey[0].devaddr == 2)
+ if (ep->packey[0].p.devaddr == 2) {
total = MIN(s->setup_len, 8);
- else
+ } else {
total = MIN(s->setup_len, 64);
+ }
s->setup_len -= total;
}
#endif
commit 9066df13a3db0b8c4c283fb6c6772da3d507c9b7
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Dec 15 11:47:19 2010 +0100
ohci: get ohci state via container_of()
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 0ad4f55..7678cdb 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -577,7 +577,7 @@ static void ohci_process_lists(OHCIState *ohci, int completion);
static void ohci_async_complete_packet(USBPacket *packet, void *opaque)
{
- OHCIState *ohci = opaque;
+ OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
#ifdef DEBUG_PACKET
DPRINTF("Async packet complete\n");
#endif
commit 7b5a44c546d9b836859c48bcfb7f1d4ef57ac3e1
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Dec 15 10:26:15 2010 +0100
uhci: keep uhci state pointer in async packet struct.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 2de0cf2..2b63b3f 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -106,6 +106,8 @@ static void dump_data(const uint8_t *data, int len)
static void dump_data(const uint8_t *data, int len) {}
#endif
+typedef struct UHCIState UHCIState;
+
/*
* Pending async transaction.
* 'packet' must be the first field because completion
@@ -113,6 +115,7 @@ static void dump_data(const uint8_t *data, int len) {}
*/
typedef struct UHCIAsync {
USBPacket packet;
+ UHCIState *uhci;
QTAILQ_ENTRY(UHCIAsync) next;
uint32_t td;
uint32_t token;
@@ -127,7 +130,7 @@ typedef struct UHCIPort {
uint16_t ctrl;
} UHCIPort;
-typedef struct UHCIState {
+struct UHCIState {
PCIDevice dev;
USBBus bus;
uint16_t cmd; /* cmd register */
@@ -147,7 +150,7 @@ typedef struct UHCIState {
/* Active packets */
QTAILQ_HEAD(,UHCIAsync) async_pending;
uint8_t num_ports_vmstate;
-} UHCIState;
+};
typedef struct UHCI_TD {
uint32_t link;
@@ -166,6 +169,7 @@ static UHCIAsync *uhci_async_alloc(UHCIState *s)
UHCIAsync *async = qemu_malloc(sizeof(UHCIAsync));
memset(&async->packet, 0, sizeof(async->packet));
+ async->uhci = s;
async->valid = 0;
async->td = 0;
async->token = 0;
@@ -830,8 +834,8 @@ done:
static void uhci_async_complete(USBPacket *packet, void *opaque)
{
- UHCIState *s = opaque;
- UHCIAsync *async = (UHCIAsync *) packet;
+ UHCIAsync *async = container_of(packet, UHCIAsync, packet);
+ UHCIState *s = async->uhci;
DPRINTF("uhci: async complete. td 0x%x token 0x%x\n", async->td, async->token);
commit ddf6583f88e29b2ec47fa81010c80868bfff7c83
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Tue Dec 14 18:19:47 2010 +0100
uhci: switch to QTAILQ
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 346db3e..2de0cf2 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -113,7 +113,7 @@ static void dump_data(const uint8_t *data, int len) {}
*/
typedef struct UHCIAsync {
USBPacket packet;
- struct UHCIAsync *next;
+ QTAILQ_ENTRY(UHCIAsync) next;
uint32_t td;
uint32_t token;
int8_t valid;
@@ -145,8 +145,7 @@ typedef struct UHCIState {
uint32_t pending_int_mask;
/* Active packets */
- UHCIAsync *async_pending;
- UHCIAsync *async_pool;
+ QTAILQ_HEAD(,UHCIAsync) async_pending;
uint8_t num_ports_vmstate;
} UHCIState;
@@ -172,7 +171,6 @@ static UHCIAsync *uhci_async_alloc(UHCIState *s)
async->token = 0;
async->done = 0;
async->isoc = 0;
- async->next = NULL;
return async;
}
@@ -184,24 +182,12 @@ static void uhci_async_free(UHCIState *s, UHCIAsync *async)
static void uhci_async_link(UHCIState *s, UHCIAsync *async)
{
- async->next = s->async_pending;
- s->async_pending = async;
+ QTAILQ_INSERT_HEAD(&s->async_pending, async, next);
}
static void uhci_async_unlink(UHCIState *s, UHCIAsync *async)
{
- UHCIAsync *curr = s->async_pending;
- UHCIAsync **prev = &s->async_pending;
-
- while (curr) {
- if (curr == async) {
- *prev = curr->next;
- return;
- }
-
- prev = &curr->next;
- curr = curr->next;
- }
+ QTAILQ_REMOVE(&s->async_pending, async, next);
}
static void uhci_async_cancel(UHCIState *s, UHCIAsync *async)
@@ -220,11 +206,10 @@ static void uhci_async_cancel(UHCIState *s, UHCIAsync *async)
*/
static UHCIAsync *uhci_async_validate_begin(UHCIState *s)
{
- UHCIAsync *async = s->async_pending;
+ UHCIAsync *async;
- while (async) {
+ QTAILQ_FOREACH(async, &s->async_pending, next) {
async->valid--;
- async = async->next;
}
return NULL;
}
@@ -234,47 +219,30 @@ static UHCIAsync *uhci_async_validate_begin(UHCIState *s)
*/
static void uhci_async_validate_end(UHCIState *s)
{
- UHCIAsync *curr = s->async_pending;
- UHCIAsync **prev = &s->async_pending;
- UHCIAsync *next;
+ UHCIAsync *curr, *n;
- while (curr) {
+ QTAILQ_FOREACH_SAFE(curr, &s->async_pending, next, n) {
if (curr->valid > 0) {
- prev = &curr->next;
- curr = curr->next;
continue;
}
-
- next = curr->next;
-
- /* Unlink */
- *prev = next;
-
+ uhci_async_unlink(s, curr);
uhci_async_cancel(s, curr);
-
- curr = next;
}
}
static void uhci_async_cancel_all(UHCIState *s)
{
- UHCIAsync *curr = s->async_pending;
- UHCIAsync *next;
-
- while (curr) {
- next = curr->next;
+ UHCIAsync *curr, *n;
+ QTAILQ_FOREACH_SAFE(curr, &s->async_pending, next, n) {
+ uhci_async_unlink(s, curr);
uhci_async_cancel(s, curr);
-
- curr = next;
}
-
- s->async_pending = NULL;
}
static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token)
{
- UHCIAsync *async = s->async_pending;
+ UHCIAsync *async;
UHCIAsync *match = NULL;
int count = 0;
@@ -291,7 +259,7 @@ static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token
* If we ever do we'd want to optimize this algorithm.
*/
- while (async) {
+ QTAILQ_FOREACH(async, &s->async_pending, next) {
if (async->token == token) {
/* Good match */
match = async;
@@ -301,8 +269,6 @@ static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token
break;
}
}
-
- async = async->next;
count++;
}
@@ -1137,6 +1103,7 @@ static int usb_uhci_common_initfn(UHCIState *s)
s->expire_time = qemu_get_clock_ns(vm_clock) +
(get_ticks_per_sec() / FRAME_TIMER_FREQ);
s->num_ports_vmstate = NB_PORTS;
+ QTAILQ_INIT(&s->async_pending);
qemu_register_reset(uhci_reset, s);
commit 19f3322379c25a235eb1ec6335676549109fa625
Author: Hans de Goede <hdegoede at redhat.com>
Date: Wed Feb 2 17:46:00 2011 +0100
usb: control buffer fixes
Windows allows control transfers to pass up to 4k of data, so raise our
control buffer size to 4k. For control out transfers the usb core code copies
the control request data to a buffer before calling the device's handle_control
callback. Add a check for overflowing the buffer before copying the data.
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/hw/usb.c b/hw/usb.c
index 82a6217..d8c0a75 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -93,6 +93,12 @@ static int do_token_setup(USBDevice *s, USBPacket *p)
s->setup_len = ret;
s->setup_state = SETUP_STATE_DATA;
} else {
+ if (s->setup_len > sizeof(s->data_buf)) {
+ fprintf(stderr,
+ "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
+ s->setup_len, sizeof(s->data_buf));
+ return USB_RET_STALL;
+ }
if (s->setup_len == 0)
s->setup_state = SETUP_STATE_ACK;
else
diff --git a/hw/usb.h b/hw/usb.h
index d3d755d..22bb338 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -167,7 +167,7 @@ struct USBDevice {
int32_t state;
uint8_t setup_buf[8];
- uint8_t data_buf[1024];
+ uint8_t data_buf[4096];
int32_t remote_wakeup;
int32_t setup_state;
int32_t setup_len;
commit bb6d5498c6756eba3d0779c7753fc8830a8a9078
Author: Hans de Goede <hdegoede at redhat.com>
Date: Fri Nov 26 19:11:03 2010 +0100
usb-linux: Add support for buffering iso out usb packets
Extend the iso buffering code to also buffer iso out packets, this
fixes for example using usb speakers with usb redirection.
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/usb-linux.c b/usb-linux.c
index 4498b16..730eac2 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -101,8 +101,10 @@ typedef struct AsyncURB AsyncURB;
struct endp_data {
uint8_t type;
uint8_t halted;
+ uint8_t iso_started;
AsyncURB *iso_urb;
int iso_urb_idx;
+ int iso_buffer_used;
int max_packet_size;
};
@@ -189,6 +191,21 @@ static void set_halt(USBHostDevice *s, int ep)
s->endp_table[ep - 1].halted = 1;
}
+static int is_iso_started(USBHostDevice *s, int ep)
+{
+ return s->endp_table[ep - 1].iso_started;
+}
+
+static void clear_iso_started(USBHostDevice *s, int ep)
+{
+ s->endp_table[ep - 1].iso_started = 0;
+}
+
+static void set_iso_started(USBHostDevice *s, int ep)
+{
+ s->endp_table[ep - 1].iso_started = 1;
+}
+
static void set_iso_urb(USBHostDevice *s, int ep, AsyncURB *iso_urb)
{
s->endp_table[ep - 1].iso_urb = iso_urb;
@@ -209,6 +226,16 @@ static int get_iso_urb_idx(USBHostDevice *s, int ep)
return s->endp_table[ep - 1].iso_urb_idx;
}
+static void set_iso_buffer_used(USBHostDevice *s, int ep, int i)
+{
+ s->endp_table[ep - 1].iso_buffer_used = i;
+}
+
+static int get_iso_buffer_used(USBHostDevice *s, int ep)
+{
+ return s->endp_table[ep - 1].iso_buffer_used;
+}
+
static int get_max_packet_size(USBHostDevice *s, int ep)
{
return s->endp_table[ep - 1].max_packet_size;
@@ -534,6 +561,8 @@ static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
else
printf("husb: leaking iso urbs because of discard failure\n");
set_iso_urb(s, ep, NULL);
+ set_iso_urb_idx(s, ep, 0);
+ clear_iso_started(s, ep);
}
static int urb_status_to_usb_ret(int status)
@@ -546,10 +575,10 @@ static int urb_status_to_usb_ret(int status)
}
}
-static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p)
+static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
{
AsyncURB *aurb;
- int i, j, ret, max_packet_size, len = 0;
+ int i, j, ret, max_packet_size, offset, len = 0;
max_packet_size = get_max_packet_size(s, p->devep);
if (max_packet_size == 0)
@@ -557,57 +586,88 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p)
aurb = get_iso_urb(s, p->devep);
if (!aurb) {
- aurb = usb_host_alloc_iso(s, p->devep, 1);
+ aurb = usb_host_alloc_iso(s, p->devep, in);
}
i = get_iso_urb_idx(s, p->devep);
j = aurb[i].iso_frame_idx;
if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
- /* Check urb status */
- if (aurb[i].urb.status) {
- len = urb_status_to_usb_ret(aurb[i].urb.status);
- /* Move to the next urb */
- aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1;
- /* Check frame status */
- } else if (aurb[i].urb.iso_frame_desc[j].status) {
- len = urb_status_to_usb_ret(aurb[i].urb.iso_frame_desc[j].status);
- /* Check the frame fits */
- } else if (aurb[i].urb.iso_frame_desc[j].actual_length > p->len) {
- printf("husb: error received isoc data is larger then packet\n");
- len = USB_RET_NAK;
- /* All good copy data over */
+ if (in) {
+ /* Check urb status */
+ if (aurb[i].urb.status) {
+ len = urb_status_to_usb_ret(aurb[i].urb.status);
+ /* Move to the next urb */
+ aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1;
+ /* Check frame status */
+ } else if (aurb[i].urb.iso_frame_desc[j].status) {
+ len = urb_status_to_usb_ret(
+ aurb[i].urb.iso_frame_desc[j].status);
+ /* Check the frame fits */
+ } else if (aurb[i].urb.iso_frame_desc[j].actual_length > p->len) {
+ printf("husb: received iso data is larger then packet\n");
+ len = USB_RET_NAK;
+ /* All good copy data over */
+ } else {
+ len = aurb[i].urb.iso_frame_desc[j].actual_length;
+ memcpy(p->data,
+ aurb[i].urb.buffer +
+ j * aurb[i].urb.iso_frame_desc[0].length,
+ len);
+ }
} else {
- len = aurb[i].urb.iso_frame_desc[j].actual_length;
- memcpy(p->data,
- aurb[i].urb.buffer +
- j * aurb[i].urb.iso_frame_desc[0].length,
- len);
+ len = p->len;
+ offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->devep);
+
+ /* Check the frame fits */
+ if (len > max_packet_size) {
+ printf("husb: send iso data is larger then max packet size\n");
+ return USB_RET_NAK;
+ }
+
+ /* All good copy data over */
+ memcpy(aurb[i].urb.buffer + offset, p->data, len);
+ aurb[i].urb.iso_frame_desc[j].length = len;
+ offset += len;
+ set_iso_buffer_used(s, p->devep, offset);
+
+ /* Start the stream once we have buffered enough data */
+ if (!is_iso_started(s, p->devep) && i == 1 && j == 8) {
+ set_iso_started(s, p->devep);
+ }
}
aurb[i].iso_frame_idx++;
if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
i = (i + 1) % ISO_URB_COUNT;
set_iso_urb_idx(s, p->devep, i);
}
+ } else {
+ if (in) {
+ set_iso_started(s, p->devep);
+ } else {
+ DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
+ }
}
- /* (Re)-submit all fully consumed urbs */
- for (i = 0; i < ISO_URB_COUNT; i++) {
- if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
- ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
- if (ret < 0) {
- printf("husb error submitting isoc urb %d: %d\n", i, errno);
- if (len == 0) {
- switch(errno) {
- case ETIMEDOUT:
- len = USB_RET_NAK;
- case EPIPE:
- default:
- len = USB_RET_STALL;
+ if (is_iso_started(s, p->devep)) {
+ /* (Re)-submit all fully consumed / filled urbs */
+ for (i = 0; i < ISO_URB_COUNT; i++) {
+ if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
+ ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
+ if (ret < 0) {
+ printf("husb error submitting iso urb %d: %d\n", i, errno);
+ if (!in || len == 0) {
+ switch(errno) {
+ case ETIMEDOUT:
+ len = USB_RET_NAK;
+ case EPIPE:
+ default:
+ len = USB_RET_STALL;
+ }
}
+ break;
}
- break;
+ aurb[i].iso_frame_idx = -1;
}
- aurb[i].iso_frame_idx = -1;
}
}
@@ -641,8 +701,9 @@ static int usb_host_handle_data(USBHostDevice *s, USBPacket *p)
clear_halt(s, p->devep);
}
- if (is_isoc(s, p->devep) && p->pid == USB_TOKEN_IN)
- return usb_host_handle_iso_data(s, p);
+ if (is_isoc(s, p->devep)) {
+ return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
+ }
aurb = async_alloc();
aurb->hdev = s;
@@ -653,19 +714,8 @@ static int usb_host_handle_data(USBHostDevice *s, USBPacket *p)
urb->endpoint = ep;
urb->buffer = p->data;
urb->buffer_length = p->len;
-
- if (is_isoc(s, p->devep)) {
- /* Setup ISOC transfer */
- urb->type = USBDEVFS_URB_TYPE_ISO;
- urb->flags = USBDEVFS_URB_ISO_ASAP;
- urb->number_of_packets = 1;
- urb->iso_frame_desc[0].length = p->len;
- } else {
- /* Setup bulk transfer */
- urb->type = USBDEVFS_URB_TYPE_BULK;
- }
-
- urb->usercontext = s;
+ urb->type = USBDEVFS_URB_TYPE_BULK;
+ urb->usercontext = s;
ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
commit 3a4854b372e0ca1a619d33531efa02477674e93f
Author: Hans de Goede <hdegoede at redhat.com>
Date: Fri Nov 26 15:02:16 2010 +0100
usb-linux: We only need to keep track of 15 endpoints
Currently we reserve room for endpoint data for 16 endpoints, but given
that we only use endpoint data for endpoints 1-15, and always index the
array with the endpoint-number - 1, 15 is enough.
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/usb-linux.c b/usb-linux.c
index 4c42fe1..4498b16 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -78,7 +78,7 @@ typedef int USBScanFunc(void *opaque, int bus_num, int addr, int devpath,
#define USBPROCBUS_PATH "/proc/bus/usb"
#define PRODUCT_NAME_SZ 32
-#define MAX_ENDPOINTS 16
+#define MAX_ENDPOINTS 15
#define USBDEVBUS_PATH "/dev/bus/usb"
#define USBSYSBUS_PATH "/sys/bus/usb"
@@ -725,7 +725,7 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
struct usbdevfs_setinterface si;
int i, ret;
- for (i = 1; i < MAX_ENDPOINTS; i++) {
+ for (i = 1; i <= MAX_ENDPOINTS; i++) {
if (is_isoc(s, i)) {
usb_host_stop_n_free_iso(s, i);
}
@@ -1276,7 +1276,7 @@ static int usb_host_close(USBHostDevice *dev)
qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
dev->closing = 1;
- for (i = 1; i < MAX_ENDPOINTS; i++) {
+ for (i = 1; i <= MAX_ENDPOINTS; i++) {
if (is_isoc(dev, i)) {
usb_host_stop_n_free_iso(dev, i);
}
commit 975f29984da4e25f2647d014ec3f4cf688c60e4d
Author: Hans de Goede <hdegoede at redhat.com>
Date: Fri Nov 26 14:59:35 2010 +0100
usb-linux: Refuse iso packets when max packet size is 0 (alt setting 0)
Refuse iso usb packets when then max packet size for the endpoint is 0,
this avoids an abort in usb_host_alloc_iso() caused by trying to qemu_malloc
a 0 bytes large buffer.
diff --git a/usb-linux.c b/usb-linux.c
index 6aef7a5..4c42fe1 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -549,7 +549,11 @@ static int urb_status_to_usb_ret(int status)
static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p)
{
AsyncURB *aurb;
- int i, j, ret, len = 0;
+ int i, j, ret, max_packet_size, len = 0;
+
+ max_packet_size = get_max_packet_size(s, p->devep);
+ if (max_packet_size == 0)
+ return USB_RET_NAK;
aurb = get_iso_urb(s, p->devep);
if (!aurb) {
commit a0b5fece8afe7deca08cbca97e2a4015d7f0038e
Author: Hans de Goede <hdegoede at redhat.com>
Date: Fri Nov 26 14:56:17 2010 +0100
usb-linux: Refuse packets for endpoints which are not in the usb descriptor
If an endpoint is not in the usb descriptor we've no idea what kind of
endpoint it is and thus how to handle it, refuse packages in this case.
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/usb-linux.c b/usb-linux.c
index a68603d..6aef7a5 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -94,6 +94,7 @@ static int usb_fs_type;
/* endpoint association data */
#define ISO_FRAME_DESC_PER_URB 32
#define ISO_URB_COUNT 3
+#define INVALID_EP_TYPE 255
typedef struct AsyncURB AsyncURB;
@@ -168,6 +169,11 @@ static int is_isoc(USBHostDevice *s, int ep)
return s->endp_table[ep - 1].type == USBDEVFS_URB_TYPE_ISO;
}
+static int is_valid(USBHostDevice *s, int ep)
+{
+ return s->endp_table[ep - 1].type != INVALID_EP_TYPE;
+}
+
static int is_halted(USBHostDevice *s, int ep)
{
return s->endp_table[ep - 1].halted;
@@ -611,6 +617,10 @@ static int usb_host_handle_data(USBHostDevice *s, USBPacket *p)
int ret;
uint8_t ep;
+ if (!is_valid(s, p->devep)) {
+ return USB_RET_NAK;
+ }
+
if (p->pid == USB_TOKEN_IN) {
ep = p->devep | 0x80;
} else {
@@ -1071,6 +1081,9 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
uint8_t devep, type, configuration, alt_interface;
int interface, length, i;
+ for (i = 0; i < MAX_ENDPOINTS; i++)
+ s->endp_table[i].type = INVALID_EP_TYPE;
+
i = usb_linux_get_configuration(s);
if (i < 0)
return 1;
commit 060dc841d117e2a2868ef50d0d30e01c90051a6f
Author: Hans de Goede <hdegoede at redhat.com>
Date: Fri Nov 26 11:41:08 2010 +0100
usb-linux: Add support for buffering iso usb packets
Currently we are submitting iso packets to the host one at a time, as we
receive them from the emulated host controller. This has 2 problems:
1) If we were fast enough to submit every packet in time for the next host host
controller usb frame, we would be generating 1000 hardware interrupts per
second on the host
2) We are not fast enough to submit every packet in time for the next host host
controller usb frame, causing us to not submit iso urbs in some usb frames
which causes devices with an endpoint with an interval of 1 ms (so every
frame) to loose data. This causes for example ubs-1.1 webcams to not work
properly (usb-2.0 is not supported at all atm).
This patch fixes both problems by changing the iso packet pass through handling
to buffer packets. This version only does so for iso input packets (webcams,
audio in) I'm working on a second patch extending this to iso output packets
(audio out).
This patch makes use of the linux batching of iso packets in one urb.
When an iso in packet gets received from the emulated host controller,
it immediately submits 3 urbs with 32 iso in packets each. This causes
the host to only get an hw interrupt every 32 packets dropping the
interrupt rate to 32 interrupts per second and gives it a queue of urbs
to work from once the first 32 iso in packets have been received to make sure
no packets are dropped.
Besides submitting a whole bunch or urbs as soon as the first urb is
received, effectively creating a buffer inside the kernel, this patch also
gets rid of the asynchroneous completion for iso in urbs. Instead they are
only marked as complete in the fd write callback (which usbfs uses to signal
complete urbs). These complete packets then get consumed by returning them
synchroneously to the emulated host controller when it submits an iso in
packet for the ep in question. When no complete packets are ready (which
happens when the stream is starting) a 0 length packet gets returned to
the emulated host controller.
With this patch I've several usb-1.1 webcams working well with usb pass
through, where as without this patch none of them work.
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/usb-linux.c b/usb-linux.c
index f4601e6..a68603d 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -92,9 +92,17 @@ static char *usb_host_device_path;
static int usb_fs_type;
/* endpoint association data */
+#define ISO_FRAME_DESC_PER_URB 32
+#define ISO_URB_COUNT 3
+
+typedef struct AsyncURB AsyncURB;
+
struct endp_data {
uint8_t type;
uint8_t halted;
+ AsyncURB *iso_urb;
+ int iso_urb_idx;
+ int max_packet_size;
};
enum {
@@ -175,19 +183,48 @@ static void set_halt(USBHostDevice *s, int ep)
s->endp_table[ep - 1].halted = 1;
}
+static void set_iso_urb(USBHostDevice *s, int ep, AsyncURB *iso_urb)
+{
+ s->endp_table[ep - 1].iso_urb = iso_urb;
+}
+
+static AsyncURB *get_iso_urb(USBHostDevice *s, int ep)
+{
+ return s->endp_table[ep - 1].iso_urb;
+}
+
+static void set_iso_urb_idx(USBHostDevice *s, int ep, int i)
+{
+ s->endp_table[ep - 1].iso_urb_idx = i;
+}
+
+static int get_iso_urb_idx(USBHostDevice *s, int ep)
+{
+ return s->endp_table[ep - 1].iso_urb_idx;
+}
+
+static int get_max_packet_size(USBHostDevice *s, int ep)
+{
+ return s->endp_table[ep - 1].max_packet_size;
+}
+
/*
* Async URB state.
- * We always allocate one isoc descriptor even for bulk transfers
+ * We always allocate iso packet descriptors even for bulk transfers
* to simplify allocation and casts.
*/
-typedef struct AsyncURB
+struct AsyncURB
{
struct usbdevfs_urb urb;
- struct usbdevfs_iso_packet_desc isocpd;
+ struct usbdevfs_iso_packet_desc isocpd[ISO_FRAME_DESC_PER_URB];
+ /* For regular async urbs */
USBPacket *packet;
USBHostDevice *hdev;
-} AsyncURB;
+
+ /* For buffered iso handling */
+ int iso_frame_idx; /* -1 means in flight */
+};
static AsyncURB *async_alloc(void)
{
@@ -244,11 +281,21 @@ static void async_complete(void *opaque)
return;
}
- p = aurb->packet;
-
DPRINTF("husb: async completed. aurb %p status %d alen %d\n",
aurb, aurb->urb.status, aurb->urb.actual_length);
+ /* If this is a buffered iso urb mark it as complete and don't do
+ anything else (it is handled further in usb_host_handle_iso_data) */
+ if (aurb->iso_frame_idx == -1) {
+ if (aurb->urb.status == -EPIPE) {
+ set_halt(s, aurb->urb.endpoint & 0xf);
+ }
+ aurb->iso_frame_idx = 0;
+ continue;
+ }
+
+ p = aurb->packet;
+
if (p) {
switch (aurb->urb.status) {
case 0:
@@ -415,34 +462,181 @@ static void usb_host_handle_destroy(USBDevice *dev)
static int usb_linux_update_endp_table(USBHostDevice *s);
+/* iso data is special, we need to keep enough urbs in flight to make sure
+ that the controller never runs out of them, otherwise the device will
+ likely suffer a buffer underrun / overrun. */
+static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, uint8_t ep, int in)
+{
+ AsyncURB *aurb;
+ int i, j, len = get_max_packet_size(s, ep);
+
+ aurb = qemu_mallocz(ISO_URB_COUNT * sizeof(*aurb));
+ for (i = 0; i < ISO_URB_COUNT; i++) {
+ aurb[i].urb.endpoint = ep;
+ aurb[i].urb.buffer_length = ISO_FRAME_DESC_PER_URB * len;
+ aurb[i].urb.buffer = qemu_malloc(aurb[i].urb.buffer_length);
+ aurb[i].urb.type = USBDEVFS_URB_TYPE_ISO;
+ aurb[i].urb.flags = USBDEVFS_URB_ISO_ASAP;
+ aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB;
+ for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++)
+ aurb[i].urb.iso_frame_desc[j].length = len;
+ if (in) {
+ aurb[i].urb.endpoint |= 0x80;
+ /* Mark as fully consumed (idle) */
+ aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB;
+ }
+ }
+ set_iso_urb(s, ep, aurb);
+
+ return aurb;
+}
+
+static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
+{
+ AsyncURB *aurb;
+ int i, ret, killed = 0, free = 1;
+
+ aurb = get_iso_urb(s, ep);
+ if (!aurb) {
+ return;
+ }
+
+ for (i = 0; i < ISO_URB_COUNT; i++) {
+ /* in flight? */
+ if (aurb[i].iso_frame_idx == -1) {
+ ret = ioctl(s->fd, USBDEVFS_DISCARDURB, &aurb[i]);
+ if (ret < 0) {
+ printf("husb: discard isoc in urb failed errno %d\n", errno);
+ free = 0;
+ continue;
+ }
+ killed++;
+ }
+ }
+
+ /* Make sure any urbs we've killed are reaped before we free them */
+ if (killed) {
+ async_complete(s);
+ }
+
+ for (i = 0; i < ISO_URB_COUNT; i++) {
+ qemu_free(aurb[i].urb.buffer);
+ }
+
+ if (free)
+ qemu_free(aurb);
+ else
+ printf("husb: leaking iso urbs because of discard failure\n");
+ set_iso_urb(s, ep, NULL);
+}
+
+static int urb_status_to_usb_ret(int status)
+{
+ switch (status) {
+ case -EPIPE:
+ return USB_RET_STALL;
+ default:
+ return USB_RET_NAK;
+ }
+}
+
+static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p)
+{
+ AsyncURB *aurb;
+ int i, j, ret, len = 0;
+
+ aurb = get_iso_urb(s, p->devep);
+ if (!aurb) {
+ aurb = usb_host_alloc_iso(s, p->devep, 1);
+ }
+
+ i = get_iso_urb_idx(s, p->devep);
+ j = aurb[i].iso_frame_idx;
+ if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
+ /* Check urb status */
+ if (aurb[i].urb.status) {
+ len = urb_status_to_usb_ret(aurb[i].urb.status);
+ /* Move to the next urb */
+ aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1;
+ /* Check frame status */
+ } else if (aurb[i].urb.iso_frame_desc[j].status) {
+ len = urb_status_to_usb_ret(aurb[i].urb.iso_frame_desc[j].status);
+ /* Check the frame fits */
+ } else if (aurb[i].urb.iso_frame_desc[j].actual_length > p->len) {
+ printf("husb: error received isoc data is larger then packet\n");
+ len = USB_RET_NAK;
+ /* All good copy data over */
+ } else {
+ len = aurb[i].urb.iso_frame_desc[j].actual_length;
+ memcpy(p->data,
+ aurb[i].urb.buffer +
+ j * aurb[i].urb.iso_frame_desc[0].length,
+ len);
+ }
+ aurb[i].iso_frame_idx++;
+ if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
+ i = (i + 1) % ISO_URB_COUNT;
+ set_iso_urb_idx(s, p->devep, i);
+ }
+ }
+
+ /* (Re)-submit all fully consumed urbs */
+ for (i = 0; i < ISO_URB_COUNT; i++) {
+ if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
+ ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
+ if (ret < 0) {
+ printf("husb error submitting isoc urb %d: %d\n", i, errno);
+ if (len == 0) {
+ switch(errno) {
+ case ETIMEDOUT:
+ len = USB_RET_NAK;
+ case EPIPE:
+ default:
+ len = USB_RET_STALL;
+ }
+ }
+ break;
+ }
+ aurb[i].iso_frame_idx = -1;
+ }
+ }
+
+ return len;
+}
+
static int usb_host_handle_data(USBHostDevice *s, USBPacket *p)
{
struct usbdevfs_urb *urb;
AsyncURB *aurb;
int ret;
-
- aurb = async_alloc();
- aurb->hdev = s;
- aurb->packet = p;
-
- urb = &aurb->urb;
+ uint8_t ep;
if (p->pid == USB_TOKEN_IN) {
- urb->endpoint = p->devep | 0x80;
+ ep = p->devep | 0x80;
} else {
- urb->endpoint = p->devep;
+ ep = p->devep;
}
if (is_halted(s, p->devep)) {
- ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &urb->endpoint);
+ ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &ep);
if (ret < 0) {
DPRINTF("husb: failed to clear halt. ep 0x%x errno %d\n",
- urb->endpoint, errno);
+ ep, errno);
return USB_RET_NAK;
}
clear_halt(s, p->devep);
}
+ if (is_isoc(s, p->devep) && p->pid == USB_TOKEN_IN)
+ return usb_host_handle_iso_data(s, p);
+
+ aurb = async_alloc();
+ aurb->hdev = s;
+ aurb->packet = p;
+
+ urb = &aurb->urb;
+
+ urb->endpoint = ep;
urb->buffer = p->data;
urb->buffer_length = p->len;
@@ -515,7 +709,13 @@ static int usb_host_set_config(USBHostDevice *s, int config)
static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
{
struct usbdevfs_setinterface si;
- int ret;
+ int i, ret;
+
+ for (i = 1; i < MAX_ENDPOINTS; i++) {
+ if (is_isoc(s, i)) {
+ usb_host_stop_n_free_iso(s, i);
+ }
+ }
si.interface = iface;
si.altsetting = alt;
@@ -927,6 +1127,8 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
break;
case 0x01:
type = USBDEVFS_URB_TYPE_ISO;
+ s->endp_table[(devep & 0xf) - 1].max_packet_size =
+ descriptors[i + 4] + (descriptors[i + 5] << 8);
break;
case 0x02:
type = USBDEVFS_URB_TYPE_BULK;
@@ -1049,12 +1251,19 @@ fail:
static int usb_host_close(USBHostDevice *dev)
{
+ int i;
+
if (dev->fd == -1) {
return -1;
}
qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
dev->closing = 1;
+ for (i = 1; i < MAX_ENDPOINTS; i++) {
+ if (is_isoc(dev, i)) {
+ usb_host_stop_n_free_iso(dev, i);
+ }
+ }
async_complete(dev);
dev->closing = 0;
usb_device_detach(&dev->dev);
commit c43831fb47e4ee51967870c7b5deb08789b0874c
Author: Hans de Goede <hdegoede at redhat.com>
Date: Wed Nov 24 12:57:59 2010 +0100
usb-linux: Get the alt. setting from sysfs rather then asking the dev
At least one device I have lies when receiving a USB_REQ_GET_INTERFACE,
always returning 0 even if the alternate setting is different. This is
likely caused because in practice this control message is never used as
the operating system's usb stack knows which alternate setting it has
told the device to get into, and thus this ctrl message does not get
tested by device manufacturers.
When usb_fs_type == USB_FS_SYS, the active alt. setting can be read directly
from sysfs, which allows using this device through qemu's usb redirection.
More in general it seems a good idea to not send needless control msg's to
devices, esp. as the code in question is called every time a set_interface
is done. Which happens multiple times during virtual machine startup, and
when device drivers are activating the usb device.
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/usb-linux.c b/usb-linux.c
index 353e1b1..f4601e6 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -830,6 +830,24 @@ static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
struct usb_ctrltransfer ct;
int ret;
+ if (usb_fs_type == USB_FS_SYS) {
+ char device_name[64], line[1024];
+ int alt_setting;
+
+ sprintf(device_name, "%d-%d:%d.%d", s->bus_num, s->devpath,
+ (int)configuration, (int)interface);
+
+ if (!usb_host_read_file(line, sizeof(line), "bAlternateSetting",
+ device_name)) {
+ goto usbdevfs;
+ }
+ if (sscanf(line, "%d", &alt_setting) != 1) {
+ goto usbdevfs;
+ }
+ return alt_setting;
+ }
+
+usbdevfs:
ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE;
ct.bRequest = USB_REQ_GET_INTERFACE;
ct.wValue = 0;
commit ed3a328db9d9a027092edc2c17348068e3271cef
Author: Hans de Goede <hdegoede at redhat.com>
Date: Wed Nov 24 12:50:00 2010 +0100
usb-linux: introduce a usb_linux_alt_setting function
The next patch in this series introduces multiple ways to get the
alt setting dependent upon usb_fs_type, it is cleaner to put this
into its own function.
Note that this patch also changes the assumed alt setting in case
of an error getting the alt setting to be 0 (a sane default) rather
then the interface numberwhich makes no sense.
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/usb-linux.c b/usb-linux.c
index 1f33c2c..353e1b1 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -823,13 +823,35 @@ usbdevfs:
return configuration;
}
+static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
+ uint8_t configuration, uint8_t interface)
+{
+ uint8_t alt_setting;
+ struct usb_ctrltransfer ct;
+ int ret;
+
+ ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE;
+ ct.bRequest = USB_REQ_GET_INTERFACE;
+ ct.wValue = 0;
+ ct.wIndex = interface;
+ ct.wLength = 1;
+ ct.data = &alt_setting;
+ ct.timeout = 50;
+ ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
+ if (ret < 0) {
+ /* Assume alt 0 on error */
+ return 0;
+ }
+
+ return alt_setting;
+}
+
/* returns 1 on problem encountered or 0 for success */
static int usb_linux_update_endp_table(USBHostDevice *s)
{
uint8_t *descriptors;
uint8_t devep, type, configuration, alt_interface;
- struct usb_ctrltransfer ct;
- int interface, ret, length, i;
+ int interface, length, i;
i = usb_linux_get_configuration(s);
if (i < 0)
@@ -858,19 +880,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
}
interface = descriptors[i + 2];
-
- ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE;
- ct.bRequest = USB_REQ_GET_INTERFACE;
- ct.wValue = 0;
- ct.wIndex = interface;
- ct.wLength = 1;
- ct.data = &alt_interface;
- ct.timeout = 50;
-
- ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
- if (ret < 0) {
- alt_interface = interface;
- }
+ alt_interface = usb_linux_get_alt_setting(s, configuration, interface);
/* the current interface descriptor is the active interface
* and has endpoints */
commit 196a778428989217b82de042725dc8eb29c8f8d8
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Apr 27 16:06:10 2011 +0200
spice: drop obsolete iothread locking
We don't use qemu internals from spice server context any more.
Thus we don't also need to grab the iothread mutex from spice
server context. And we don't have to temporarely release the
lock to avoid deadlocks. Drop all the calls.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/qxl.c b/hw/qxl.c
index 4dfddf0..2bb36c6 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -666,10 +666,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm)
dprint(d, 1, "%s: start%s\n", __FUNCTION__,
loadvm ? " (loadvm)" : "");
- qemu_mutex_unlock_iothread();
d->ssd.worker->reset_cursor(d->ssd.worker);
d->ssd.worker->reset_image_cache(d->ssd.worker);
- qemu_mutex_lock_iothread();
qxl_reset_surfaces(d);
qxl_reset_memslots(d);
@@ -799,9 +797,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
{
dprint(d, 1, "%s:\n", __FUNCTION__);
d->mode = QXL_MODE_UNDEFINED;
- qemu_mutex_unlock_iothread();
d->ssd.worker->destroy_surfaces(d->ssd.worker);
- qemu_mutex_lock_iothread();
memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds));
}
@@ -870,9 +866,7 @@ static void qxl_destroy_primary(PCIQXLDevice *d)
dprint(d, 1, "%s\n", __FUNCTION__);
d->mode = QXL_MODE_UNDEFINED;
- qemu_mutex_unlock_iothread();
d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
- qemu_mutex_lock_iothread();
}
static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
@@ -942,10 +936,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val)
case QXL_IO_UPDATE_AREA:
{
QXLRect update = d->ram->update_area;
- qemu_mutex_unlock_iothread();
d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface,
&update, NULL, 0, 0);
- qemu_mutex_lock_iothread();
break;
}
case QXL_IO_NOTIFY_CMD:
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 8579bfd..15f0704 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -176,18 +176,14 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
surface.mem = (intptr_t)ssd->buf;
surface.group_id = MEMSLOT_GROUP_HOST;
- qemu_mutex_unlock_iothread();
ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
- qemu_mutex_lock_iothread();
}
void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
{
dprint(1, "%s:\n", __FUNCTION__);
- qemu_mutex_unlock_iothread();
ssd->worker->destroy_primary_surface(ssd->worker, 0);
- qemu_mutex_lock_iothread();
}
void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
@@ -197,9 +193,7 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
if (running) {
ssd->worker->start(ssd->worker);
} else {
- qemu_mutex_unlock_iothread();
ssd->worker->stop(ssd->worker);
- qemu_mutex_lock_iothread();
}
ssd->running = running;
}
commit 075360945860ad9bdd491921954b383bf762b0e5
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Apr 27 15:50:32 2011 +0200
spice: don't call displaystate callbacks from spice server context.
This patch moves the displaystate callback calls for setting the cursor
and the mouse pointer from spice server to qemu (iothread) context.
This allows us to simplify locking.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 58965e0..1316066 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -185,7 +185,6 @@ void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
QXLCursor *cursor;
QEMUCursor *c;
- int x = -1, y = -1;
if (!qxl->ssd.ds->mouse_set || !qxl->ssd.ds->cursor_define) {
return;
@@ -198,8 +197,6 @@ void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
}
switch (cmd->type) {
case QXL_CURSOR_SET:
- x = cmd->u.set.position.x;
- y = cmd->u.set.position.y;
cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id);
if (cursor->chunk.data_size != cursor->data_size) {
fprintf(stderr, "%s: multiple chunks\n", __FUNCTION__);
@@ -209,18 +206,20 @@ void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
if (c == NULL) {
c = cursor_builtin_left_ptr();
}
- qemu_mutex_lock_iothread();
- qxl->ssd.ds->cursor_define(c);
- qxl->ssd.ds->mouse_set(x, y, 1);
- qemu_mutex_unlock_iothread();
- cursor_put(c);
+ qemu_mutex_lock(&qxl->ssd.lock);
+ if (qxl->ssd.cursor) {
+ cursor_put(qxl->ssd.cursor);
+ }
+ qxl->ssd.cursor = c;
+ qxl->ssd.mouse_x = cmd->u.set.position.x;
+ qxl->ssd.mouse_y = cmd->u.set.position.y;
+ qemu_mutex_unlock(&qxl->ssd.lock);
break;
case QXL_CURSOR_MOVE:
- x = cmd->u.position.x;
- y = cmd->u.position.y;
- qemu_mutex_lock_iothread();
- qxl->ssd.ds->mouse_set(x, y, 1);
- qemu_mutex_unlock_iothread();
+ qemu_mutex_lock(&qxl->ssd.lock);
+ qxl->ssd.mouse_x = cmd->u.position.x;
+ qxl->ssd.mouse_y = cmd->u.position.y;
+ qemu_mutex_unlock(&qxl->ssd.lock);
break;
}
}
diff --git a/hw/qxl.c b/hw/qxl.c
index bd250db..4dfddf0 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1309,6 +1309,8 @@ static int qxl_init_primary(PCIDevice *dev)
qxl_hw_screen_dump, qxl_hw_text_update, qxl);
qxl->ssd.ds = vga->ds;
qemu_mutex_init(&qxl->ssd.lock);
+ qxl->ssd.mouse_x = -1;
+ qxl->ssd.mouse_y = -1;
qxl->ssd.bufsize = (16 * 1024 * 1024);
qxl->ssd.buf = qemu_malloc(qxl->ssd.bufsize);
diff --git a/ui/spice-display.c b/ui/spice-display.c
index d56dcfc..8579bfd 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -254,6 +254,16 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
ssd->update = qemu_spice_create_update(ssd);
ssd->notify++;
}
+ if (ssd->cursor) {
+ ssd->ds->cursor_define(ssd->cursor);
+ cursor_put(ssd->cursor);
+ ssd->cursor = NULL;
+ }
+ if (ssd->mouse_x != -1 && ssd->mouse_y != -1) {
+ ssd->ds->mouse_set(ssd->mouse_x, ssd->mouse_y, 1);
+ ssd->mouse_x = -1;
+ ssd->mouse_y = -1;
+ }
qemu_mutex_unlock(&ssd->lock);
if (ssd->notify) {
@@ -409,6 +419,8 @@ void qemu_spice_display_init(DisplayState *ds)
assert(sdpy.ds == NULL);
sdpy.ds = ds;
qemu_mutex_init(&sdpy.lock);
+ sdpy.mouse_x = -1;
+ sdpy.mouse_y = -1;
sdpy.bufsize = (16 * 1024 * 1024);
sdpy.buf = qemu_malloc(sdpy.bufsize);
register_displaychangelistener(ds, &display_listener);
diff --git a/ui/spice-display.h b/ui/spice-display.h
index e0cc46e..2f95f68 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -20,6 +20,7 @@
#include <spice/qxl_dev.h>
#include "qemu-thread.h"
+#include "console.h"
#include "pflib.h"
#define NUM_MEMSLOTS 8
@@ -55,6 +56,8 @@ struct SimpleSpiceDisplay {
*/
QemuMutex lock;
SimpleSpiceUpdate *update;
+ QEMUCursor *cursor;
+ int mouse_x, mouse_y;
};
struct SimpleSpiceUpdate {
commit e0c64d08d11736dcea7c5a6373e3e7f62db51d9e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Apr 27 15:21:51 2011 +0200
spice: don't create updates in spice server context.
This patch moves the creation of spice screen updates from the spice
server context to qemu iothread context (display refresh timer to be
exact). This way we avoid accessing qemu internals (display surface)
from spice thread context which in turn allows us to simplify locking.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/qxl.c b/hw/qxl.c
index fe4212b..bd250db 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -343,18 +343,22 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
SimpleSpiceUpdate *update;
QXLCommandRing *ring;
QXLCommand *cmd;
- int notify;
+ int notify, ret;
switch (qxl->mode) {
case QXL_MODE_VGA:
dprint(qxl, 2, "%s: vga\n", __FUNCTION__);
- update = qemu_spice_create_update(&qxl->ssd);
- if (update == NULL) {
- return false;
+ ret = false;
+ qemu_mutex_lock(&qxl->ssd.lock);
+ if (qxl->ssd.update != NULL) {
+ update = qxl->ssd.update;
+ qxl->ssd.update = NULL;
+ *ext = update->ext;
+ ret = true;
}
- *ext = update->ext;
+ qemu_mutex_unlock(&qxl->ssd.lock);
qxl_log_command(qxl, "vga", ext);
- return true;
+ return ret;
case QXL_MODE_COMPAT:
case QXL_MODE_NATIVE:
case QXL_MODE_UNDEFINED:
@@ -1304,6 +1308,7 @@ static int qxl_init_primary(PCIDevice *dev)
vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
qxl_hw_screen_dump, qxl_hw_text_update, qxl);
qxl->ssd.ds = vga->ds;
+ qemu_mutex_init(&qxl->ssd.lock);
qxl->ssd.bufsize = (16 * 1024 * 1024);
qxl->ssd.buf = qemu_malloc(qxl->ssd.bufsize);
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 020b423..d56dcfc 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -62,14 +62,7 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
dest->right = MAX(dest->right, r->right);
}
-/*
- * Called from spice server thread context (via interface_get_command).
- *
- * We must aquire the global qemu mutex here to make sure the
- * DisplayState (+DisplaySurface) we are accessing doesn't change
- * underneath us.
- */
-SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
+static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
{
SimpleSpiceUpdate *update;
QXLDrawable *drawable;
@@ -78,9 +71,7 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
uint8_t *src, *dst;
int by, bw, bh;
- qemu_mutex_lock_iothread();
if (qemu_spice_rect_is_empty(&ssd->dirty)) {
- qemu_mutex_unlock_iothread();
return NULL;
};
@@ -141,7 +132,6 @@ SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
cmd->data = (intptr_t)drawable;
memset(&ssd->dirty, 0, sizeof(ssd->dirty));
- qemu_mutex_unlock_iothread();
return update;
}
@@ -241,6 +231,12 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
qemu_pf_conv_put(ssd->conv);
ssd->conv = NULL;
+ qemu_mutex_lock(&ssd->lock);
+ if (ssd->update != NULL) {
+ qemu_spice_destroy_update(ssd, ssd->update);
+ ssd->update = NULL;
+ }
+ qemu_mutex_unlock(&ssd->lock);
qemu_spice_destroy_host_primary(ssd);
qemu_spice_create_host_primary(ssd);
@@ -252,6 +248,14 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
{
dprint(3, "%s:\n", __FUNCTION__);
vga_hw_update();
+
+ qemu_mutex_lock(&ssd->lock);
+ if (ssd->update == NULL) {
+ ssd->update = qemu_spice_create_update(ssd);
+ ssd->notify++;
+ }
+ qemu_mutex_unlock(&ssd->lock);
+
if (ssd->notify) {
ssd->notify = 0;
ssd->worker->wakeup(ssd->worker);
@@ -298,14 +302,20 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
{
SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
SimpleSpiceUpdate *update;
+ int ret = false;
dprint(3, "%s:\n", __FUNCTION__);
- update = qemu_spice_create_update(ssd);
- if (update == NULL) {
- return false;
+
+ qemu_mutex_lock(&ssd->lock);
+ if (ssd->update != NULL) {
+ update = ssd->update;
+ ssd->update = NULL;
+ *ext = update->ext;
+ ret = true;
}
- *ext = update->ext;
- return true;
+ qemu_mutex_unlock(&ssd->lock);
+
+ return ret;
}
static int interface_req_cmd_notification(QXLInstance *sin)
@@ -398,6 +408,7 @@ void qemu_spice_display_init(DisplayState *ds)
{
assert(sdpy.ds == NULL);
sdpy.ds = ds;
+ qemu_mutex_init(&sdpy.lock);
sdpy.bufsize = (16 * 1024 * 1024);
sdpy.buf = qemu_malloc(sdpy.bufsize);
register_displaychangelistener(ds, &display_listener);
diff --git a/ui/spice-display.h b/ui/spice-display.h
index aef0464..e0cc46e 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -19,6 +19,7 @@
#include <spice/enums.h>
#include <spice/qxl_dev.h>
+#include "qemu-thread.h"
#include "pflib.h"
#define NUM_MEMSLOTS 8
@@ -31,7 +32,10 @@
#define NUM_SURFACES 1024
-typedef struct SimpleSpiceDisplay {
+typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
+typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
+
+struct SimpleSpiceDisplay {
DisplayState *ds;
void *buf;
int bufsize;
@@ -43,19 +47,26 @@ typedef struct SimpleSpiceDisplay {
QXLRect dirty;
int notify;
int running;
-} SimpleSpiceDisplay;
-typedef struct SimpleSpiceUpdate {
+ /*
+ * All struct members below this comment can be accessed from
+ * both spice server and qemu (iothread) context and any access
+ * to them must be protected by the lock.
+ */
+ QemuMutex lock;
+ SimpleSpiceUpdate *update;
+};
+
+struct SimpleSpiceUpdate {
QXLDrawable drawable;
QXLImage image;
QXLCommandExt ext;
uint8_t *bitmap;
-} SimpleSpiceUpdate;
+};
int qemu_spice_rect_is_empty(const QXLRect* r);
void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r);
-SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *sdpy);
void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update);
void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd);
void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd);
commit 14da8345b2f7c21bab20fd12b755a61d6277f171
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Tue Feb 1 15:53:23 2011 +0100
Make spice dummy functions inline to fix calls not checking return values
qemu_spice_set_passwd() and qemu_spice_set_pw_expire() dummy functions
needs to be inline, in order to handle the case where they are called
without checking the return value.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h
index 916e5dc..3c6f1fe 100644
--- a/ui/qemu-spice.h
+++ b/ui/qemu-spice.h
@@ -47,8 +47,16 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts);
#else /* CONFIG_SPICE */
#define using_spice 0
-#define qemu_spice_set_passwd(_p, _f1, _f2) (-1)
-#define qemu_spice_set_pw_expire(_e) (-1)
+static inline int qemu_spice_set_passwd(const char *passwd,
+ bool fail_if_connected,
+ bool disconnect_if_connected)
+{
+ return -1;
+}
+static inline int qemu_spice_set_pw_expire(time_t expires)
+{
+ return -1;
+}
static inline int qemu_spice_migrate_info(const char *h, int p, int t, const char *s)
{ return -1; }
commit 22f3647b781ab36f654de4ec29997f549f979c97
Author: Avi Kivity <avi at redhat.com>
Date: Mon Apr 4 18:28:07 2011 +0300
wdt_i6300esb: convert to pci_register_bar_simple()
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 4a7fba7..0791721 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -355,31 +355,6 @@ static void i6300esb_mem_writel(void *vp, target_phys_addr_t addr, uint32_t val)
}
}
-static void i6300esb_map(PCIDevice *dev, int region_num,
- pcibus_t addr, pcibus_t size, int type)
-{
- static CPUReadMemoryFunc * const mem_read[3] = {
- i6300esb_mem_readb,
- i6300esb_mem_readw,
- i6300esb_mem_readl,
- };
- static CPUWriteMemoryFunc * const mem_write[3] = {
- i6300esb_mem_writeb,
- i6300esb_mem_writew,
- i6300esb_mem_writel,
- };
- I6300State *d = DO_UPCAST(I6300State, dev, dev);
- int io_mem;
-
- i6300esb_debug("addr = %"FMT_PCIBUS", size = %"FMT_PCIBUS", type = %d\n",
- addr, size, type);
-
- io_mem = cpu_register_io_memory(mem_read, mem_write, d,
- DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory (addr, 0x10, io_mem);
- /* qemu_register_coalesced_mmio (addr, 0x10); ? */
-}
-
static const VMStateDescription vmstate_i6300esb = {
.name = "i6300esb_wdt",
.version_id = sizeof(I6300State),
@@ -407,6 +382,17 @@ static int i6300esb_init(PCIDevice *dev)
{
I6300State *d = DO_UPCAST(I6300State, dev, dev);
uint8_t *pci_conf;
+ int io_mem;
+ static CPUReadMemoryFunc * const mem_read[3] = {
+ i6300esb_mem_readb,
+ i6300esb_mem_readw,
+ i6300esb_mem_readl,
+ };
+ static CPUWriteMemoryFunc * const mem_write[3] = {
+ i6300esb_mem_writeb,
+ i6300esb_mem_writew,
+ i6300esb_mem_writel,
+ };
i6300esb_debug("I6300State = %p\n", d);
@@ -418,8 +404,10 @@ static int i6300esb_init(PCIDevice *dev)
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_ESB_9);
pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER);
- pci_register_bar(&d->dev, 0, 0x10,
- PCI_BASE_ADDRESS_SPACE_MEMORY, i6300esb_map);
+ io_mem = cpu_register_io_memory(mem_read, mem_write, d,
+ DEVICE_NATIVE_ENDIAN);
+ pci_register_bar_simple(&d->dev, 0, 0x10, 0, io_mem);
+ /* qemu_register_coalesced_mmio (addr, 0x10); ? */
return 0;
}
commit 6e964ded1e791aaaab270b5f04af5cd23c60c514
Author: Avi Kivity <avi at redhat.com>
Date: Mon Apr 4 18:28:06 2011 +0300
usb-ohci: convert to pci_register_bar_simple()
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index d2b14f7..73d47b8 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1713,13 +1713,6 @@ typedef struct {
OHCIState state;
} OHCIPCIState;
-static void ohci_mapfunc(PCIDevice *pci_dev, int i,
- pcibus_t addr, pcibus_t size, int type)
-{
- OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, pci_dev);
- cpu_register_physical_memory(addr, size, ohci->state.mem);
-}
-
static int usb_ohci_initfn_pci(struct PCIDevice *dev)
{
OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
@@ -1737,8 +1730,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
ohci->state.irq = ohci->pci_dev.irq[0];
/* TODO: avoid cast below by using dev */
- pci_register_bar(&ohci->pci_dev, 0, 256,
- PCI_BASE_ADDRESS_SPACE_MEMORY, ohci_mapfunc);
+ pci_register_bar_simple(&ohci->pci_dev, 0, 256, 0, ohci->state.mem);
return 0;
}
commit 27a4154324b9de74b8621c83980fd82ac80f3b8f
Author: Avi Kivity <avi at redhat.com>
Date: Mon Apr 4 18:28:05 2011 +0300
pcnet-pci: convert to pci_register_bar_simple()
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 339a401..4ac3e32 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -214,19 +214,6 @@ static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
&pcnet_mmio_readl
};
-static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
- pcibus_t addr, pcibus_t size, int type)
-{
- PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
-
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
- addr, size);
-#endif
-
- cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
-}
-
static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap)
{
@@ -300,8 +287,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE,
PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
- pci_register_bar(pci_dev, 1, PCNET_PNPMMIO_SIZE,
- PCI_BASE_ADDRESS_SPACE_MEMORY, pcnet_mmio_map);
+ pci_register_bar_simple(pci_dev, 1, PCNET_PNPMMIO_SIZE, 0, s->mmio_index);
s->irq = pci_dev->irq[0];
s->phys_mem_read = pci_physical_memory_read;
commit 667bb59d2358daeef179583c944becba3f1f9680
Author: Avi Kivity <avi at redhat.com>
Date: Mon Apr 4 18:28:02 2011 +0300
ich/ahci: convert to pci_register_bar_simple()
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 98bdf70..c6e0c77 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1129,15 +1129,6 @@ void ahci_uninit(AHCIState *s)
qemu_free(s->dev);
}
-void ahci_pci_map(PCIDevice *pci_dev, int region_num,
- pcibus_t addr, pcibus_t size, int type)
-{
- struct AHCIPCIState *d = (struct AHCIPCIState *)pci_dev;
- AHCIState *s = &d->ahci;
-
- cpu_register_physical_memory(addr, size, s->mem);
-}
-
void ahci_reset(void *opaque)
{
struct AHCIPCIState *d = opaque;
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index a4560c4..dc86951 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -325,9 +325,6 @@ typedef struct NCQFrame {
void ahci_init(AHCIState *s, DeviceState *qdev, int ports);
void ahci_uninit(AHCIState *s);
-void ahci_pci_map(PCIDevice *pci_dev, int region_num,
- pcibus_t addr, pcibus_t size, int type);
-
void ahci_reset(void *opaque);
#endif /* HW_IDE_AHCI_H */
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index f242d7a..eb00f03 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -95,8 +95,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
qemu_register_reset(ahci_reset, d);
/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
- pci_register_bar(&d->card, 5, 0x1000, PCI_BASE_ADDRESS_SPACE_MEMORY,
- ahci_pci_map);
+ pci_register_bar_simple(&d->card, 5, 0x1000, 0, d->ahci.mem);
msi_init(dev, 0x50, 1, true, false);
commit f32dd06ba6299e6c9174e94bd0ac9e4f7828bd78
Author: Avi Kivity <avi at redhat.com>
Date: Mon Apr 4 18:28:04 2011 +0300
hda-intel: convert to pci_register_bar_simple() (partial)
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 84a4992..6c811cf 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2037,15 +2037,6 @@ static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
cpu_register_physical_memory(addr + 0, 0x2000, s->ram_io_addr);
}
-static void lsi_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
- pcibus_t addr, pcibus_t size, int type)
-{
- LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
-
- DPRINTF("Mapping registers at %08"FMT_PCIBUS"\n", addr);
- cpu_register_physical_memory(addr + 0, 0x400, s->mmio_io_addr);
-}
-
static void lsi_scsi_reset(DeviceState *dev)
{
LSIState *s = DO_UPCAST(LSIState, dev.qdev, dev);
@@ -2188,8 +2179,7 @@ static int lsi_scsi_init(PCIDevice *dev)
pci_register_bar(&s->dev, 0, 256,
PCI_BASE_ADDRESS_SPACE_IO, lsi_io_mapfunc);
- pci_register_bar(&s->dev, 1, 0x400,
- PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_mmio_mapfunc);
+ pci_register_bar_simple(&s->dev, 1, 0x400, 0, s->mmio_io_addr);
pci_register_bar(&s->dev, 2, 0x2000,
PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc);
QTAILQ_INIT(&s->queue);
commit d28ca60a47f59bc6e36d9c3167ed59b866e63630
Author: Avi Kivity <avi at redhat.com>
Date: Mon Apr 4 18:28:03 2011 +0300
hda-intel: convert to pci_register_bar_simple()
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index b0b1d12..7f83745 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -1109,14 +1109,6 @@ static CPUWriteMemoryFunc * const intel_hda_mmio_write[3] = {
intel_hda_mmio_writel,
};
-static void intel_hda_map(PCIDevice *pci, int region_num,
- pcibus_t addr, pcibus_t size, int type)
-{
- IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
-
- cpu_register_physical_memory(addr, 0x4000, d->mmio_addr);
-}
-
/* --------------------------------------------------------------------- */
static void intel_hda_reset(DeviceState *dev)
@@ -1158,8 +1150,7 @@ static int intel_hda_init(PCIDevice *pci)
d->mmio_addr = cpu_register_io_memory(intel_hda_mmio_read,
intel_hda_mmio_write, d,
DEVICE_NATIVE_ENDIAN);
- pci_register_bar(&d->pci, 0, 0x4000, PCI_BASE_ADDRESS_SPACE_MEMORY,
- intel_hda_map);
+ pci_register_bar_simple(&d->pci, 0, 0x4000, 0, d->mmio_addr);
if (d->msi) {
msi_init(&d->pci, 0x50, 1, true, false);
}
commit 22ec60937a8004fc10597b78fdfe5014bb0c37bc
Author: Avi Kivity <avi at redhat.com>
Date: Mon Apr 4 18:28:01 2011 +0300
eepro100: convert to pci_register_bar_simple()
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/eepro100.c b/hw/eepro100.c
index edf48f6..f2505e4 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -228,7 +228,7 @@ typedef struct {
uint8_t scb_stat; /* SCB stat/ack byte */
uint8_t int_stat; /* PCI interrupt status */
/* region must not be saved by nic_save. */
- uint32_t region[3]; /* PCI region addresses */
+ uint32_t region1; /* PCI region 1 address */
uint16_t mdimem[32];
eeprom_t *eeprom;
uint32_t device; /* device variant */
@@ -1488,19 +1488,19 @@ static uint32_t ioport_read1(void *opaque, uint32_t addr)
#if 0
logout("addr=%s\n", regname(addr));
#endif
- return eepro100_read1(s, addr - s->region[1]);
+ return eepro100_read1(s, addr - s->region1);
}
static uint32_t ioport_read2(void *opaque, uint32_t addr)
{
EEPRO100State *s = opaque;
- return eepro100_read2(s, addr - s->region[1]);
+ return eepro100_read2(s, addr - s->region1);
}
static uint32_t ioport_read4(void *opaque, uint32_t addr)
{
EEPRO100State *s = opaque;
- return eepro100_read4(s, addr - s->region[1]);
+ return eepro100_read4(s, addr - s->region1);
}
static void ioport_write1(void *opaque, uint32_t addr, uint32_t val)
@@ -1509,19 +1509,19 @@ static void ioport_write1(void *opaque, uint32_t addr, uint32_t val)
#if 0
logout("addr=%s val=0x%02x\n", regname(addr), val);
#endif
- eepro100_write1(s, addr - s->region[1], val);
+ eepro100_write1(s, addr - s->region1, val);
}
static void ioport_write2(void *opaque, uint32_t addr, uint32_t val)
{
EEPRO100State *s = opaque;
- eepro100_write2(s, addr - s->region[1], val);
+ eepro100_write2(s, addr - s->region1, val);
}
static void ioport_write4(void *opaque, uint32_t addr, uint32_t val)
{
EEPRO100State *s = opaque;
- eepro100_write4(s, addr - s->region[1], val);
+ eepro100_write4(s, addr - s->region1, val);
}
/***********************************************************/
@@ -1544,7 +1544,7 @@ static void pci_map(PCIDevice * pci_dev, int region_num,
register_ioport_write(addr, size, 4, ioport_write4, s);
register_ioport_read(addr, size, 4, ioport_read4, s);
- s->region[region_num] = addr;
+ s->region1 = addr;
}
/*****************************************************************************
@@ -1619,22 +1619,6 @@ static CPUReadMemoryFunc * const pci_mmio_read[] = {
pci_mmio_readl
};
-static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
- pcibus_t addr, pcibus_t size, int type)
-{
- EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
-
- TRACE(OTHER, logout("region %d, addr=0x%08"FMT_PCIBUS", "
- "size=0x%08"FMT_PCIBUS", type=%d\n",
- region_num, addr, size, type));
-
- assert(region_num == 0 || region_num == 2);
-
- /* Map control / status registers and flash. */
- cpu_register_physical_memory(addr, size, s->mmio_index);
- s->region[region_num] = addr;
-}
-
static int nic_can_receive(VLANClientState *nc)
{
EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
@@ -1882,17 +1866,16 @@ static int e100_nic_init(PCIDevice *pci_dev)
cpu_register_io_memory(pci_mmio_read, pci_mmio_write, s,
DEVICE_NATIVE_ENDIAN);
- pci_register_bar(&s->dev, 0, PCI_MEM_SIZE,
- PCI_BASE_ADDRESS_SPACE_MEMORY |
- PCI_BASE_ADDRESS_MEM_PREFETCH, pci_mmio_map);
+ pci_register_bar_simple(&s->dev, 0, PCI_MEM_SIZE,
+ PCI_BASE_ADDRESS_MEM_PREFETCH, s->mmio_index);
+
pci_register_bar(&s->dev, 1, PCI_IO_SIZE, PCI_BASE_ADDRESS_SPACE_IO,
pci_map);
- pci_register_bar(&s->dev, 2, PCI_FLASH_SIZE, PCI_BASE_ADDRESS_SPACE_MEMORY,
- pci_mmio_map);
+ pci_register_bar_simple(&s->dev, 2, PCI_FLASH_SIZE, 0, s->mmio_index);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
logout("macaddr: %s\n", nic_dump(&s->conf.macaddr.a[0], 6));
- assert(s->region[1] == 0);
+ assert(s->region1 == 0);
nic_reset(s);
commit e30376da4b7ba5c5d0ea7ce49d775ce38e5194c8
Author: Avi Kivity <avi at redhat.com>
Date: Mon Apr 4 18:28:00 2011 +0300
cirrus-vga: convert to pci_register_bar_simple()
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 7212849..722cac7 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3081,15 +3081,6 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
vga_dirty_log_start(&s->vga);
}
-static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
- pcibus_t addr, pcibus_t size, int type)
-{
- CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
-
- cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
- s->cirrus_mmio_io_addr);
-}
-
static void pci_cirrus_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
@@ -3128,8 +3119,8 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
pci_register_bar(&d->dev, 0, 0x2000000,
PCI_BASE_ADDRESS_MEM_PREFETCH, cirrus_pci_lfb_map);
if (device_id == CIRRUS_ID_CLGD5446) {
- pci_register_bar(&d->dev, 1, CIRRUS_PNPMMIO_SIZE,
- PCI_BASE_ADDRESS_SPACE_MEMORY, cirrus_pci_mmio_map);
+ pci_register_bar_simple(&d->dev, 1, CIRRUS_PNPMMIO_SIZE, 0,
+ s->cirrus_mmio_io_addr);
}
return 0;
}
commit f5de212c4c022dd5eb49e9223201bb702d9f33ab
Author: Avi Kivity <avi at redhat.com>
Date: Mon Apr 4 18:27:59 2011 +0300
rtl8139: convert to pci_register_bar_simple()
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index d545933..822038d 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3341,14 +3341,6 @@ static const VMStateDescription vmstate_rtl8139 = {
/***********************************************************/
/* PCI RTL8139 definitions */
-static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
- pcibus_t addr, pcibus_t size, int type)
-{
- RTL8139State *s = DO_UPCAST(RTL8139State, dev, pci_dev);
-
- cpu_register_physical_memory(addr + 0, 0x100, s->rtl8139_mmio_io_addr);
-}
-
static void rtl8139_ioport_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
@@ -3444,8 +3436,7 @@ static int pci_rtl8139_init(PCIDevice *dev)
pci_register_bar(&s->dev, 0, 0x100,
PCI_BASE_ADDRESS_SPACE_IO, rtl8139_ioport_map);
- pci_register_bar(&s->dev, 1, 0x100,
- PCI_BASE_ADDRESS_SPACE_MEMORY, rtl8139_mmio_map);
+ pci_register_bar_simple(&s->dev, 1, 0x100, 0, s->rtl8139_mmio_io_addr);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
commit 17cbcb0bf79c605aecaab3661dc8bad627e4cb3b
Author: Avi Kivity <avi at redhat.com>
Date: Mon Apr 4 18:27:58 2011 +0300
pci: add pci_register_bar_simple() API
This is similar to pci_register_bar(), but automatically registers a single
memory region spanning the entire BAR.
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/pci.c b/hw/pci.c
index 3ee4871..410b67b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -866,6 +866,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
r->filtered_size = size;
r->type = type;
r->map_func = map_func;
+ r->ram_addr = IO_MEM_UNASSIGNED;
wmask = ~(size - 1);
addr = pci_bar(pci_dev, region_num);
@@ -884,6 +885,22 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
}
}
+static void pci_simple_bar_mapfunc(PCIDevice *pci_dev, int region_num,
+ pcibus_t addr, pcibus_t size, int type)
+{
+ cpu_register_physical_memory(addr, size,
+ pci_dev->io_regions[region_num].ram_addr);
+}
+
+void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
+ pcibus_t size, uint8_t attr, ram_addr_t ram_addr)
+{
+ pci_register_bar(pci_dev, region_num, size,
+ PCI_BASE_ADDRESS_SPACE_MEMORY | attr,
+ pci_simple_bar_mapfunc);
+ pci_dev->io_regions[region_num].ram_addr = ram_addr;
+}
+
static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
uint8_t type)
{
diff --git a/hw/pci.h b/hw/pci.h
index a5f875d..c6a6eb6 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -92,6 +92,7 @@ typedef struct PCIIORegion {
pcibus_t filtered_size;
uint8_t type;
PCIMapIORegionFunc *map_func;
+ ram_addr_t ram_addr;
} PCIIORegion;
#define PCI_ROM_SLOT 6
@@ -200,6 +201,8 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
void pci_register_bar(PCIDevice *pci_dev, int region_num,
pcibus_t size, uint8_t type,
PCIMapIORegionFunc *map_func);
+void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
+ pcibus_t size, uint8_t attr, ram_addr_t ram_addr);
int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
uint8_t offset, uint8_t size);
commit af94482bcee9640d9f8a6aa06104d8456bbe0d7f
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Wed Apr 6 22:54:18 2011 +0300
cirrus_vga: flag on-device ram for dirty logging
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index bdf4c8b..7212849 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2489,7 +2489,9 @@ static void map_linear_vram(CirrusVGAState *s)
if (!s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
s->vga.map_addr = s->vga.lfb_addr;
s->vga.map_end = s->vga.lfb_end;
- cpu_register_physical_memory(s->vga.map_addr, s->vga.map_end - s->vga.map_addr, s->vga.vram_offset);
+ cpu_register_physical_memory_log(s->vga.map_addr,
+ s->vga.map_end - s->vga.map_addr,
+ s->vga.vram_offset, 0, true);
}
if (!s->vga.map_addr)
@@ -2502,10 +2504,14 @@ static void map_linear_vram(CirrusVGAState *s)
&& !((s->vga.gr[0x0B] & 0x14) == 0x14)
&& !(s->vga.gr[0x0B] & 0x02)) {
- cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000,
- (s->vga.vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM);
- cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000,
- (s->vga.vram_offset + s->cirrus_bank_base[1]) | IO_MEM_RAM);
+ cpu_register_physical_memory_log(isa_mem_base + 0xa0000, 0x8000,
+ (s->vga.vram_offset +
+ s->cirrus_bank_base[0]) |
+ IO_MEM_RAM, 0, true);
+ cpu_register_physical_memory_log(isa_mem_base + 0xa8000, 0x8000,
+ (s->vga.vram_offset +
+ s->cirrus_bank_base[1]) |
+ IO_MEM_RAM, 0, true);
s->vga.lfb_vram_mapped = 1;
}
commit 4e789564d30a9c5f9408657857560a88386b0ac4
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Thu Mar 31 15:45:51 2011 +0200
vhost: optimize out no-change assignment
Cirrus VGA (at least) calls register memory region
with the same values again and again. The
registration in vhost-net slows this a lot,
optimize by checking that the same data is already registered.
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/vhost.c b/hw/vhost.c
index 257e3dd..80f771e 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -297,6 +297,45 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
return 0;
}
+static struct vhost_memory_region *vhost_dev_find_reg(struct vhost_dev *dev,
+ uint64_t start_addr,
+ uint64_t size)
+{
+ int i, n = dev->mem->nregions;
+ for (i = 0; i < n; ++i) {
+ struct vhost_memory_region *reg = dev->mem->regions + i;
+ if (ranges_overlap(reg->guest_phys_addr, reg->memory_size,
+ start_addr, size)) {
+ return reg;
+ }
+ }
+ return NULL;
+}
+
+static bool vhost_dev_cmp_memory(struct vhost_dev *dev,
+ uint64_t start_addr,
+ uint64_t size,
+ uint64_t uaddr)
+{
+ struct vhost_memory_region *reg = vhost_dev_find_reg(dev, start_addr, size);
+ uint64_t reglast;
+ uint64_t memlast;
+
+ if (!reg) {
+ return true;
+ }
+
+ reglast = range_get_last(reg->guest_phys_addr, reg->memory_size);
+ memlast = range_get_last(start_addr, size);
+
+ /* Need to extend region? */
+ if (start_addr < reg->guest_phys_addr || memlast > reglast) {
+ return true;
+ }
+ /* userspace_addr changed? */
+ return uaddr != reg->userspace_addr + start_addr - reg->guest_phys_addr;
+}
+
static void vhost_client_set_memory(CPUPhysMemoryClient *client,
target_phys_addr_t start_addr,
ram_addr_t size,
@@ -309,6 +348,7 @@ static void vhost_client_set_memory(CPUPhysMemoryClient *client,
(dev->mem->nregions + 1) * sizeof dev->mem->regions[0];
uint64_t log_size;
int r;
+
dev->mem = qemu_realloc(dev->mem, s);
if (log_dirty) {
@@ -317,6 +357,20 @@ static void vhost_client_set_memory(CPUPhysMemoryClient *client,
assert(size);
+ /* Optimize no-change case. At least cirrus_vga does this a lot at this time. */
+ if (flags == IO_MEM_RAM) {
+ if (!vhost_dev_cmp_memory(dev, start_addr, size,
+ (uintptr_t)qemu_get_ram_ptr(phys_offset))) {
+ /* Region exists with same address. Nothing to do. */
+ return;
+ }
+ } else {
+ if (!vhost_dev_find_reg(dev, start_addr, size)) {
+ /* Removing region that we don't access. Nothing to do. */
+ return;
+ }
+ }
+
vhost_dev_unassign_memory(dev, start_addr, size);
if (flags == IO_MEM_RAM) {
/* Add given mapping, merging adjacent regions if any */
commit f5a4e64f8e12d088a11b9a2743875cc88671e13a
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Wed Apr 6 22:30:24 2011 +0300
vhost: skip memory which needs dirty logging
vhost doesn't support write logging
(except for migration), anyway.
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/vhost.c b/hw/vhost.c
index dc3d0e2..257e3dd 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -311,6 +311,10 @@ static void vhost_client_set_memory(CPUPhysMemoryClient *client,
int r;
dev->mem = qemu_realloc(dev->mem, s);
+ if (log_dirty) {
+ flags = IO_MEM_UNASSIGNED;
+ }
+
assert(size);
vhost_dev_unassign_memory(dev, start_addr, size);
commit 25254bbc4d91408b6be706d095e3fbc60a972db4
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Wed Apr 6 22:09:54 2011 +0300
kvm: halve number of set memory calls for vga
use the new api to reduce the number of these (expensive)
system calls.
Note: using this API, we should be able to
get rid of vga_dirty_log_xxx APIs. Using them doesn't
affect the performance though because we detects
the log_dirty flag set and ignores the call.
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/kvm-all.c b/kvm-all.c
index 1647e1a..7ace9a2 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -245,48 +245,60 @@ err:
/*
* dirty pages logging control
*/
-static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
- ram_addr_t size, int flags, int mask)
+
+static int kvm_mem_flags(KVMState *s, bool log_dirty)
+{
+ return log_dirty ? KVM_MEM_LOG_DIRTY_PAGES : 0;
+}
+
+static int kvm_slot_dirty_pages_log_change(KVMSlot *mem, bool log_dirty)
{
KVMState *s = kvm_state;
- KVMSlot *mem = kvm_lookup_matching_slot(s, phys_addr, phys_addr + size);
+ int flags, mask = KVM_MEM_LOG_DIRTY_PAGES;
int old_flags;
- if (mem == NULL) {
- fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-"
- TARGET_FMT_plx "\n", __func__, phys_addr,
- (target_phys_addr_t)(phys_addr + size - 1));
- return -EINVAL;
- }
-
old_flags = mem->flags;
- flags = (mem->flags & ~mask) | flags;
+ flags = (mem->flags & ~mask) | kvm_mem_flags(s, log_dirty);
mem->flags = flags;
/* If nothing changed effectively, no need to issue ioctl */
if (s->migration_log) {
flags |= KVM_MEM_LOG_DIRTY_PAGES;
}
+
if (flags == old_flags) {
- return 0;
+ return 0;
}
return kvm_set_user_memory_region(s, mem);
}
+static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
+ ram_addr_t size, bool log_dirty)
+{
+ KVMState *s = kvm_state;
+ KVMSlot *mem = kvm_lookup_matching_slot(s, phys_addr, phys_addr + size);
+
+ if (mem == NULL) {
+ fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-"
+ TARGET_FMT_plx "\n", __func__, phys_addr,
+ (target_phys_addr_t)(phys_addr + size - 1));
+ return -EINVAL;
+ }
+ return kvm_slot_dirty_pages_log_change(mem, log_dirty);
+}
+
static int kvm_log_start(CPUPhysMemoryClient *client,
target_phys_addr_t phys_addr, ram_addr_t size)
{
- return kvm_dirty_pages_log_change(phys_addr, size, KVM_MEM_LOG_DIRTY_PAGES,
- KVM_MEM_LOG_DIRTY_PAGES);
+ return kvm_dirty_pages_log_change(phys_addr, size, true);
}
static int kvm_log_stop(CPUPhysMemoryClient *client,
target_phys_addr_t phys_addr, ram_addr_t size)
{
- return kvm_dirty_pages_log_change(phys_addr, size, 0,
- KVM_MEM_LOG_DIRTY_PAGES);
+ return kvm_dirty_pages_log_change(phys_addr, size, false);
}
static int kvm_set_migration_log(int enable)
@@ -495,7 +507,7 @@ kvm_check_extension_list(KVMState *s, const KVMCapabilityInfo *list)
}
static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
- ram_addr_t phys_offset)
+ ram_addr_t phys_offset, bool log_dirty)
{
KVMState *s = kvm_state;
ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
@@ -520,7 +532,8 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
(start_addr + size <= mem->start_addr + mem->memory_size) &&
(phys_offset - start_addr == mem->phys_offset - mem->start_addr)) {
/* The new slot fits into the existing one and comes with
- * identical parameters - nothing to be done. */
+ * identical parameters - update flags and done. */
+ kvm_slot_dirty_pages_log_change(mem, log_dirty);
return;
}
@@ -550,7 +563,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
mem->memory_size = old.memory_size;
mem->start_addr = old.start_addr;
mem->phys_offset = old.phys_offset;
- mem->flags = 0;
+ mem->flags = kvm_mem_flags(s, log_dirty);
err = kvm_set_user_memory_region(s, mem);
if (err) {
@@ -571,7 +584,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
mem->memory_size = start_addr - old.start_addr;
mem->start_addr = old.start_addr;
mem->phys_offset = old.phys_offset;
- mem->flags = 0;
+ mem->flags = kvm_mem_flags(s, log_dirty);
err = kvm_set_user_memory_region(s, mem);
if (err) {
@@ -590,7 +603,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
size_delta = mem->start_addr - old.start_addr;
mem->memory_size = old.memory_size - size_delta;
mem->phys_offset = old.phys_offset + size_delta;
- mem->flags = 0;
+ mem->flags = kvm_mem_flags(s, log_dirty);
err = kvm_set_user_memory_region(s, mem);
if (err) {
@@ -613,7 +626,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
mem->memory_size = size;
mem->start_addr = start_addr;
mem->phys_offset = phys_offset;
- mem->flags = 0;
+ mem->flags = kvm_mem_flags(s, log_dirty);
err = kvm_set_user_memory_region(s, mem);
if (err) {
@@ -628,7 +641,7 @@ static void kvm_client_set_memory(struct CPUPhysMemoryClient *client,
ram_addr_t size, ram_addr_t phys_offset,
bool log_dirty)
{
- kvm_set_phys_mem(start_addr, size, phys_offset);
+ kvm_set_phys_mem(start_addr, size, phys_offset, log_dirty);
}
static int kvm_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,
commit 0fd542fb7d13ddf12f897bb27c5950f31638b1df
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Wed Apr 6 22:25:38 2011 +0300
cpu: add set_memory flag to request dirty logging
Pass the flag to all cpu notifiers, doing
nothing at this point. Will be used by
follow-up patches.
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/cpu-common.h b/cpu-common.h
index ef4e8da..c239cc0 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -34,10 +34,21 @@ typedef unsigned long ram_addr_t;
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
-void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
- ram_addr_t size,
- ram_addr_t phys_offset,
- ram_addr_t region_offset);
+void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
+ ram_addr_t size,
+ ram_addr_t phys_offset,
+ ram_addr_t region_offset,
+ bool log_dirty);
+
+static inline void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
+ ram_addr_t size,
+ ram_addr_t phys_offset,
+ ram_addr_t region_offset)
+{
+ cpu_register_physical_memory_log(start_addr, size, phys_offset,
+ region_offset, false);
+}
+
static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
@@ -91,7 +102,8 @@ struct CPUPhysMemoryClient {
void (*set_memory)(struct CPUPhysMemoryClient *client,
target_phys_addr_t start_addr,
ram_addr_t size,
- ram_addr_t phys_offset);
+ ram_addr_t phys_offset,
+ bool log_dirty);
int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client,
target_phys_addr_t start_addr,
target_phys_addr_t end_addr);
diff --git a/exec.c b/exec.c
index 964ce31..d1a066c 100644
--- a/exec.c
+++ b/exec.c
@@ -1711,11 +1711,12 @@ static QLIST_HEAD(memory_client_list, CPUPhysMemoryClient) memory_client_list
static void cpu_notify_set_memory(target_phys_addr_t start_addr,
ram_addr_t size,
- ram_addr_t phys_offset)
+ ram_addr_t phys_offset,
+ bool log_dirty)
{
CPUPhysMemoryClient *client;
QLIST_FOREACH(client, &memory_client_list, list) {
- client->set_memory(client, start_addr, size, phys_offset);
+ client->set_memory(client, start_addr, size, phys_offset, log_dirty);
}
}
@@ -1755,7 +1756,7 @@ static void phys_page_for_each_1(CPUPhysMemoryClient *client,
for (i = 0; i < L2_SIZE; ++i) {
if (pd[i].phys_offset != IO_MEM_UNASSIGNED) {
client->set_memory(client, pd[i].region_offset,
- TARGET_PAGE_SIZE, pd[i].phys_offset);
+ TARGET_PAGE_SIZE, pd[i].phys_offset, false);
}
}
} else {
@@ -2600,10 +2601,11 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
start_addr and region_offset are rounded down to a page boundary
before calculating this offset. This should not be a problem unless
the low bits of start_addr and region_offset differ. */
-void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
+void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset,
- ram_addr_t region_offset)
+ ram_addr_t region_offset,
+ bool log_dirty)
{
target_phys_addr_t addr, end_addr;
PhysPageDesc *p;
@@ -2611,7 +2613,7 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
ram_addr_t orig_size = size;
subpage_t *subpage;
- cpu_notify_set_memory(start_addr, size, phys_offset);
+ cpu_notify_set_memory(start_addr, size, phys_offset, log_dirty);
if (phys_offset == IO_MEM_UNASSIGNED) {
region_offset = start_addr;
diff --git a/hw/vhost.c b/hw/vhost.c
index 14b571d..dc3d0e2 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -300,7 +300,8 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
static void vhost_client_set_memory(CPUPhysMemoryClient *client,
target_phys_addr_t start_addr,
ram_addr_t size,
- ram_addr_t phys_offset)
+ ram_addr_t phys_offset,
+ bool log_dirty)
{
struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
diff --git a/kvm-all.c b/kvm-all.c
index 1d7e8ea..1647e1a 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -625,7 +625,8 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
static void kvm_client_set_memory(struct CPUPhysMemoryClient *client,
target_phys_addr_t start_addr,
- ram_addr_t size, ram_addr_t phys_offset)
+ ram_addr_t size, ram_addr_t phys_offset,
+ bool log_dirty)
{
kvm_set_phys_mem(start_addr, size, phys_offset);
}
commit afe3ef1d01dd767b6824c0580ecb92f6a27b75cc
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Fri Apr 1 20:43:24 2011 +0900
piix_pci: load path clean up
The previous patch didn't change the behavior when load,
it resulted in ugly code. This patch cleans it up.
With this patch, pic irq lines are manipulated when loaded.
It is expected that it won't change the behaviour because
the interrupts are level: at the moment e.g. pci devices already
reassert interrupts on load.
Test:
- rung linux as guest and use flooding ping (ping -f) to host
in order to trigger interrupts for e1000 emulated.
- savevm/loadvm and see guest kept running after loadvm.
To be honest, I'm not sure that ping -f caused enough interrupts
because Linux e1000 driver supports NAPI.
TODO: test more OSes, stress test with save/load, live-migration
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 7ffb821..5f0d92f 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -281,8 +281,7 @@ static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
(pic_irq * PIIX_NUM_PIRQS))));
}
-static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level,
- bool propagate)
+static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level)
{
int pic_irq;
uint64_t mask;
@@ -296,15 +295,13 @@ static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level,
piix3->pic_levels &= ~mask;
piix3->pic_levels |= mask * !!level;
- if (propagate) {
- piix3_set_irq_pic(piix3, pic_irq);
- }
+ piix3_set_irq_pic(piix3, pic_irq);
}
static void piix3_set_irq(void *opaque, int pirq, int level)
{
PIIX3State *piix3 = opaque;
- piix3_set_irq_level(piix3, pirq, level, true);
+ piix3_set_irq_level(piix3, pirq, level);
}
/* irq routing is changed. so rebuild bitmap */
@@ -315,8 +312,7 @@ static void piix3_update_irq_levels(PIIX3State *piix3)
piix3->pic_levels = 0;
for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
piix3_set_irq_level(piix3, pirq,
- pci_bus_get_irq_level(piix3->dev.bus, pirq),
- false);
+ pci_bus_get_irq_level(piix3->dev.bus, pirq));
}
}
commit ab431c283e7055bcd6fb622f212bb29e84a6a134
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Fri Apr 1 20:43:23 2011 +0900
piix_pci: optimize set irq path
optimize irq routing in piix_pic.c which has been a TODO.
So far piix3 tracks each pirq level and checks whether a given pic pins is
asserted by seeing if each pirq is mapped into the pic pin.
This is independent on irq routing, but data path is on slow path.
Given that irq routing is rarely changed and asserting pic pins is on
data path, the path that asserts pic pins should be optimized and
chainging irq routing should be on slow path.
The new behavior with this patch series is to use bitmap which is addressed
by pirq and pic pins with a given irq routing.
When pirq is asserted, the bitmap is set and see if the pic pins is
asserted by checking the bitmaps.
When irq routing is changed, rebuild the bitmap and re-assert pic pins.
test:
- create VM with 4 e1000 nics in different pci slots
(i.e. fn=0 for each e1000)
Thus those e1000's INTA are connected to each PIRQ[A-D].
- run linux as guest and saw each devices triggers interrupt
by seeing /proc/interrupts. And then confirmed that each PIRQ[A-D]
surely asserted interrupts.
Because irq 10 and 11 are shared by 4 e1000's, it only one NIC is activated
with ifconfig ethN up/down when counting interrupts.
Cc: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 35e420c..7ffb821 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -37,10 +37,27 @@
typedef PCIHostState I440FXState;
+#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */
#define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */
+#define PIIX_PIRQC 0x60
typedef struct PIIX3State {
PCIDevice dev;
+
+ /*
+ * bitmap to track pic levels.
+ * The pic level is the logical OR of all the PCI irqs mapped to it
+ * So one PIC level is tracked by PIIX_NUM_PIRQS bits.
+ *
+ * PIRQ is mapped to PIC pins, we track it by
+ * PIIX_NUM_PIRQS * PIIX_NUM_PIC_IRQS = 64 bits with
+ * pic_irq * PIIX_NUM_PIRQS + pirq
+ */
+#if PIIX_NUM_PIC_IRQS * PIIX_NUM_PIRQS > 64
+#error "unable to encode pic state in 64bit in pic_levels."
+#endif
+ uint64_t pic_levels;
+
qemu_irq *pic;
/* This member isn't used. Just for save/load compatibility */
@@ -59,16 +76,16 @@ struct PCII440FXState {
#define I440FX_PAM_SIZE 7
#define I440FX_SMRAM 0x72
-static void piix3_set_irq(void *opaque, int irq_num, int level);
+static void piix3_set_irq(void *opaque, int pirq, int level);
/* return the global irq number corresponding to a given device irq
pin. We could also use the bus number to have a more precise
mapping. */
-static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx)
{
int slot_addend;
slot_addend = (pci_dev->devfn >> 3) - 1;
- return (irq_num + slot_addend) & 3;
+ return (pci_intx + slot_addend) & 3;
}
static void update_pam(PCII440FXState *d, uint32_t start, uint32_t end, int r)
@@ -256,25 +273,64 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *
}
/* PIIX3 PCI to ISA bridge */
+static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
+{
+ qemu_set_irq(piix3->pic[pic_irq],
+ !!(piix3->pic_levels &
+ (((1UL << PIIX_NUM_PIRQS) - 1) <<
+ (pic_irq * PIIX_NUM_PIRQS))));
+}
-static void piix3_set_irq(void *opaque, int irq_num, int level)
+static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level,
+ bool propagate)
+{
+ int pic_irq;
+ uint64_t mask;
+
+ pic_irq = piix3->dev.config[PIIX_PIRQC + pirq];
+ if (pic_irq >= PIIX_NUM_PIC_IRQS) {
+ return;
+ }
+
+ mask = 1ULL << ((pic_irq * PIIX_NUM_PIRQS) + pirq);
+ piix3->pic_levels &= ~mask;
+ piix3->pic_levels |= mask * !!level;
+
+ if (propagate) {
+ piix3_set_irq_pic(piix3, pic_irq);
+ }
+}
+
+static void piix3_set_irq(void *opaque, int pirq, int level)
{
- int i, pic_irq, pic_level;
PIIX3State *piix3 = opaque;
+ piix3_set_irq_level(piix3, pirq, level, true);
+}
- /* now we change the pic irq level according to the piix irq mappings */
- /* XXX: optimize */
- pic_irq = piix3->dev.config[0x60 + irq_num];
- if (pic_irq < 16) {
- /* The pic level is the logical OR of all the PCI irqs mapped
- to it */
- pic_level = 0;
- for (i = 0; i < 4; i++) {
- if (pic_irq == piix3->dev.config[0x60 + i]) {
- pic_level |= pci_bus_get_irq_level(piix3->dev.bus, i);
- }
+/* irq routing is changed. so rebuild bitmap */
+static void piix3_update_irq_levels(PIIX3State *piix3)
+{
+ int pirq;
+
+ piix3->pic_levels = 0;
+ for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
+ piix3_set_irq_level(piix3, pirq,
+ pci_bus_get_irq_level(piix3->dev.bus, pirq),
+ false);
+ }
+}
+
+static void piix3_write_config(PCIDevice *dev,
+ uint32_t address, uint32_t val, int len)
+{
+ pci_default_write_config(dev, address, val, len);
+ if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
+ PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
+ int pic_irq;
+ piix3_update_irq_levels(piix3);
+ for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
+ piix3_set_irq_pic(piix3, pic_irq);
}
- qemu_set_irq(piix3->pic[pic_irq], pic_level);
}
}
@@ -314,6 +370,15 @@ static void piix3_reset(void *opaque)
pci_conf[0xab] = 0x00;
pci_conf[0xac] = 0x00;
pci_conf[0xae] = 0x00;
+
+ d->pic_levels = 0;
+}
+
+static int piix3_post_load(void *opaque, int version_id)
+{
+ PIIX3State *piix3 = opaque;
+ piix3_update_irq_levels(piix3);
+ return 0;
}
static void piix3_pre_save(void *opaque)
@@ -332,6 +397,7 @@ static const VMStateDescription vmstate_piix3 = {
.version_id = 3,
.minimum_version_id = 2,
.minimum_version_id_old = 2,
+ .post_load = piix3_post_load,
.pre_save = piix3_pre_save,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(dev, PIIX3State),
@@ -375,6 +441,7 @@ static PCIDeviceInfo i440fx_info[] = {
.qdev.no_user = 1,
.no_hotplug = 1,
.init = piix3_initfn,
+ .config_write = piix3_write_config,
},{
/* end of list */
}
commit e735b55a8c11dd455e31ccd4420e6c9485191d0c
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Fri Apr 1 20:43:22 2011 +0900
piix_pci: eliminate PIIX3State::pci_irq_levels
PIIX3State::pci_irq_levels are redundant which is already tracked by
PCIBus layer. So eliminate them.
Cc: Juan Quintela <quintela at redhat.com>
Cc: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 358da58..35e420c 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -37,10 +37,14 @@
typedef PCIHostState I440FXState;
+#define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */
+
typedef struct PIIX3State {
PCIDevice dev;
- int pci_irq_levels[4];
qemu_irq *pic;
+
+ /* This member isn't used. Just for save/load compatibility */
+ int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
} PIIX3State;
struct PCII440FXState {
@@ -162,9 +166,11 @@ static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
i440fx_update_memory_mappings(d);
qemu_get_8s(f, &d->smm_enabled);
- if (version_id == 2)
- for (i = 0; i < 4; i++)
- d->piix3->pci_irq_levels[i] = qemu_get_be32(f);
+ if (version_id == 2) {
+ for (i = 0; i < PIIX_NUM_PIRQS; i++) {
+ qemu_get_be32(f); /* dummy load for compatibility */
+ }
+ }
return 0;
}
@@ -236,7 +242,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *
piix3 = DO_UPCAST(PIIX3State, dev,
pci_create_simple_multifunction(b, -1, true, "PIIX3"));
piix3->pic = pic;
- pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, 4);
+ pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, PIIX_NUM_PIRQS);
(*pi440fx_state)->piix3 = piix3;
*piix3_devfn = piix3->dev.devfn;
@@ -256,8 +262,6 @@ static void piix3_set_irq(void *opaque, int irq_num, int level)
int i, pic_irq, pic_level;
PIIX3State *piix3 = opaque;
- piix3->pci_irq_levels[irq_num] = level;
-
/* now we change the pic irq level according to the piix irq mappings */
/* XXX: optimize */
pic_irq = piix3->dev.config[0x60 + irq_num];
@@ -266,8 +270,9 @@ static void piix3_set_irq(void *opaque, int irq_num, int level)
to it */
pic_level = 0;
for (i = 0; i < 4; i++) {
- if (pic_irq == piix3->dev.config[0x60 + i])
- pic_level |= piix3->pci_irq_levels[i];
+ if (pic_irq == piix3->dev.config[0x60 + i]) {
+ pic_level |= pci_bus_get_irq_level(piix3->dev.bus, i);
+ }
}
qemu_set_irq(piix3->pic[pic_irq], pic_level);
}
@@ -309,8 +314,17 @@ static void piix3_reset(void *opaque)
pci_conf[0xab] = 0x00;
pci_conf[0xac] = 0x00;
pci_conf[0xae] = 0x00;
+}
- memset(d->pci_irq_levels, 0, sizeof(d->pci_irq_levels));
+static void piix3_pre_save(void *opaque)
+{
+ int i;
+ PIIX3State *piix3 = opaque;
+
+ for (i = 0; i < ARRAY_SIZE(piix3->pci_irq_levels_vmstate); i++) {
+ piix3->pci_irq_levels_vmstate[i] =
+ pci_bus_get_irq_level(piix3->dev.bus, i);
+ }
}
static const VMStateDescription vmstate_piix3 = {
@@ -318,9 +332,11 @@ static const VMStateDescription vmstate_piix3 = {
.version_id = 3,
.minimum_version_id = 2,
.minimum_version_id_old = 2,
+ .pre_save = piix3_pre_save,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(dev, PIIX3State),
- VMSTATE_INT32_ARRAY_V(pci_irq_levels, PIIX3State, 4, 3),
+ VMSTATE_INT32_ARRAY_V(pci_irq_levels_vmstate, PIIX3State,
+ PIIX_NUM_PIRQS, 3),
VMSTATE_END_OF_LIST()
}
};
commit 9ddf8437856539c352070dee0e9fb6a33ab6ff5c
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Fri Apr 1 20:43:21 2011 +0900
pci: add accessor function to get irq levels
Introduce accessor function to know INTx levels.
It will be used later by q35.
Although piix_pci tracks the intx line levels, it can be eliminated
by this helper function.
Cc: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/pci.c b/hw/pci.c
index 6b577e1..3ee4871 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -126,6 +126,13 @@ static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
}
+int pci_bus_get_irq_level(PCIBus *bus, int irq_num)
+{
+ assert(irq_num >= 0);
+ assert(irq_num < bus->nirq);
+ return !!bus->irq_count[irq_num];
+}
+
/* Update interrupt status bit in config space on interrupt
* state change. */
static void pci_update_irq_status(PCIDevice *dev)
diff --git a/hw/pci.h b/hw/pci.h
index 52ee8c9..a5f875d 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -234,6 +234,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque, int nirq);
+int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
commit 41e7313f878813efeac4a65680018efcaff322a9
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sat Mar 26 22:53:09 2011 +0100
cirrus_vga: remove unneeded reset
cirrus_reset is already called by the reset framework,
so there is no need to call it in cirrus_init_common.
Cc: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 2724f7b..bdf4c8b 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3024,7 +3024,6 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
s->vga.cursor_draw_line = cirrus_cursor_draw_line;
qemu_register_reset(cirrus_reset, s);
- cirrus_reset(s);
}
/***************************************
More information about the Spice-commits
mailing list