[Qemu-devel] Rewritten Linux kernel loader
I got a bug report today that my recent changes to the Linux kernel setup broke the Qemu kernel loader. I implemented a workaround, but found a number of serious bugs in the loader itself. As a consequence, I have rewritten it; here is a patch against qemu-0.9.0. As rewritten, it should follow the current version of the Linux boot protocol specification and recommendations. As a side benefit, it no longer relies on load_linux.S; instead I have a small code generator which can be used to set up an arbitrary state -- thus usable for other startup scenarios as well. -hpa diff -urN qemu-0.9.0/hw/pc.c qemu-0.9.0-newloader/hw/pc.c --- qemu-0.9.0/hw/pc.c 2007-02-05 15:01:54.0 -0800 +++ qemu-0.9.0-newloader/hw/pc.c 2007-05-16 14:13:46.0 -0700 @@ -31,10 +31,10 @@ #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" #define LINUX_BOOT_FILENAME "linux_boot.bin" -#define KERNEL_LOAD_ADDR 0x0010 -#define INITRD_LOAD_ADDR 0x0060 -#define KERNEL_PARAMS_ADDR 0x0009 -#define KERNEL_CMDLINE_ADDR 0x00099000 +/* If loading an operating system, don't touch this much memory at the + top of RAM -- possibly reserved for the BIOS for things like ACPI + tables. */ +#define HIGHMEM_FOR_BIOS 0x0010 static fdctrl_t *floppy_controller; static RTCState *rtc_state; @@ -347,6 +347,61 @@ register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL); } +/* Generate an initial boot sector which sets state and jump to + a specified vector */ +static int generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip) +{ +uint8_t bootsect[512], *p; +int i; + +if (bs_table[0] == NULL) { + fprintf(stderr, "A disk image must be given for 'hda' when booting " + "a Linux kernel\n"); + exit(1); +} + +memset(bootsect, 0, sizeof(bootsect)); + +/* Copy the MSDOS partition table if possible */ +bdrv_read(bs_table[0], 0, bootsect, 1); + +/* Make sure we have a partition signature */ +bootsect[0x510] = 0x55; +bootsect[0x511] = 0xaa; + +/* Actual code */ +p = bootsect; +*p++ = 0xfa; /* CLI */ +*p++ = 0xfc; /* CLD */ + +for (i = 0; i < 6; i++) { + if (i == 1) /* Skip CS */ + continue; + + *p++ = 0xb8; /* MOV AX,imm16 */ + *p++ = segs[i]; + *p++ = segs[i] >> 8; + *p++ = 0x8e; /* MOV ,AX */ + *p++ = 0xc0 + (i << 3); +} + +for (i = 0; i < 8; i++) { + *p++ = 0x66; /* 32-bit operand size */ + *p++ = 0xb8 + i; /* MOV ,imm32 */ + *p++ = gpr[i]; + *p++ = gpr[i] >> 8; + *p++ = gpr[i] >> 16; + *p++ = gpr[i] >> 24; +} + +*p++ = 0xea; /* JMP FAR */ +*p++ = ip; /* IP */ +*p++ = ip >> 8; +*p++ = segs[1]; /* CS */ +*p++ = segs[1] >> 8; + +bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect)); +} int load_kernel(const char *filename, uint8_t *addr, uint8_t *real_addr) @@ -379,6 +434,169 @@ return -1; } +static long get_file_size(FILE *f) +{ +long where, size; + +/* XXX: on Unix systems, using fstat() probably makes more sense */ + +where = ftell(f); +fseek(f, 0, SEEK_END); +size = ftell(f); +fseek(f, where, SEEK_SET); + +return size; +} + +static void load_linux(const char *kernel_filename, + const char *initrd_filename, + const char *kernel_cmdline) +{ +uint16_t protocol; +uint32_t gpr[8]; +uint16_t seg[6]; +uint16_t real_seg; +int setup_size, kernel_size, initrd_size, cmdline_size; +uint32_t initrd_max; +uint8_t header[1024]; +uint8_t *real_addr, *prot_addr, *cmdline_addr, *initrd_addr; +FILE *f, *fi; + +/* Align to 16 bytes as a paranoia measure */ +cmdline_size = (strlen(kernel_cmdline)+16) & ~15; + +/* load the kernel header */ +f = fopen(kernel_filename, "rb"); +if (!f || !(kernel_size = get_file_size(f)) || + fread(header, 1, 1024, f) != 1024) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", + kernel_filename); + exit(1); +} + +/* kernel protocol version */ +fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202)); +if (ldl_p(header+0x202) == 0x53726448) + protocol = lduw_p(header+0x206); +else + protocol = 0; + +if (protocol < 0x200 || !(header[0x211] & 0x01)) { + /* Low kernel */ + real_addr= phys_ram_base + 0x9; + cmdline_addr = phys_ram_base + 0x9a000 - cmdline_size; + prot_addr= phys_ram_base + 0x1; +} else if (protocol < 0x202) { + /* High but ancient kernel */ + real_addr= phys_ram_base + 0x9; + cmdline_addr = phys_ram_base + 0x9a000 - cmdline_size; + prot_addr= phys_ram_base + 0x10; +} else { + /* High and recent kernel */ + real_addr= phys_ram_base + 0x1; + cmdline_addr = phys_ram_base + 0x2; + prot_addr= phys_ram_base + 0x10; +} + +fprintf(stderr, + "qemu: real_addr = %#zx\n" + "qemu: cmdline_addr = %#zx\n" + "qemu: prot_addr = %#zx\n", + real_addr-phys_ram_base, + cmdline_addr-phys_ram_base, +
[Qemu-devel] [PATCH] Fix a race condition and non-leaf images growing in VMDK chains.
Hi, The bug was in my last patch. This is a new one. I'll very appreciate any comments. Regards, Igor Lvovsky -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Igor Lvovsky Sent: Sunday, May 13, 2007 2:13 PM To: qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH] Fix a race condition and non-leaf imagesgrowing in VMDK chains. Hi, In this patch I fixed two issues: 1. A race condition during write operations on snapshots. Now we write the grain of data first and the L2 metadata after. So, the snapshot will stay correct if the VM will be destroyed in the middle of the write. 2. Non-leaf images growing during writes. Assume we have snapshots chain (Base->Snap1->Snap2->...->Leaf) and we run a VM with the latest image of this chain (leaf image). We have a problem with non-leaf images growing in the snapshot-chain (most noticeable when the VM performs aggressive writes). It's an incorrect behavior according to VMDK spec. For every write operation into an unknown offset, the active image must query its ancestors for this offset, and if exists in any of them perform a read-from-ancestor/modify/write-to-active the whole grain of that offset. The problem happened upon read-from-ancestor/modify/write-to-active where the ancestor was 2 or more generations above the active (leaf)image (not a direct parent), as its direct child was modified. Fixed by always write to the 'active' (leaf) image. Regards, Igor Lvovsky -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Fabrice Bellard Sent: Tuesday, January 16, 2007 9:36 PM To: qemu-devel@nongnu.org Subject: Re: [Qemu-devel] Race condition in VMDK (QCOW*) formats. Well, it was never said that the QCOW* code was safe if you interrupted QEMU at some point. But I agree that it could be safer to write the sector first and update the links after. It could be interesting to analyze the QCOW2 snapshots handling too (what if QEMU is stopped during the creation of a snapshot ?). Regards, Fabrice. Igor Lvovsky wrote: > > > Hi all, > > I have doubt about the race condition during the *write operation on > snapshot*. > > I think the problem exists in VMDK and QCOW* formats (I didn't checked > the others). > > > > The example from the block_vmdk.c. > > > > static int vmdk_write(BlockDriverState *bs, int64_t sector_num, > > const uint8_t *buf, int nb_sectors) > > { > > BDRVVmdkState *s = bs->opaque; > > int ret, index_in_cluster, n; > > uint64_t cluster_offset; > > > > while (nb_sectors > 0) { > > index_in_cluster = sector_num & (s->cluster_sectors - 1); > > n = s->cluster_sectors - index_in_cluster; > > if (n > nb_sectors) > > n = nb_sectors; > > cluster_offset = get_cluster_offset(bs, sector_num << 9, 1); > > if (!cluster_offset) > > return -1; > > lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET); > > ret = write(s->fd, buf, n * 512); > > if (ret != n * 512) > > return -1; > > nb_sectors -= n; > > sector_num += n; > > buf += n * 512; > > } > > return 0; > > } > > > > The /get_cluster_offset(…)/ routine update the L2 table of the metadata > and return the /cluster_offset. / > > After that the /vmdk_write(…)/ routine/ /actually write the grain at > right place. > > So, we have timing hole here. > > > > Assume, VM that perform write operation will be destroyed at this moment. > > So, we have corrupted image (with updated L2 table, but without the > grain itself). > > > > Regards, > > Igor Lvovsky > > > > > > > > > > > > > > > ___ > Qemu-devel mailing list > Qemu-devel@nongnu.org > http://lists.nongnu.org/mailman/listinfo/qemu-devel ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel block-vmdk.diff Description: block-vmdk.diff
Re: [Qemu-devel] Rewritten Linux kernel loader
On Wednesday 16 May 2007 14:31:38 H. Peter Anvin wrote: > As rewritten, it should follow the current version of the Linux boot > protocol specification and recommendations. As a side benefit, it no > longer relies on load_linux.S; instead I have a small code generator > which can be used to set up an arbitrary state -- thus usable for other > startup scenarios as well. It also eliminates the annoying hardcoded load addresses for the kernel and initrd. Thanks for doing this! --Ed
Re: [Qemu-devel] Rewritten Linux kernel loader
On Wednesday 16 May 2007, H. Peter Anvin wrote: > I got a bug report today that my recent changes to the Linux kernel > setup broke the Qemu kernel loader. I implemented a workaround, but > found a number of serious bugs in the loader itself. As a consequence, > I have rewritten it; here is a patch against qemu-0.9.0. Pleas update your patch to current CVS. Paul
[Qemu-devel] How to Linux kernel for MIPSEL qemu
Hello every one, I try to build a mipsel kernel by myself for qemu-system-mipsel. But the qemu can not boot it properly. Is there anyone can give me some suggestion about it. My method is following, * Get the kernel of 2.6.18.3 from kernel.org * Get the config.gz from the mipsel kernel that be provided by Qemu web. * uncompress config.gz and rename it as .config, copy it to Linux kernel directory . * in the kernel directory, use following command to build the kernel make ARCH=mips CROSS_COMPILE=/opt/noki/mipsel-unknown-linux/sdktool/bin/mipsel-unknown-linux- oldconfig make ARCH=mips CROSS_COMPILE=/opt/noki/mipsel-unknown-linux/sdktool/bin/mipsel-unknown-linux- all after build , I use qemu 0.9 to boot it, and do not successes. #qemu-system-mipsel -kernel vmlinux -initrd initrd.gz -append "console=ttyS0" qemu: Warning, could not load MIPS bios '/opt/noki/mipsel-unknown-linux//sdktool//share/qemu/mipsel_bios.bin' qemu: could not load kernel 'vmlinux' Best regard! Pan
Re: [Qemu-devel] How to Linux kernel for MIPSEL qemu
PianoPan wrote: > Hello every one, > > I try to build a mipsel kernel by myself for qemu-system-mipsel. But > the qemu can not boot it properly. Is there anyone can give me some > suggestion about it. > > My method is following, > > * Get the kernel of 2.6.18.3 from kernel.org In general the source tree from www.linux-mips.org is morfe likely to work. > * Get the config.gz from the mipsel kernel that be provided by Qemu web. > * uncompress config.gz and rename it as .config, copy it to Linux > kernel directory . > * in the kernel directory, use following command to build the kernel > make ARCH=mips > CROSS_COMPILE=/opt/noki/mipsel-unknown-linux/sdktool/bin/mipsel-unknown-linux- > oldconfig > > make ARCH=mips > CROSS_COMPILE=/opt/noki/mipsel-unknown-linux/sdktool/bin/mipsel-unknown-linux- > all Looks ok. > after build , I use qemu 0.9 to boot it, and do not successes. > > #qemu-system-mipsel -kernel vmlinux -initrd initrd.gz -append > "console=ttyS0" > qemu: Warning, could not load MIPS bios > '/opt/noki/mipsel-unknown-linux//sdktool//share/qemu/mipsel_bios.bin' > qemu: could not load kernel 'vmlinux' This means Qemu's built-in ELF loader failed to load the vmlinux binary. I've seen that when attempting to load a kernel with the wrong endianness. Maybe you want to try the Debian installer image, e.g. from http://ftp.uk.debian.org/debian/dists/etch/main/installer-mipsel/current/images/qemu/netboot/ Thiemo
[Qemu-devel] qemu/hw slavio_timer.c sun4m.c
CVSROOT:/cvsroot/qemu Module name:qemu Changes by: Blue Swirl 07/05/17 19:21:47 Modified files: hw : slavio_timer.c sun4m.c Log message: Force the primary CPU to run and other CPUs to halt, recalculate timers after system_reset. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/qemu/hw/slavio_timer.c?cvsroot=qemu&r1=1.7&r2=1.8 http://cvs.savannah.gnu.org/viewcvs/qemu/hw/sun4m.c?cvsroot=qemu&r1=1.36&r2=1.37
[Qemu-devel] qemu/hw sun4m.c
CVSROOT:/cvsroot/qemu Module name:qemu Changes by: Blue Swirl 07/05/17 19:25:15 Modified files: hw : sun4m.c Log message: Set limits for memory size to avoid overlap with devices CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/qemu/hw/sun4m.c?cvsroot=qemu&r1=1.37&r2=1.38
[Qemu-devel] qemu exec-all.h exec.c target-sparc/cpu.h targe...
CVSROOT:/cvsroot/qemu Module name:qemu Changes by: Blue Swirl 07/05/17 19:30:10 Modified files: . : exec-all.h exec.c target-sparc : cpu.h op_helper.c translate.c Log message: Enable faults for unassigned memory accesses and unimplemented ASIs CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/qemu/exec-all.h?cvsroot=qemu&r1=1.55&r2=1.56 http://cvs.savannah.gnu.org/viewcvs/qemu/exec.c?cvsroot=qemu&r1=1.94&r2=1.95 http://cvs.savannah.gnu.org/viewcvs/qemu/target-sparc/cpu.h?cvsroot=qemu&r1=1.36&r2=1.37 http://cvs.savannah.gnu.org/viewcvs/qemu/target-sparc/op_helper.c?cvsroot=qemu&r1=1.26&r2=1.27 http://cvs.savannah.gnu.org/viewcvs/qemu/target-sparc/translate.c?cvsroot=qemu&r1=1.56&r2=1.57
[Qemu-devel] qemu/hw slavio_timer.c
CVSROOT:/cvsroot/qemu Module name:qemu Changes by: Blue Swirl 07/05/17 19:32:20 Modified files: hw : slavio_timer.c Log message: Fix Qemu division by zero triggered by NetBSD CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/qemu/hw/slavio_timer.c?cvsroot=qemu&r1=1.8&r2=1.9
[Qemu-devel] qemu/hw tcx.c
CVSROOT:/cvsroot/qemu Module name:qemu Changes by: Blue Swirl 07/05/17 19:34:41 Modified files: hw : tcx.c Log message: Make TCX registers match what NetBSD expects CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/qemu/hw/tcx.c?cvsroot=qemu&r1=1.14&r2=1.15
[Qemu-devel] "BUG: soft lockup detected on CPU#0!"
Hi, I want to instrument all store instructions, and for this I wrote a helper function (in helper.c) which prints out some information every time a store is executed. I call this helper function from within every store OPROTO in ops_mem.h for example: void OPPROTO glue(glue(op_stl, MEMSUFFIX), _T0_A0)(void) { glue(stl, MEMSUFFIX)(A0, T0); helper_print_info(A0); // MY HELPER FUNCTION FORCE_RET(); } This works just fine for me for some time, but after a while when the frequency of calls to helper_print_info increases, QEMU just hangs throwing out some information on the QEMU console. I have typed in the error message in parts below - (If you need more information, please let me know - I included a subset just because I do not yet know how to copy-paste text from QEMU console to the host machine console) *** BUG: soft lockup detected on CPU#0! Pid: 0, comm: swapper EIP: 0060:[] CPU: 0 EIP is at serio_interrupt+0x7f/0x18f EFLAGS: 0286 ... [c02c1b2d>] cdrom_pc_intr+0x90/0x21a ... [] do_IRQ+0x4a/0x82 === ... [] unknown_bootoption+0x0/0x1cd QEMU hangs after throwing out the above error. However, if I switch to the Monitor and disable my helper function, QEMU resumes back and works fine. Can somebody tell me - 1. Am I instrumenting all stores if I instrument the OPROTOs in ops_mem.h? 2. From my above example, am I instrumenting the stores with my helper function in the right way? 3. Can you please tell me why "BUG: soft lockup detected..." error shows up freezing QEMU? Looking forward to your help. Thanks in advance. -Shashi.
Re: [Qemu-devel] "BUG: soft lockup detected on CPU#0!"
Hi, Answering "1. Am I instrumenting all stores if I instrument the OPROTOs in ops_mem.h? " Do you consider all updates to memory as stores? e.g. add %ebx, (%eax), will also write to the memory and void OPPROTO glue(glue(op_stl, MEMSUFFIX), _T0_A0)(void) or one of its variant will be called. If you are interested in all the memory updates, then your approach is correct. If you are only interested in store instructions then your approach is not correct. Atif On 5/17/07, Shashidhar Mysore <[EMAIL PROTECTED]> wrote: Hi, I want to instrument all store instructions, and for this I wrote a helper function (in helper.c) which prints out some information every time a store is executed. I call this helper function from within every store OPROTO in ops_mem.h for example: void OPPROTO glue(glue(op_stl, MEMSUFFIX), _T0_A0)(void) { glue(stl, MEMSUFFIX)(A0, T0); helper_print_info(A0); // MY HELPER FUNCTION FORCE_RET(); } This works just fine for me for some time, but after a while when the frequency of calls to helper_print_info increases, QEMU just hangs throwing out some information on the QEMU console. I have typed in the error message in parts below - (If you need more information, please let me know - I included a subset just because I do not yet know how to copy-paste text from QEMU console to the host machine console) *** BUG: soft lockup detected on CPU#0! Pid: 0, comm: swapper EIP: 0060:[] CPU: 0 EIP is at serio_interrupt+0x7f/0x18f EFLAGS: 0286 ... [c02c1b2d>] cdrom_pc_intr+0x90/0x21a ... [] do_IRQ+0x4a/0x82 === ... [] unknown_bootoption+0x0/0x1cd QEMU hangs after throwing out the above error. However, if I switch to the Monitor and disable my helper function, QEMU resumes back and works fine. Can somebody tell me - 1. Am I instrumenting all stores if I instrument the OPROTOs in ops_mem.h? 2. From my above example, am I instrumenting the stores with my helper function in the right way? 3. Can you please tell me why "BUG: soft lockup detected..." error shows up freezing QEMU? Looking forward to your help. Thanks in advance. -Shashi.
Re: [Qemu-devel] "BUG: soft lockup detected on CPU#0!"
Hi Atif, Thanks for the quick reply. Yes, you are right, I want to consider all updates to memory. Can you tell me if it is sufficient enough to instrument just those in ops_mem.h? I want to make sure I am not missing any form of write to the memory (even it is from IO devices, which I think is taken care of). Thanks, -Shashi. On 5/17/07, Atif Hashmi <[EMAIL PROTECTED]> wrote: Hi, Answering "1. Am I instrumenting all stores if I instrument the OPROTOs in ops_mem.h? " Do you consider all updates to memory as stores? e.g. add %ebx, (%eax), will also write to the memory and void OPPROTO glue(glue(op_stl, MEMSUFFIX), _T0_A0)(void) or one of its variant will be called. If you are interested in all the memory updates, then your approach is correct. If you are only interested in store instructions then your approach is not correct. Atif On 5/17/07, Shashidhar Mysore <[EMAIL PROTECTED]> wrote: > > Hi, > > I want to instrument all store instructions, and for this I wrote a > helper function (in helper.c) which prints out some information every > time a store is executed. I call this helper function from within every > store OPROTO in ops_mem.h > > for example: > void OPPROTO glue(glue(op_stl, MEMSUFFIX), _T0_A0)(void) > { > glue(stl, MEMSUFFIX)(A0, T0); > helper_print_info(A0); // MY HELPER FUNCTION > FORCE_RET(); > } > > > This works just fine for me for some time, but after a while when the > frequency of calls to helper_print_info increases, QEMU just hangs throwing > out some information on the QEMU console. I have typed in the error message > in parts below - (If you need more information, please let me know - I > included a subset just because I do not yet know how to copy-paste text > from QEMU console to the host machine console) > > *** > BUG: soft lockup detected on CPU#0! > > Pid: 0, comm: swapper > EIP: 0060:[] CPU: 0 > EIP is at serio_interrupt+0x7f/0x18f > EFLAGS: 0286 > ... > [c02c1b2d>] cdrom_pc_intr+0x90/0x21a > ... > [] do_IRQ+0x4a/0x82 > === > ... > [] unknown_bootoption+0x0/0x1cd > > > QEMU hangs after throwing out the above error. However, if I switch to > the Monitor and disable my helper function, QEMU resumes back and works > fine. > Can somebody tell me - > 1. Am I instrumenting all stores if I instrument the OPROTOs in > ops_mem.h? > 2. From my above example, am I instrumenting the stores with my helper > function in the right way? > 3. Can you please tell me why "BUG: soft lockup detected..." error shows > up freezing QEMU? > > Looking forward to your help. > Thanks in advance. > -Shashi. >
Re: [Qemu-devel] Rewritten Linux kernel loader
H. Peter Anvin wrote: > I got a bug report today that my recent changes to the Linux kernel > setup broke the Qemu kernel loader. I implemented a workaround, but > found a number of serious bugs in the loader itself. As a consequence, > I have rewritten it; here is a patch against qemu-0.9.0. > > As rewritten, it should follow the current version of the Linux boot > protocol specification and recommendations. As a side benefit, it no > longer relies on load_linux.S; instead I have a small code generator > which can be used to set up an arbitrary state -- thus usable for other > startup scenarios as well. Updated against qemu-snapshot-2007-05-17_05. -hpa diff -urN qemu-snapshot-2007-05-17_05/hw/pc.c qemu-snapshot-2007-05-17_05.newloader/hw/pc.c --- qemu-snapshot-2007-05-17_05/hw/pc.c 2007-04-07 11:14:41.0 -0700 +++ qemu-snapshot-2007-05-17_05.newloader/hw/pc.c 2007-05-17 10:19:07.0 -0700 @@ -31,10 +31,6 @@ #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" #define LINUX_BOOT_FILENAME "linux_boot.bin" -#define KERNEL_LOAD_ADDR 0x0010 -#define MAX_INITRD_LOAD_ADDR 0x3800 -#define KERNEL_PARAMS_ADDR 0x0009 -#define KERNEL_CMDLINE_ADDR 0x00099000 /* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */ #define ACPI_DATA_SIZE 0x1 @@ -350,6 +346,61 @@ register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL); } +/* Generate an initial boot sector which sets state and jump to + a specified vector */ +static int generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip) +{ +uint8_t bootsect[512], *p; +int i; + +if (bs_table[0] == NULL) { + fprintf(stderr, "A disk image must be given for 'hda' when booting " + "a Linux kernel\n"); + exit(1); +} + +memset(bootsect, 0, sizeof(bootsect)); + +/* Copy the MSDOS partition table if possible */ +bdrv_read(bs_table[0], 0, bootsect, 1); + +/* Make sure we have a partition signature */ +bootsect[0x510] = 0x55; +bootsect[0x511] = 0xaa; + +/* Actual code */ +p = bootsect; +*p++ = 0xfa; /* CLI */ +*p++ = 0xfc; /* CLD */ + +for (i = 0; i < 6; i++) { + if (i == 1) /* Skip CS */ + continue; + + *p++ = 0xb8; /* MOV AX,imm16 */ + *p++ = segs[i]; + *p++ = segs[i] >> 8; + *p++ = 0x8e; /* MOV ,AX */ + *p++ = 0xc0 + (i << 3); +} + +for (i = 0; i < 8; i++) { + *p++ = 0x66; /* 32-bit operand size */ + *p++ = 0xb8 + i; /* MOV ,imm32 */ + *p++ = gpr[i]; + *p++ = gpr[i] >> 8; + *p++ = gpr[i] >> 16; + *p++ = gpr[i] >> 24; +} + +*p++ = 0xea; /* JMP FAR */ +*p++ = ip; /* IP */ +*p++ = ip >> 8; +*p++ = segs[1]; /* CS */ +*p++ = segs[1] >> 8; + +bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect)); +} int load_kernel(const char *filename, uint8_t *addr, uint8_t *real_addr) @@ -382,6 +433,169 @@ return -1; } +static long get_file_size(FILE *f) +{ +long where, size; + +/* XXX: on Unix systems, using fstat() probably makes more sense */ + +where = ftell(f); +fseek(f, 0, SEEK_END); +size = ftell(f); +fseek(f, where, SEEK_SET); + +return size; +} + +static void load_linux(const char *kernel_filename, + const char *initrd_filename, + const char *kernel_cmdline) +{ +uint16_t protocol; +uint32_t gpr[8]; +uint16_t seg[6]; +uint16_t real_seg; +int setup_size, kernel_size, initrd_size, cmdline_size; +uint32_t initrd_max; +uint8_t header[1024]; +uint8_t *real_addr, *prot_addr, *cmdline_addr, *initrd_addr; +FILE *f, *fi; + +/* Align to 16 bytes as a paranoia measure */ +cmdline_size = (strlen(kernel_cmdline)+16) & ~15; + +/* load the kernel header */ +f = fopen(kernel_filename, "rb"); +if (!f || !(kernel_size = get_file_size(f)) || + fread(header, 1, 1024, f) != 1024) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", + kernel_filename); + exit(1); +} + +/* kernel protocol version */ +fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202)); +if (ldl_p(header+0x202) == 0x53726448) + protocol = lduw_p(header+0x206); +else + protocol = 0; + +if (protocol < 0x200 || !(header[0x211] & 0x01)) { + /* Low kernel */ + real_addr= phys_ram_base + 0x9; + cmdline_addr = phys_ram_base + 0x9a000 - cmdline_size; + prot_addr= phys_ram_base + 0x1; +} else if (protocol < 0x202) { + /* High but ancient kernel */ + real_addr= phys_ram_base + 0x9; + cmdline_addr = phys_ram_base + 0x9a000 - cmdline_size; + prot_addr= phys_ram_base + 0x10; +} else { + /* High and recent kernel */ + real_addr= phys_ram_base + 0x1; + cmdline_addr = phys_ram_base + 0x2; + prot_addr= phys_ram_base + 0x10; +} + +fprintf(stderr, + "qemu: real_addr = %#zx\n" + "qemu: cmdline_addr = %#zx\n" + "qemu: prot_addr = %#zx\n", + real_addr-phys_ram_base, + cmdline_addr-phys_ram_base,
Re: [Qemu-devel] "BUG: soft lockup detected on CPU#0!"
Hi Shashi, I think it is sufficient to add your intercept code in ops_mem.h. I am not sure about the writes from the I/O though. Regards, Atif On 5/17/07, Shashidhar Mysore <[EMAIL PROTECTED]> wrote: Hi Atif, Thanks for the quick reply. Yes, you are right, I want to consider all updates to memory. Can you tell me if it is sufficient enough to instrument just those in ops_mem.h? I want to make sure I am not missing any form of write to the memory (even it is from IO devices, which I think is taken care of). Thanks, -Shashi. On 5/17/07, Atif Hashmi <[EMAIL PROTECTED]> wrote: > > Hi, > > Answering "1. Am I instrumenting all stores if I instrument the OPROTOs > in ops_mem.h? " > > Do you consider all updates to memory as stores? e.g. add %ebx, (%eax), > will also write to the memory and > void OPPROTO glue(glue(op_stl, MEMSUFFIX), _T0_A0)(void) or one of its > variant will be called. > > If you are interested in all the memory updates, then your approach is > correct. If you are only interested in store instructions then your approach > is not correct. > > Atif > > On 5/17/07, Shashidhar Mysore <[EMAIL PROTECTED]> wrote: > > > > Hi, > > > > I want to instrument all store instructions, and for this I wrote a > > helper function (in helper.c) which prints out some information every > > time a store is executed. I call this helper function from within every > > store OPROTO in ops_mem.h > > > > for example: > > void OPPROTO glue(glue(op_stl, MEMSUFFIX), _T0_A0)(void) > > { > > glue(stl, MEMSUFFIX)(A0, T0); > > helper_print_info(A0); // MY HELPER FUNCTION > > FORCE_RET(); > > } > > > > > > This works just fine for me for some time, but after a while when the > > frequency of calls to helper_print_info increases, QEMU just hangs throwing > > out some information on the QEMU console. I have typed in the error message > > in parts below - (If you need more information, please let me know - I > > included a subset just because I do not yet know how to copy-paste text > > from QEMU console to the host machine console) > > > > *** > > BUG: soft lockup detected on CPU#0! > > > > Pid: 0, comm: swapper > > EIP: 0060:[] CPU: 0 > > EIP is at serio_interrupt+0x7f/0x18f > > EFLAGS: 0286 > > ... > > [c02c1b2d>] cdrom_pc_intr+0x90/0x21a > > ... > > [] do_IRQ+0x4a/0x82 > > === > > ... > > [] unknown_bootoption+0x0/0x1cd > > > > > > QEMU hangs after throwing out the above error. However, if I switch to > > the Monitor and disable my helper function, QEMU resumes back and works > > fine. > > Can somebody tell me - > > 1. Am I instrumenting all stores if I instrument the OPROTOs in > > ops_mem.h? > > 2. From my above example, am I instrumenting the stores with my helper > > function in the right way? > > 3. Can you please tell me why "BUG: soft lockup detected..." error > > shows up freezing QEMU? > > > > Looking forward to your help. > > Thanks in advance. > > -Shashi. > > > >
[Qemu-devel] qemu/target-mips op.c translate.c
CVSROOT:/sources/qemu Module name:qemu Changes by: Thiemo Seufer 07/05/18 01:13:09 Modified files: target-mips: op.c translate.c Log message: Work around the lack of proper handling for self-modifying code. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/qemu/target-mips/op.c?cvsroot=qemu&r1=1.55&r2=1.56 http://cvs.savannah.gnu.org/viewcvs/qemu/target-mips/translate.c?cvsroot=qemu&r1=1.78&r2=1.79
Re: [Qemu-devel] How to Linux kernel for MIPSEL qemu
Thiemo: Thanks for your suggestion. Yes, it is a issue about endianness. I already fix it. The default of kernel for MIPS Qemu is not support the little endian. The arch/mips/Kconfig must be updated for mipsel. Thanks for ur help! Best regard! Pan On 5/18/07, Thiemo Seufer <[EMAIL PROTECTED]> wrote: PianoPan wrote: > Hello every one, > > I try to build a mipsel kernel by myself for qemu-system-mipsel. But > the qemu can not boot it properly. Is there anyone can give me some > suggestion about it. > > My method is following, > > * Get the kernel of 2.6.18.3 from kernel.org In general the source tree from www.linux-mips.org is morfe likely to work. > * Get the config.gz from the mipsel kernel that be provided by Qemu web. > * uncompress config.gz and rename it as .config, copy it to Linux > kernel directory . > * in the kernel directory, use following command to build the kernel > make ARCH=mips > CROSS_COMPILE=/opt/noki/mipsel-unknown-linux/sdktool/bin/mipsel-unknown-linux- > oldconfig > > make ARCH=mips > CROSS_COMPILE=/opt/noki/mipsel-unknown-linux/sdktool/bin/mipsel-unknown-linux- > all Looks ok. > after build , I use qemu 0.9 to boot it, and do not successes. > > #qemu-system-mipsel -kernel vmlinux -initrd initrd.gz -append > "console=ttyS0" > qemu: Warning, could not load MIPS bios > '/opt/noki/mipsel-unknown-linux//sdktool//share/qemu/mipsel_bios.bin' > qemu: could not load kernel 'vmlinux' This means Qemu's built-in ELF loader failed to load the vmlinux binary. I've seen that when attempting to load a kernel with the wrong endianness. Maybe you want to try the Debian installer image, e.g. from http://ftp.uk.debian.org/debian/dists/etch/main/installer-mipsel/current/images/qemu/netboot/ Thiemo