On 27/04/13 07:06, Artyom Tarasenko wrote:
>> Is this a regression? If so, what was the last know good revision?
>
> Doesn't look like a regression. Checked the OpenBIOS image packaged with QEMU
> (they didn't update it recently) and it fails too.
> Just haven't tested it before. Usually I boot from a CD/DVD image or
> load the kernel directly with the -kernel option.
Ha okay - I finally figured this one out with a reproducible test case
like this:
1) First drop the Linux filesystem cache:
echo 3 > /proc/sys/vm/drop_caches
2) Start up QEMU - this now blows up in SILO:
./qemu-system-sparc64 -hda
/home/build/src/qemu/image/sparc64/debian-wheezy.qcow2 -boot c
-nographic -snapshot
3) Load the debian-wheezy.qcow2 image into the filesystem cache
cat debian-wheezy.qcow2 > /dev/null
4) Restart QEMU again and the image boots
./qemu-system-sparc64 -hda
/home/build/src/qemu/image/sparc64/debian-wheezy.qcow2 -boot c
-nographic -snapshot
Once I could reproduce this at will, I recompiled OpenBIOS with
CONFIG_DEBUG_IDE enabled and got the following output:
Jumping to entry point 0000000000004000 for type 0000000000000005...
switching to new context: entry point 0x4000 stack 0x00000000ffe86a39
SIDE - ob_ide_open: opening channel -1539032 unit 0
IDE DRIVE @ffe88428:
unit: 0
present: 1
type: 1
media: 32
model: QEMU HARDDISK
nr: 0
cyl: 8322
head: 16
sect: 63
bs: 512
IDE - ob_ide_block_size: ob_ide_block_size: block size 200
IDE - ob_ide_max_transfer: max_transfer 1fe00
IDE - ob_ide_read_blocks: ob_ide_read_blocks ffe86b20 block=0 n=1
IDE - ob_ide_read_sectors: ob_ide_read_sectors: block=0 sectors=1
IDE - ob_ide_read_blocks: ob_ide_read_blocks ffe86b20 block=0 n=1
IDE - ob_ide_read_sectors: ob_ide_read_sectors: block=0 sectors=1
IDE - ob_ide_read_blocks: ob_ide_read_blocks ffea9e98 block=2 n=2
IDE - ob_ide_read_sectors: ob_ide_read_sectors: block=2 sectors=2
IDE - ob_ide_read_blocks: ob_ide_read_blocks 41dc block=5248 n=1
IDE - ob_ide_read_sectors: ob_ide_read_sectors: block=5248 sectors=1
IDE - ob_ide_error: ob_ide_error drive<0>: timed out waiting for BUSY clear:
IDE - ob_ide_error: cmd=20, stat=d0IDE - ob_ide_error:
IDE - ob_ide_pio_data_in: bytes=512, stat=d0
IDE - ob_ide_read_blocks: ob_ide_read_blocks: error
EXIT
0 >
Looking at drivers/ide.c, it was apparent that we were timing out
waiting for the IDE event to finish:
/*
* wait for BUSY clear
*/
if (ob_ide_wait_stat(drive, 0, BUSY_STAT | ERR_STAT, &stat)) {
ob_ide_error(drive, stat, "timed out waiting for BUSY clear");
cmd->stat = stat;
break;
}
And ob_ide_wait_stat() has a loop that looks like this:
for (i = 0; i < 5000; i++) {
stat = ob_ide_pio_readb(drive, IDEREG_STATUS);
if (!(stat & BUSY_STAT))
break;
udelay(1000);
}
This led me to wonder if there was a problem with udelay() returning too
quickly and so I had a look at the implementation in
arch/sparc64/openbios.c which looks like this:
void udelay(unsigned int usecs)
{
}
Ah. So the problem is that we are not waiting long enough for the IDE
command to finish which is why we are getting the error. A quick patch
to get things working again for me is:
--- a/openbios-devel/arch/sparc64/openbios.c
+++ b/openbios-devel/arch/sparc64/openbios.c
@@ -547,6 +547,9 @@ void setup_timers(void)
void udelay(unsigned int usecs)
{
+ volatile int i;
+
+ for (i = 0; i < usecs * 100; i++);
}
But we probably need a better solution for this that works for both
SPARC32 and SPARC64. I've seen some code that waits for the RTC to tick
1s and measures the number of loop iterations within that time to find a
basic timing constant which looks quite appealing as it is simple and
will work across both SPARC32 and SPARC64 (SPARC32 doesn't have a %tick
register).
Blue - any thoughts on how to implement this?
ATB,
Mark.
On Sat, Apr 20, 2013 at 1:05 PM, Blue Swirl <blauwirbel(a)gmail.com> wrote:
> On Fri, Apr 19, 2013 at 9:10 PM, Artyom Tarasenko <atar4qemu(a)gmail.com> wrote:
>> On Mon, May 14, 2012 at 8:58 PM, Blue Swirl <blauwirbel(a)gmail.com> wrote:
>>> On Mon, May 14, 2012 at 1:49 PM, Mark Cave-Ayland
>>> <mark.cave-ayland(a)ilande.co.uk> wrote:
>>>> On 14/05/12 14:28, Artyom Tarasenko wrote:
>>>>
>>>>>>> It's to avoid VGA legacy mapping at 0xa0000. If I change
>>>>>>> hwdefs.pci.pci_mem_base in arch/sparc64/openbios.c to 0, OpenBIOS will
>>>>>>> crash during VGA init. Previously this worked because the PCI devices
>>>>>>> were mapped somewhat randomly and by chance, VGA legacy low mem area
>>>>>>> was avoided.
>>>>>>>
>>>>>>> I think the correct fix is to make QEMU VGA device disable the legacy
>>>>>>> mapping unless explicitly enabled. Alternatively the child base
>>>>>>> arithmetic could be fixed in OpenBIOS like proposed by Jakub.
>>>>>>
>>>>>>
>>>>>>
>>>>>> Did a patch ever come out of this discussion in the end?
>>>>>>
>>>>>
>>>>> No. :-) Feel free to fix it, unless Blue prefers fixing it himself...
>>>>
>>>>
>>>> I'm not sure I'm confident enough with PCI to do this, and I'm also not sure
>>>> what Blue's recommended fix actually is? Is it to increase parent_base by
>>>> 0x1000 or set child_base to zero?
>>>
>>> The best solution is to fix VGA (assuming my analysis was right) and
>>> set child_base to zero.
>>
>> Blue, do you know whether the QOMification improved the situation with
>> the legacy VGA low mem area?
>
> I don't think it had any effect, but PCI bridging code was fixed recently.
>
> There are still some problems, if I move most devices behind the first
> bridge with this patch, Sparc64 does not boot anymore:
> diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
> index 0d29620..8bf7230 100644
> --- a/hw/sparc64/sun4u.c
> +++ b/hw/sparc64/sun4u.c
> @@ -813,7 +813,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
> M48t59State *nvram;
> unsigned int i;
> uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
> - PCIBus *pci_bus, *pci_bus2, *pci_bus3;
> + PCIBus *pci_bus2, *pci_bus3;
> ISABus *isa_bus;
> qemu_irq *ivec_irqs, *pbm_irqs;
> DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
> @@ -829,12 +829,11 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
> prom_init(hwdef->prom_addr, bios_name);
>
> ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, cpu, IVEC_MAX);
> - pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs,
> &pci_bus2,
> - &pci_bus3, &pbm_irqs);
> - pci_vga_init(pci_bus);
> + pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2,
> + &pci_bus3, &pbm_irqs);
> + pci_vga_init(pci_bus2);
>
> - // XXX Should be pci_bus3
> - isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs);
> + isa_bus = pci_ebus_init(pci_bus2, -1, pbm_irqs);
>
> i = 0;
> if (hwdef->console_serial_base) {
> @@ -859,7 +858,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
>
> ide_drive_get(hd, MAX_IDE_BUS);
>
> - pci_cmd646_ide_init(pci_bus, hd, 1);
> + pci_cmd646_ide_init(pci_bus2, hd, 1);
>
> isa_create_simple(isa_bus, "i8042");
> for(i = 0; i < MAX_FD; i++) {
>
> Also ethernet is using the main PCI bus instead of the bridged version:
> (qemu) info pci
> Bus 0, device 0, function 0:
> Host bridge: PCI device 108e:a000
> id ""
> Bus 0, device 1, function 0:
> PCI bridge: PCI device 108e:5000
> BUS 0.
> secondary bus 1.
> subordinate bus 255.
> IO range [0x0000, 0x0fff]
> memory range [0x00000000, 0x000fffff]
> prefetchable memory range [0x00000000, 0x000fffff]
> id ""
> Bus 1, device 0, function 0:
> VGA controller: PCI device 1234:1111
> BAR0: 32 bit prefetchable memory at 0x01000000 [0x01ffffff].
> BAR2: 32 bit memory at 0x02000000 [0x02000fff].
> BAR6: 32 bit memory at 0x02010000 [0x0201ffff].
> id ""
> Bus 1, device 1, function 0:
> Bridge: PCI device 108e:1000
> BAR0: 32 bit memory at 0xffffffffffffffff [0x00fffffe].
> BAR1: 32 bit memory at 0xffffffffffffffff [0x007ffffe].
> id ""
> Bus 1, device 2, function 0:
> IDE controller: PCI device 1095:0646
> IRQ 0.
> BAR0: I/O at 0xffffffffffffffff [0x0006].
> BAR1: I/O at 0xffffffffffffffff [0x0002].
> BAR2: I/O at 0xffffffffffffffff [0x0006].
> BAR3: I/O at 0xffffffffffffffff [0x0002].
> BAR4: I/O at 0xffffffffffffffff [0x000e].
> id ""
> Bus 0, device 1, function 1:
> PCI bridge: PCI device 108e:5000
> BUS 0.
> secondary bus 0.
> subordinate bus 0.
> IO range [0x0000, 0x0fff]
> memory range [0x00000000, 0x000fffff]
> prefetchable memory range [0x00000000, 0x000fffff]
> id ""
> Bus 0, device 2, function 0:
> ^ should be bus 1.
But in your patch above you didn't touch the Ethernet, only cmd646 and
vga, or am I missing something?
Another question - is VGA legacy low mem area turned on by the PCI
feature called "DOS Compatibility" in the PBM and APB docs?
Both PBM and APB docs say that they don't have "DOS Compatibility" feature.
Maybe it's possible to tell the VGA card, that we don't need the low mem area?
>
> Ethernet controller: PCI device 10ec:8029
> IRQ 0.
> BAR0: I/O at 0xffffffffffffffff [0x00fe].
> BAR6: 32 bit memory at 0xffffffffffffffff [0x0003fffe].
> id ""
>
>>
--
Regards,
Artyom Tarasenko
linux/sparc and solaris/sparc under qemu blog:
http://tyom.blogspot.com/search/label/qemu
On 27/04/13 12:47, Blue Swirl wrote:
> Maybe we should make a macro similar to OLDWORLD() and NEWWORLD() for Sparc64?
Hmmm yes. That could be a nice tidy-up...
ATB,
Mark.
The patches 1/3 and 2/3 are depending on the QEMU pbm patch.
Together they allow using multiple PCI (virtio) devices simultaneously.
Tested on installing Debian Wheezy / sparc64.
http://tyom.blogspot.de/2013/03/debiansparc64-wheezy-under-qemu-how-to.html…
Without the patches the install process hangs at random places between 6% and 60%.
The patch 3/3 is a trivial rename patch.
Artyom Tarasenko (3):
sparc64: use direct interrupt mapping for PCI devices
sparc64: remove hacks for the "interrupts" property
use the proper name for the virtio-blk devices
drivers/ide.c | 2 --
drivers/pci.c | 15 +++++++--------
drivers/pci_database.c | 6 +++---
drivers/pci_database.h | 1 -
4 files changed, 10 insertions(+), 14 deletions(-)
Author: blueswirl
Date: Sat Apr 27 13:42:18 2013
New Revision: 1133
URL: http://tracker.coreboot.org/trac/openbios/changeset/1133
Log:
use the proper name for the virtio-blk devices
The name 'virtio-scsi' is misleading, since there is another device
called 'virtio-scsi' in QEMU. Use the name 'virtio-blk' instead.
Signed-off-by: Artyom Tarasenko <atar4qemu(a)gmail.com>
Signed-off-by: Blue Swirl <blauwirbel(a)gmail.com>
Modified:
trunk/openbios-devel/drivers/pci_database.c
Modified: trunk/openbios-devel/drivers/pci_database.c
==============================================================================
--- trunk/openbios-devel/drivers/pci_database.c Sat Apr 27 13:42:16 2013 (r1132)
+++ trunk/openbios-devel/drivers/pci_database.c Sat Apr 27 13:42:18 2013 (r1133)
@@ -49,7 +49,7 @@
{
/* Virtio-block controller */
PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_BLOCK,
- NULL, "virtio-scsi", NULL,
+ NULL, "virtio-blk", NULL,
"pci1af4,1001\0pci1af4,1001\0pciclass,01018f\0",
0, 0, 0,
NULL, NULL,
On 26/04/13 23:21, Artyom Tarasenko wrote:
>> In that case can you just try removing this part of the address reservation
>> code from SVN trunk like this:
>>
>> --- a/openbios-devel/arch/sparc32/openbios.c
>> +++ b/openbios-devel/arch/sparc32/openbios.c
>> @@ -820,9 +820,6 @@ static void init_memory(void)
>>
>> /* Generate the mapping (and lock translation into the TLBs) */
>> ofmem_map(phys, virt, MEMORY_SIZE,
>> ofmem_arch_default_translation_mode(phys));
>>
>> - /* Mark everything up until OFMEM_VIRT_TOP as in use */
>> - ofmem_claim_virt(OFMEM_VIRT_TOP, OF_CODE_START - MEMORY_SIZE -
>> OFMEM_VIRT_TOP, 0);
>> -
>> /* we push start and end of memory to the stack
>> * so that it can be used by the forth word QUIT
>> * to initialize the memory allocator
>>
>> Now the only remaining memory reserved in that region is at the very top
>> end, and is just the 128K Forth dictionary which from your tests before
>> should work.
>
> Yes, I figured that too. Did some testing yesterday night, and it looked ok.
> As for the exact value of OFMEM_VIRT_TOP, I'm not sure any more that
> 0xff000000 is better than the current value. I think SunOS might behave
> differently just because of conflicting with OpenBIOS memory mappings.
Great! I've just committed a patch to remove these lines to SVN trunk.
ATB,
Mark.