Skip to contentSkip to conversation

qemu initrd and ide support

PATCH Daniel Jacobowitz 2 participants 6 messages Oct 12, 2006 – Oct 24, 2006

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

These patches for qemu let IDE and initrd work in the defconfig. It seems to function - I was able to get as far as partitioning the drive in the debian installer and the next time I started qemu the new partitions were found. But the installer hangs up trying to format swap.

Of course, what would be really nice would be a PCI controller. I'm not brave enough to try.

I'm not going to submit the qemu change until I have some better evidence that it all works right (or someone else does).

Signature · 2 lines
Daniel Jacobowitz
CodeSourcery
Makefile.target +2 -2
@@ -350,8 +350,8 @@ VL_OBJS+= grackle_pci.o prep_pci.o unin_
 DEFINES += -DHAS_AUDIO
 endif
 ifeq ($(TARGET_ARCH), mips)
-VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o
-#VL_OBJS+= #ide.o pckbd.o fdc.o m48t59.o
+VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o ide.o
+#VL_OBJS+= #pckbd.o fdc.o m48t59.o
 endif
 ifeq ($(TARGET_BASE_ARCH), sparc)
 ifeq ($(TARGET_ARCH), sparc64)
mips_r4k.c +24 -7
@@ -7,6 +7,10 @@
 
 #define VIRT_TO_PHYS_ADDEND (-0x80000000LL)
 
+static const int ide_iobase[2] = { 0x1f0, 0x170 };
+static const int ide_iobase2[2] = { 0x3f6, 0x376 };
+static const int ide_irq[2] = { 14, 15 };
+
 extern FILE *logfile;
 
 static PITState *pit;
@@ -117,7 +121,8 @@ void mips_r4k_init (int ram_size, int vg
     unsigned long bios_offset;
     int ret;
     CPUState *env;
-    long kernel_size;
+    long kernel_size, initrd_size;
+    int i;
 
     env = cpu_init();
     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
@@ -158,21 +163,29 @@ void mips_r4k_init (int ram_size, int vg
 	}
 
         /* load initrd */
+        initrd_size = 0;
         if (initrd_filename) {
-            if (load_image(initrd_filename,
-			   phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND)
-		== (target_ulong) -1) {
+            initrd_size = load_image(initrd_filename,
+                                     phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
+            if (initrd_size == (target_ulong) -1) {
                 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
                         initrd_filename);
                 exit(1);
             }
         }
 
-	/* Store command line.  */
+        /* Store command line.  */
         strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
         /* FIXME: little endian support */
-        *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
-        *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
+        if (initrd_size > 0) {
+            *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345679);
+            *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
+            *(int *)(phys_ram_base + (16 << 20) - 268) = tswap32 (INITRD_LOAD_ADDR);
+            *(int *)(phys_ram_base + (16 << 20) - 272) = tswap32 (initrd_size);
+        } else {
+            *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
+            *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
+        }
     }
 
     /* Init internal devices */
@@ -198,6 +211,10 @@ void mips_r4k_init (int ram_size, int vg
             exit (1);
         }
     }
+
+    for(i = 0; i < 2; i++)
+        isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+                     bs_table[2 * i], bs_table[2 * i + 1]);
 }
 
 QEMUMachine mips_machine = {

Update QEmu configuration for IDE, initrd, and basic functionality. Also recognize the location of an initrd as provided by qemu.

arch/mips/configs/qemu_defconfig +80 -30

274 lines not on this page · raw message

arch/mips/qemu/q-firmware.c +7 -0
index fb2a867..e1e77aa 100644
@@ -12,6 +12,13 @@ void __init prom_init(void)
 		if (*(char *)(cmdline + 1))
 			strcpy (arcs_cmdline, (char *)(cmdline + 1));
 		add_memory_region(0x0<<20, cmdline[-1], BOOT_MEM_RAM);
+	} else if (*cmdline == 0x12345679) {
+		extern unsigned long initrd_start, initrd_end;
+		if (*(char *)(cmdline + 1))
+			strcpy (arcs_cmdline, (char *)(cmdline + 1));
+		add_memory_region(0x0<<20, cmdline[-1], BOOT_MEM_RAM);
+		initrd_start = cmdline[-2];
+		initrd_end = initrd_start + cmdline[-3];
 	} else {
 		add_memory_region(0x0<<20, 0x10<<20, BOOT_MEM_RAM);
 	}
#1 lore raw

Hi!

Quoted 6 lines · Daniel Jacobowitz

These patches for qemu let IDE and initrd work in the defconfig. It seems to function - I was able to get as far as partitioning the drive in the debian installer and the next time I started qemu the new partitions were found. But the installer hangs up trying to format swap.

Quoted 6 lines

Of course, what would be really nice would be a PCI controller. I'm not brave enough to try.

I'm not going to submit the qemu change until I have some better evidence that it all works right (or someone else does).

First of all, thanks a lot for your work, that makes QEMU mips more usable.

The IDE part works very well, though there seems to be some problems with userland tools (mke2fs), an instruction is probably not/bad emulated. I now have a system with the root on the IDE drive and with swap.

The initrd seems to works well, but it generates a strange failure during the boot:

[...]
Mount-cache hash table entries: 512
Checking for 'wait' instruction... available.
checking if image is initramfs...it isn't (bad gzip magic numbers); looks like an initrd Bad page state in process 'swapper'
page:81010000 flags:0x00080000 mapping:00000000 mapcount:0 count:0
Trying to fix it up, but a reboot is needed

Backtrace:
Call Trace:
 [<8005c748>] bad_page+0x68/0xa8
 [<8005ccf0>] free_hot_cold_page+0x1a4/0x1b4
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<80080138>] __fput+0x14c/0x1cc
 [<8001b094>] free_init_pages+0xa4/0xfc
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<80288d98>] free_initrd+0x28/0x44
 [<80288e80>] populate_rootfs+0xcc/0x110
 [<80292860>] spawn_softlockup_task+0x30/0x50
 [<80010498>] init+0x54/0x300
 [<80010498>] init+0x54/0x300
 [<80013074>] kernel_thread_helper+0x10/0x18
 [<80013064>] kernel_thread_helper+0x0/0x18

Freeing initrd memory: 2520k freed
NET: Registered protocol family 16
NET: Registered protocol family 2
[...]

This message is not present when initrd is not used, and it also does not appear with the previous way of passing the size and location of the initrd.

I don't have time to look more now, I will give you some more details when/if I found some time to work on that.

Bye,
Aurelien

Signature · 4 lines
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   [email protected]         | [email protected]
   `-    people.debian.org/~aurel32 | www.aurel32.net
#2 lore raw
Quoted 27 lines · Aurelien Jarno

The initrd seems to works well, but it generates a strange failure during the boot:

[...]
Mount-cache hash table entries: 512
Checking for 'wait' instruction... available.
checking if image is initramfs...it isn't (bad gzip magic numbers); looks like an initrd Bad page state in process 'swapper'
page:81010000 flags:0x00080000 mapping:00000000 mapcount:0 count:0
Trying to fix it up, but a reboot is needed

Backtrace:
Call Trace:
 [<8005c748>] bad_page+0x68/0xa8
 [<8005ccf0>] free_hot_cold_page+0x1a4/0x1b4
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<80080138>] __fput+0x14c/0x1cc
 [<8001b094>] free_init_pages+0xa4/0xfc
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<80288d98>] free_initrd+0x28/0x44
 [<80288e80>] populate_rootfs+0xcc/0x110
 [<80292860>] spawn_softlockup_task+0x30/0x50
 [<80010498>] init+0x54/0x300
 [<80010498>] init+0x54/0x300
 [<80013074>] kernel_thread_helper+0x10/0x18
 [<80013064>] kernel_thread_helper+0x0/0x18
Quoted 9 lines

Freeing initrd memory: 2520k freed
NET: Registered protocol family 16
NET: Registered protocol family 2
[...]

This message is not present when initrd is not used, and it also does not appear with the previous way of passing the size and location of the initrd.

I don't have time to look more now, I will give you some more details when/if I found some time to work on that.

This failure is due to the fact that initrd_reserve_bootmem is not set anymore to 1 in arch/mips/kernel/setup.c. It is set to 1 when the initrd location and size are read from the command line arguments, but not when
read from the place where QEMU put it.

Setting this value to 1 fixes the problem, but it is rather a big hack than a fix.

About the patch itself, another comment: you should add a #ifdef CONFIG_BLK_DEV_INITRD #endif for the block concerning the initrd in arch/mips/qemu/q-firmware.c

Bye,
Aurelien

Signature · 4 lines
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   [email protected]         | [email protected]
   `-    people.debian.org/~aurel32 | www.aurel32.net
#3 lore raw
In reply to Aurelien Jarno
Quoted 1 line · Aurelien Jarno

Hi!

Hi!

Quoted 49 lines
Quoted 6 lines · Daniel Jacobowitz

These patches for qemu let IDE and initrd work in the defconfig. It seems to function - I was able to get as far as partitioning the drive in the debian installer and the next time I started qemu the new partitions were found. But the installer hangs up trying to format swap.

Quoted 6 lines

Of course, what would be really nice would be a PCI controller. I'm not brave enough to try.

I'm not going to submit the qemu change until I have some better evidence that it all works right (or someone else does).

First of all, thanks a lot for your work, that makes QEMU mips more usable.

The IDE part works very well, though there seems to be some problems with userland tools (mke2fs), an instruction is probably not/bad emulated. I now have a system with the root on the IDE drive and with swap.

The initrd seems to works well, but it generates a strange failure during the boot:

[...]
Mount-cache hash table entries: 512
Checking for 'wait' instruction... available.
checking if image is initramfs...it isn't (bad gzip magic numbers); looks like an initrd
Bad page state in process 'swapper'
page:81010000 flags:0x00080000 mapping:00000000 mapcount:0 count:0 Trying to fix it up, but a reboot is needed

Backtrace:
Call Trace:
 [<8005c748>] bad_page+0x68/0xa8
 [<8005ccf0>] free_hot_cold_page+0x1a4/0x1b4
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<80080138>] __fput+0x14c/0x1cc
 [<8001b094>] free_init_pages+0xa4/0xfc
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<802a0000>] ic_bootp_recv+0x238/0x6a0
 [<80288d98>] free_initrd+0x28/0x44
 [<80288e80>] populate_rootfs+0xcc/0x110
 [<80292860>] spawn_softlockup_task+0x30/0x50
 [<80010498>] init+0x54/0x300
 [<80010498>] init+0x54/0x300
 [<80013074>] kernel_thread_helper+0x10/0x18
 [<80013064>] kernel_thread_helper+0x0/0x18
Quoted 4 lines

Freeing initrd memory: 2520k freed
NET: Registered protocol family 16
NET: Registered protocol family 2
[...]

As discussed on IRC, it seems the oops does not occurs on all system, but we don't know what trigger it.

Alternatively, please find attached a patch to QEMU to pass the initrd arguments directly in text, so that no modifications are needed in the kernel.

Signature · 4 lines
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   [email protected]         | [email protected]
   `-    people.debian.org/~aurel32 | www.aurel32.net

Index: hw/mips_r4k.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mips_r4k.c,v
retrieving revision 1.20

mips_r4k.c +16 -5
diff -u -d -p -r1.20 mips_r4k.c
@@ -117,7 +117,7 @@ void mips_r4k_init (int ram_size, int vg
     unsigned long bios_offset;
     int ret;
     CPUState *env;
-    long kernel_size;
+    long kernel_size, initrd_size;
 
     env = cpu_init();
     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
@@ -158,10 +158,11 @@ void mips_r4k_init (int ram_size, int vg
 	}
 
         /* load initrd */
+        initrd_size = 0;
         if (initrd_filename) {
-            if (load_image(initrd_filename,
-			   phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND)
-		== (target_ulong) -1) {
+            initrd_size = load_image(initrd_filename,
+                                     phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
+            if (initrd_size == (target_ulong) -1) {
                 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
                         initrd_filename);
                 exit(1);
@@ -169,7 +170,17 @@ void mips_r4k_init (int ram_size, int vg
         }
 
 	/* Store command line.  */
-        strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
+        if (initrd_size > 0) {
+            ret = sprintf(phys_ram_base + (16 << 20) - 256, 
+                          "rd_start=0x%08x rd_size=%li ",
+                          INITRD_LOAD_ADDR,
+                          initrd_size);
+            strcpy (phys_ram_base + (16 << 20) - 256 + ret, kernel_cmdline);
+	}
+	else {
+            strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
+	}
+
         /* FIXME: little endian support */
         *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
         *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
#4 lore raw
In reply to Aurelien Jarno
Quoted 16 lines · Aurelien Jarno

Hi!

Quoted 6 lines · Daniel Jacobowitz

These patches for qemu let IDE and initrd work in the defconfig. It seems to function - I was able to get as far as partitioning the drive in the debian installer and the next time I started qemu the new partitions were found. But the installer hangs up trying to format swap.

Quoted 6 lines

Of course, what would be really nice would be a PCI controller. I'm not brave enough to try.

I'm not going to submit the qemu change until I have some better evidence that it all works right (or someone else does).

Quoted 6 lines

First of all, thanks a lot for your work, that makes QEMU mips more usable.

The IDE part works very well, though there seems to be some problems with userland tools (mke2fs), an instruction is probably not/bad emulated. I now have a system with the root on the IDE drive and with swap.

After a week of test, I can say that the IDE part is working correctly (at least for me, and I suppose for you), I am using it on an emulated system with ext3 as the root partition, and with swap. There are some problems related to the userland tools (mke2fs) though.

Therefore I propose to submit the IDE part to QEMU. I have extracted it from your patch, which also contains initrd support.

Care to send it?

Thanks,
Aurelien

Signature · 4 lines
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   [email protected]         | [email protected]
   `-    people.debian.org/~aurel32 | www.aurel32.net

Index: Makefile.target
===================================================================
RCS file: /sources/qemu/qemu/Makefile.target,v
retrieving revision 1.130

Makefile.target +2 -2
diff -u -d -p -r1.130 Makefile.target
@@ -357,8 +357,8 @@ VL_OBJS+= grackle_pci.o prep_pci.o unin_
 DEFINES += -DHAS_AUDIO
 endif
 ifeq ($(TARGET_ARCH), mips)
-VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o
-#VL_OBJS+= #ide.o pckbd.o fdc.o m48t59.o
+VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o ide.o
+#VL_OBJS+= #pckbd.o fdc.o m48t59.o
 endif
 ifeq ($(TARGET_BASE_ARCH), sparc)
 ifeq ($(TARGET_ARCH), sparc64)

Index: hw/mips_r4k.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mips_r4k.c,v
retrieving revision 1.20

mips_r4k.c +9 -0
diff -u -d -p -r1.20 mips_r4k.c
@@ -7,6 +7,10 @@
 
 #define VIRT_TO_PHYS_ADDEND (-0x80000000LL)
 
+static const int ide_iobase[2] = { 0x1f0, 0x170 };
+static const int ide_iobase2[2] = { 0x3f6, 0x376 };
+static const int ide_irq[2] = { 14, 15 };
+
 extern FILE *logfile;
 
 static PITState *pit;
@@ -118,6 +122,7 @@ void mips_r4k_init (int ram_size, int vg
     int ret;
     CPUState *env;
     long kernel_size;
+    int i;
 
     env = cpu_init();
     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
@@ -198,6 +203,10 @@ void mips_r4k_init (int ram_size, int vg
             exit (1);
         }
     }
+
+    for(i = 0; i < 2; i++)
+        isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+                     bs_table[2 * i], bs_table[2 * i + 1]);
 }
 
 QEMUMachine mips_machine = {
#5 lore raw
Quoted 9 lines · Aurelien Jarno

After a week of test, I can say that the IDE part is working correctly (at least for me, and I suppose for you), I am using it on an emulated system with ext3 as the root partition, and with swap. There are some problems related to the userland tools (mke2fs) though.

Therefore I propose to submit the IDE part to QEMU. I have extracted it from your patch, which also contains initrd support.

Care to send it?

Could you do it? Since you've tested them more, and separated them, you might as well :-) I think that both this and the rd_size patch are good to submit.

I hope that I can find the time at some point to fix the problems blocking a Debian installer, but right at the moment I don't know when I'll have time.

Signature · 2 lines
Daniel Jacobowitz
CodeSourcery