]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools, bios: Fix BIOS to kernel memory copy
authorPekka Enberg <penberg@kernel.org>
Fri, 30 Sep 2011 15:53:48 +0000 (18:53 +0300)
committerPekka Enberg <penberg@kernel.org>
Sun, 16 Oct 2011 18:33:34 +0000 (21:33 +0300)
This patch implements memcpy16() function that copies memory areas in 16-bit
real mode and converts bios/int10.c to use it instead of relying on GCC struct
memcpy to do the right thing.

Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: Asias He <asias.hejun@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/Makefile
tools/kvm/bios/entry.S
tools/kvm/bios/int10.c
tools/kvm/bios/memcpy.c [new file with mode: 0644]
tools/kvm/include/bios/memcpy.h [new file with mode: 0644]
tools/kvm/include/kvm/bios.h

index 3939c1164294ed0777a3cfc975d81832515b97a8..8387e2f9dbc1f0ded56490a2804d2981bc3866aa 100644 (file)
@@ -219,6 +219,8 @@ BIOS_CFLAGS += -mregparm=3
 bios.o: bios/bios.bin bios/bios-rom.h
 
 bios/bios.bin.elf: bios/entry.S bios/e820.c bios/int10.c bios/int15.c bios/rom.ld.S
+       $(E) "  CC       bios/memcpy.o"
+       $(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/memcpy.c -o bios/memcpy.o
        $(E) "  CC       bios/e820.o"
        $(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/e820.c -o bios/e820.o
        $(E) "  CC       bios/int10.o"
@@ -228,7 +230,7 @@ bios/bios.bin.elf: bios/entry.S bios/e820.c bios/int10.c bios/int15.c bios/rom.l
        $(E) "  CC       bios/entry.o"
        $(Q) $(CC) $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/entry.S -o bios/entry.o
        $(E) "  LD      " $@
-       $(Q) ld -T bios/rom.ld.S -o bios/bios.bin.elf bios/entry.o bios/e820.o bios/int10.o bios/int15.o
+       $(Q) ld -T bios/rom.ld.S -o bios/bios.bin.elf bios/memcpy.o bios/entry.o bios/e820.o bios/int10.o bios/int15.o
 
 bios/bios.bin: bios/bios.bin.elf
        $(E) "  OBJCOPY " $@
index 2ee21a9116d612b843ab8e5a2941fc19604c2e5f..85056e9816c46d34b8d9d0aa8b86ebd9c6ce7957 100644 (file)
@@ -16,6 +16,7 @@
 .macro SAVE_BIOSREGS
        pushl   %fs
        pushl   %es
+       pushl   %ds
        pushl   %edi
        pushl   %esi
        pushl   %ebp
@@ -35,6 +36,7 @@
        popl    %ebp
        popl    %esi
        popl    %edi
+       popl    %ds
        popl    %es
        popl    %fs
 .endm
index 22da9fa0f92857ee41f4624f8940cb0b14a29355..6387ca8b15ebdc79dbbe6d184a67dd2d7b7293c4 100644 (file)
@@ -2,6 +2,9 @@
 #include "kvm/bios.h"
 #include "kvm/util.h"
 #include "kvm/vesa.h"
+
+#include "bios/memcpy.h"
+
 #include <stdint.h>
 
 #define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24))
@@ -99,18 +102,21 @@ static void vbe_get_mode(struct biosregs *args)
 
 static void vbe_get_info(struct biosregs *args)
 {
-       struct vesa_general_info *info = (struct vesa_general_info *) args->edi;
+       struct vesa_general_info *infop = (struct vesa_general_info *) args->edi;
+       struct vesa_general_info info;
 
-       *info = (struct vesa_general_info) {
+       info = (struct vesa_general_info) {
                .signature              = VESA_MAGIC,
                .version                = 0x102,
-               .vendor_string          = &info->oem_string,
+               .vendor_string          = &infop->oem_string,
                .capabilities           = 0x10,
-               .video_mode_ptr         = &info->modes,
+               .video_mode_ptr         = &infop->modes,
                .total_memory           = (4 * VESA_WIDTH * VESA_HEIGHT) / 0x10000,
                .oem_string             = "KVM VESA",
                .modes                  = { 0x0112, 0xffff },
        };
+
+       memcpy16(args->es, infop, args->ds, &info, sizeof(info));
 }
 
 #define VBE_STATUS_OK          0x004F
diff --git a/tools/kvm/bios/memcpy.c b/tools/kvm/bios/memcpy.c
new file mode 100644 (file)
index 0000000..40b9b65
--- /dev/null
@@ -0,0 +1,23 @@
+#include "bios/memcpy.h"
+
+/*
+ *  Copy memory area in 16-bit real mode.
+ */
+void memcpy16(u16 dst_seg, void *dst, u16 src_seg, const void *src, size_t len)
+{
+       __asm__ __volatile__ (
+               "pushw  %%ds                            \n"
+               "pushw  %%es                            \n"
+               "movw   %[src_seg], %%ds                \n"
+               "movw   %[dst_seg], %%es                \n"
+               "rep movsb %%ds:(%%si), %%es:(%%di)     \n"
+               "popw   %%es                            \n"
+               "popw   %%ds                            \n"
+               :
+               : "S"(src),
+                 "D"(dst),
+                 "c"(len),
+                 [src_seg] "r"(src_seg),
+                 [dst_seg] "r"(dst_seg)
+               : "cc", "memory");
+}
diff --git a/tools/kvm/include/bios/memcpy.h b/tools/kvm/include/bios/memcpy.h
new file mode 100644 (file)
index 0000000..e021044
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef KVM_BIOS_MEMCPY_H
+#define KVM_BIOS_MEMCPY_H
+
+#include <linux/types.h>
+#include <stddef.h>
+
+void memcpy16(u16 dst_seg, void *dst, u16 src_seg, const void *src, size_t len);
+
+#endif /* KVM_BIOS_MEMCPY_H */
index 469576ecaaa4a74c89421a82f65e7fc1c58e18cb..39cc972e9cc34cf2d9fd50e74827b7ec5016b776 100644 (file)
@@ -69,6 +69,7 @@ struct biosregs {
        u32                     ebp;
        u32                     esi;
        u32                     edi;
+       u32                     ds;
        u32                     es;
        u32                     fs;
        u32                     eip;