> kvm_run->mmio.is_bigendian = vcpu->arch.some_register & >From your example code, I can know is_bigendian indicate whether guest is in bigendian mode when accessing MMIO.
Qemu is responsible for handling MMIO emulation, Qemus always assume it is running on littleendian mode. So if guest accesses MMIO in bigendian mode, kvm need to transform it to littleendian before delivering this MMIO request to Qemu. This works for IA64 side. Thanks, - Anthony Hollis Blanchard wrote: > We're just talking about a flag in the kvm_run.mmio structure, so it > does not represent the state of any software, guest or host, other > than that single MMIO access. > > This flag is only used for communication between host kernel and host > userland, so the host kernel is always responsible for setting it. > > "is_bigendian" is just one more necessary piece of information for > MMIO emulation. kvm_run already tells you that you are loading 4 > bytes from address 0. What you don't know today is if byte 0 is the > least significant or most significant byte. If "is_bigendian" is set, > you know that byte 0 is the MSB and byte 3 is the LSB. If not, the > opposite is true. > > In the simplest case, IA64's in-kernel MMIO emulation code could look > something like: > kvm_run->mmio.phys_addr = addr; > kvm_run->mmio.len = len; > ... > kvm_run->mmio.is_bigendian = vcpu->arch.some_register & > BIGENDIAN; > > If IA64 has reverse-endian load/store instructions like PowerPC, then > you would also need to consider the particular instruction used as > well as the guest state. > > > On Fri, 2008-01-11 at 10:02 +0800, Xu, Anthony wrote: >> Hi all, >> >> That's a good start to consider BE. >> Yes, IA64 support BE and LE. >> >> I have below comments. >> >> What does is_bigendian mean? >> Host is runing with BE or guest is running with BE. >> Who will set is_bigendian? >> >> For supporing BE, >> We need to consider host BE and guest BE. >> For IA64, most OS is running with LE, and >> Application can run with BE or LE, >> For example, Qemu can run with BE or LE. >> >> IMHO, we need two flags, >> host_is_bigendian indicates Qemu is running with BE >> Guest_is_bigendian indecates the guest application who is accessing >> MMIO >> >> Is running with LE. >> >> >> - Anthony >> >> >> >> >> >> >> Hollis Blanchard wrote: >>> On Thu, 2008-01-10 at 17:28 +0200, Avi Kivity wrote: >>>> I'll apply that patch (with a #ifdef CONFIG_PPC so other archs >>>> don't use it by mistake). >>> >>> I don't think that's the right ifdef. For example, I believe IA64 >>> can run in BE mode and so will have the same issue, and there are >>> certainly other architectures (less relevant to the current code) >>> that definitely are in the same situation. >>> >>> We need to plumb this through to the libkvm users anyways. Take a >>> look at the patch below and tell me if you think it's not the right >>> approach. x86 simply won't consider 'is_bigendian'. I spent a lot >>> of time on this, and it's by far the cleanest solution I could come >>> up with. >>> >>> >>> >>> diff --git a/libkvm/config-i386.mak b/libkvm/config-i386.mak --- >>> a/libkvm/config-i386.mak +++ b/libkvm/config-i386.mak >>> @@ -2,5 +2,6 @@ LIBDIR := /lib >>> LIBDIR := /lib >>> CFLAGS += -m32 >>> CFLAGS += -D__i386__ >>> +CFLAGS += -DARCH_MMIO_ENDIAN_LITTLE >>> >>> libkvm-$(ARCH)-objs := libkvm-x86.o >>> diff --git a/libkvm/config-ia64.mak b/libkvm/config-ia64.mak --- >>> a/libkvm/config-ia64.mak +++ b/libkvm/config-ia64.mak >>> @@ -1,5 +1,6 @@ >>> >>> LIBDIR := /lib >>> CFLAGS += -D__ia64__ >>> +CFLAGS += -DARCH_MMIO_ENDIAN_LITTLE -DARCH_MMIO_ENDIAN_BIG >>> >>> libkvm-$(ARCH)-objs := libkvm-ia64.o >>> diff --git a/libkvm/config-powerpc.mak b/libkvm/config-powerpc.mak >>> --- a/libkvm/config-powerpc.mak >>> +++ b/libkvm/config-powerpc.mak >>> @@ -2,5 +2,6 @@ LIBDIR := /lib >>> LIBDIR := /lib >>> CFLAGS += -m32 >>> CFLAGS += -D__powerpc__ >>> +CFLAGS += -DARCH_MMIO_ENDIAN_BIG -DARCH_MMIO_ENDIAN_LITTLE >>> >>> libkvm-$(ARCH)-objs := libkvm-powerpc.o >>> diff --git a/libkvm/config-x86_64.mak b/libkvm/config-x86_64.mak >>> --- a/libkvm/config-x86_64.mak >>> +++ b/libkvm/config-x86_64.mak >>> @@ -2,5 +2,6 @@ LIBDIR := /lib64 >>> LIBDIR := /lib64 >>> CFLAGS += -m64 >>> CFLAGS += -D__x86_64__ >>> +CFLAGS += -DARCH_MMIO_ENDIAN_LITTLE >>> >>> libkvm-$(ARCH)-objs := libkvm-x86.o >>> diff --git a/libkvm/libkvm.c b/libkvm/libkvm.c >>> --- a/libkvm/libkvm.c >>> +++ b/libkvm/libkvm.c >>> @@ -774,21 +774,56 @@ int kvm_set_sregs(kvm_context_t kvm, int >>> return ioctl(kvm->vcpu_fd[vcpu], KVM_SET_SREGS, sregs); } >>> >>> +#ifdef ARCH_MMIO_ENDIAN_BIG >>> +static int handle_mmio_bigendian(kvm_context_t kvm, struct kvm_run >>> *kvm_run) +{ + if (kvm_run->mmio.is_write) >>> + return kvm->callbacks->mmio_write_be(kvm->opaque, >>> + >> kvm_run->mmio.phys_addr, >>> + kvm_run->mmio.data, >>> + kvm_run->mmio.len); >>> + else >>> + return kvm->callbacks->mmio_read_be(kvm->opaque, >>> + >> kvm_run->mmio.phys_addr, >>> + kvm_run->mmio.data, >>> + kvm_run->mmio.len); >>> +} >>> +#endif >>> + >>> +#ifdef ARCH_MMIO_ENDIAN_LITTLE >>> +static int handle_mmio_littleendian(kvm_context_t kvm, struct >>> kvm_run *kvm_run) +{ + if (kvm_run->mmio.is_write) >>> + return kvm->callbacks->mmio_write_le(kvm->opaque, >>> + >> kvm_run->mmio.phys_addr, >>> + kvm_run->mmio.data, >>> + kvm_run->mmio.len); >>> + else >>> + return kvm->callbacks->mmio_read_le(kvm->opaque, >>> + >> kvm_run->mmio.phys_addr, >>> + kvm_run->mmio.data, >>> + kvm_run->mmio.len); >>> +} >>> +#endif >>> + >>> static int handle_mmio(kvm_context_t kvm, struct kvm_run *kvm_run) >>> { unsigned long addr = kvm_run->mmio.phys_addr; >>> - void *data = kvm_run->mmio.data; >>> >>> /* hack: Red Hat 7.1 generates these weird accesses. */ >>> if ((addr > 0xa0000-4 && addr <= 0xa0000) && kvm_run->mmio.len == >>> 3) return 0; >>> >>> - if (kvm_run->mmio.is_write) >>> - return kvm->callbacks->mmio_write(kvm->opaque, addr, data, >>> - kvm_run->mmio.len); >>> +#if defined(ARCH_MMIO_ENDIAN_BIG) && >>> defined(ARCH_MMIO_ENDIAN_LITTLE) + if (kvm_run->mmio.is_bigendian) >>> + return handle_mmio_bigendian(kvm, kvm_run); >>> else >>> - return kvm->callbacks->mmio_read(kvm->opaque, addr, data, >>> - kvm_run->mmio.len); >>> + return handle_mmio_littleendian(kvm, kvm_run); >>> +#elif ARCH_MMIO_ENDIAN_LITTLE >>> + return handle_mmio_littleendian(kvm, kvm_run); >>> +#elif ARCH_MMIO_ENDIAN_BIG >>> + return handle_mmio_bigendian(kvm, kvm_run); >>> +#endif >>> } >>> >>> int handle_io_window(kvm_context_t kvm) >>> diff --git a/libkvm/libkvm.h b/libkvm/libkvm.h >>> --- a/libkvm/libkvm.h >>> +++ b/libkvm/libkvm.h >>> @@ -46,11 +46,11 @@ struct kvm_callbacks { >>> /// For 32bit IO writes from the guest (Usually when executing >>> 'outl') int (*outl)(void *opaque, uint16_t addr, uint32_t >>> data); /// generic memory reads to unmapped memory (For MMIO >>> devices) >>> - int (*mmio_read)(void *opaque, uint64_t addr, uint8_t *data, >>> - int len); >>> + int (*mmio_read_be)(void *opaque, uint64_t addr, uint8_t *data, >>> int len); + int (*mmio_read_le)(void *opaque, uint64_t addr, >>> uint8_t *data, int len); /// generic memory writes to unmapped >>> memory (For MMIO devices) >>> - int (*mmio_write)(void *opaque, uint64_t addr, uint8_t *data, >>> - int len); >>> + int (*mmio_write_be)(void *opaque, uint64_t addr, uint8_t >>> *data, int len); + int (*mmio_write_le)(void *opaque, uint64_t >>> addr, uint8_t *data, int len); int (*debug)(void *opaque, int >>> vcpu); /*! * \brief Called when the VCPU issues an 'hlt' >>> instruction. >>> diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c >>> --- a/qemu/qemu-kvm.c >>> +++ b/qemu/qemu-kvm.c >>> @@ -21,6 +21,7 @@ int kvm_irqchip = 1; >>> #include <libkvm.h> >>> #include <pthread.h> >>> #include <sys/utsname.h> >>> +#include <endian.h> >>> >>> extern void perror(const char *s); >>> >>> @@ -533,8 +534,13 @@ static struct kvm_callbacks qemu_kvm_ops >>> .outb = kvm_outb, .outw = kvm_outw, >>> .outl = kvm_outl, >>> - .mmio_read = kvm_mmio_read, >>> - .mmio_write = kvm_mmio_write, >>> +#if __BYTE_ORDER == __LITTLE_ENDIAN >>> + .mmio_read_le = kvm_mmio_read, >>> + .mmio_write_le = kvm_mmio_write, >>> +#else >>> + .mmio_read_be = kvm_mmio_read, >>> + .mmio_write_be = kvm_mmio_write, >>> +#endif >>> .halt = kvm_halt, >>> .shutdown = kvm_shutdown, >>> .io_window = kvm_io_window, >>> diff --git a/user/main-ppc.c b/user/main-ppc.c >>> --- a/user/main-ppc.c >>> +++ b/user/main-ppc.c >>> @@ -92,14 +92,14 @@ static int test_pre_kvm_run(void *opaque >>> return 0; } >>> >>> -static int test_mem_read(void *opaque, uint64_t addr, uint8_t >>> *data, int len) +static int test_mem_read_be(void *opaque, uint64_t >>> addr, uint8_t *data, int len) { printf("%s: addr %"PRIx64" len >>> %d\n", __func__, addr, len); memset(data, 0, len); return 0; >>> } >>> >>> -static int test_mem_write(void *opaque, uint64_t addr, uint8_t >>> *data, int len) +static int test_mem_write_be(void *opaque, uint64_t >>> addr, uint8_t *data, int len) { >>> printf("%s: addr %"PRIx64" len %d data %"PRIx64"\n", >>> __func__, addr, len, *(uint64_t *)data); >>> @@ -120,8 +120,8 @@ static int test_dcr_write(kvm_context_t } >>> >>> static struct kvm_callbacks test_callbacks = { >>> - .mmio_read = test_mem_read, >>> - .mmio_write = test_mem_write, >>> + .mmio_read_be = test_mem_read_be, >>> + .mmio_write_be = test_mem_write_be, >>> .debug = test_debug, >>> .halt = test_halt, >>> .io_window = test_io_window, >>> diff --git a/user/main.c b/user/main.c >>> --- a/user/main.c >>> +++ b/user/main.c >>> @@ -389,8 +389,8 @@ static struct kvm_callbacks test_callbac >>> .outb = test_outb, .outw = test_outw, >>> .outl = test_outl, >>> - .mmio_read = test_mem_read, >>> - .mmio_write = test_mem_write, >>> + .mmio_read_le = test_mem_read, >>> + .mmio_write_le = test_mem_write, >>> .debug = test_debug, >>> .halt = test_halt, >>> .io_window = test_io_window, >> >> ------------------------------------------------------------------------ - >> Check out the new SourceForge.net Marketplace. >> It's the best place to buy or sell services for >> just about anything Open Source. >> http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketp lace >> _______________________________________________ >> kvm-devel mailing list >> kvm-devel@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/kvm-devel ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel