OSDev.org

The Place to Start for Operating System Developers
It is currently Wed Apr 24, 2024 9:48 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Bochs DMA Errors and invlaid DMA Bus Master port # PCI BAR4
PostPosted: Mon Oct 29, 2018 2:41 pm 
Offline
Member
Member

Joined: Tue Oct 29, 2013 1:13 pm
Posts: 207
HI,

I have a problem with DMA in bochs and qemu.

I have my OS run correctly in virtual box. when I tried to run it on bochs the DMA IDE interrupts stopped to fire upon reading sectors.

I have been struggling with this for a couple of days with no clue of what is going on.

I have enabled DMA debugging in side bochs and I have noticed during the BIOS initialization that the DMA debug messages indicate that the DMA Bus Master I/O port is 0x80 or 0x000d ?!!

Code:
00000000000d[DMA   ] write: address=000d value=00
00000000000d[DMA   ] DMA-1: master clear
00000000000d[DMA   ] write: address=00da value=00
00000000000d[DMA   ] DMA-2: master clear
00000000005d[DMA   ] write: address=00d6 value=c0
00000000005d[DMA   ] DMA-2: mode register[0] = c0
00000000005d[DMA   ] write: address=00d4 value=00
00000000005d[DMA   ] DMA-2: set_mask_bit=0, channel=0, mask now=00h
00000005160d[DMA   ] write: address=0080 value=00
00000005160d[DMA   ] write: extra page register 0x0080 (unused)
00000005200d[DMA   ] write: address=0080 value=00
00000005200d[DMA   ] write: extra page register 0x0080 (unused)
00000005235d[DMA   ] write: address=0080 value=00
00000005235d[DMA   ] write: extra page register 0x0080 (unused)
00000005275d[DMA   ] write: address=0080 value=00
00000005275d[DMA   ] write: extra page register 0x0080 (unused)
00000005310d[DMA   ] write: address=0080 value=00

......


The important thing is that it is different from the value I read from BAR4 in the PCI header of the ATA disk I have which is 0xC001, and having the status bit set indicates that it is an I/O port and not mem/io so the port address i 0xc000.

When I try to write to this address, bochs does not generate any debug output which made me suspect that there is something wrong with this address.

I hardwired the dma port address to 0x80 and only then bochs starts spitting out debug info upon writing to that address.

The problem is that I still cannot get interrupts to fire.

An error occurs when I try to write to the address offset to set the DMA table (offset 4) and the debug output is as follows:

Code:
00704828900d[DMA   ] write: address=0080 value=00
00704828900d[DMA   ] write: extra page register 0x0080 (unused)
00704828910d[DMA   ] write: address=0082 value=06
00704828910d[DMA   ] DMA-1: page register 3 = 06
00704828920e[DEV   ] write to port 0x0084 with len 4 ignored
00704838220d[DMA   ] read addr=0082
00704843265d[DMA   ] write: address=0080 value=09
00704843265d[DMA   ] write: extra page register 0x0080 (unused)


Notice the write to 0x0084, that is the attempt to write to the address offset which says that it is ignored.

Any help will be much appreciated.
Thanks a lot,
Karim.


Top
 Profile  
 
 Post subject: Re: Bochs DMA Errors and invlaid DMA Bus Master port # PCI B
PostPosted: Mon Oct 29, 2018 9:28 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5145
kemosparc wrote:
I have enabled DMA debugging in side bochs and I have noticed during the BIOS initialization that the DMA debug messages indicate that the DMA Bus Master I/O port is 0x80 or 0x000d ?!!

Those are the ISA DMA controller ports. They're not used for PCI.

Enable debugging for the pci_ide device instead of the DMA device.


Top
 Profile  
 
 Post subject: Re: Bochs DMA Errors and invlaid DMA Bus Master port # PCI B
PostPosted: Thu Nov 01, 2018 2:31 am 
Offline
Member
Member

Joined: Tue Oct 29, 2013 1:13 pm
Posts: 207
Hi,

Thanks a lot for the reply.

I have enabled the pci_ide debug option.

I did some experiments that might help helping me:)

Now for virtualbox my OS run with no problems and with the expected functionalities.

I have downloaded bochs 2.6.9 (the latest) and I have tried running my OS on the three environments Bochs 2.6.8, 2.6.9, and Qemu.

First of all here is the code portion that has the problem:
Code:
uint8_t readDMADiskSectors (ATADisk * p_ataDisk,uint64_t addr,uint32_t p_sector_count)
{
    uint16_t io_port = p_ataDisk->io_port;
    uint32_t dma_port_address = p_ataDisk->dma_port_address;
    uint8_t * dma_phy_address = p_ataDisk->dma_phy_address;
    uint32_t * ptr = (uint32_t *)p_ataDisk->prdt;
    memset(dma_phy_address,0,0x2000000);
   
    uint32_t sectors = p_sector_count;
    uint16_t i = 0;
    for ( ;sectors > 0; i+= 2 )
    {
        if ( sectors > 128 )
        {
            ptr[i] = (uint64_t) dma_phy_address+ ((i/2) * 0x10000);
            ptr[i+1] = 0x00000000 | (128 * 0x200);
            sectors -= 128;
        }
        else if (sectors  <= 128)
        {
            ptr[i] = (uint64_t) dma_phy_address+ ((i/2) * 0x10000);
            ptr[i+1] = 0x80000000 | (sectors * 0x200);
            sectors = 0;
        }
    }   
    outportb(dma_port_address+BM0_COMMAND+p_ataDisk->bm_offset,0);
    outportb(dma_port_address+BM0_STATUS+p_ataDisk->bm_offset,(1<<2)|(1 << 1));
    outportl(dma_port_address+BM0_ADDRESS+p_ataDisk->bm_offset,(uint32_t)ptr);

    uint8_t select = (0xE0 | (p_ataDisk->slavebit << 4));
    if (kernel.dmaBuffer.current_select != select )
    {
        if (  p_ataDisk->lba48)
        {
            printk ("reading lba48\n");
            outportb(io_port + ATA_REG_HDDEVSEL,select);
        }
        else outportb(io_port + ATA_REG_HDDEVSEL, (select | ((addr >> 24) & 0x0F)));
        ide_400ns_delay(p_ataDisk);
        kernel.dmaBuffer.current_select = select;
    }
    printk ("io_port: %x\n",io_port);

    outportb(io_port + ATA_REG_FEATURES, 0x00);
    outportb(io_port + ATA_REG_SECCOUNT1, (uint8_t)(p_sector_count >> 8));   
    outportb(io_port + ATA_REG_LBA3, (uint8_t)(addr >> 24));
    outportb(io_port + ATA_REG_LBA4, (uint8_t)(addr >> 32));
    outportb(io_port + ATA_REG_LBA5, (uint8_t)(addr >> 40));
    outportb(io_port + ATA_REG_SECCOUNT0,(uint8_t) p_sector_count);
    outportb(io_port + ATA_REG_LBA0, (uint8_t)addr);
    outportb(io_port + ATA_REG_LBA1, (uint8_t)(addr >> 8));
    outportb(io_port + ATA_REG_LBA2, (uint8_t)(addr >> 16));

    if ( p_ataDisk->lba48) outportb(io_port + ATA_REG_COMMAND, ATA_CMD_READ_DMA_EXT);
    else outportb(io_port + ATA_REG_COMMAND, ATA_CMD_READ_DMA); // 0xC8 for reading
    if (inportb(io_port + ATA_REG_STATUS))
    {
        for (uint64_t i = 0 ;;i++)
        {
            uint8_t status = inportb(io_port+ATA_REG_STATUS);
            if ( (status & ATA_SR_BSY))
            {
                printk ("DMA status is BSY: %d\n",i);
                continue;
            }
            else if(status & ATA_SR_ERR)
            {
                printk ("<<<<<< Error in readDMADiskSector: %x\n",status);
                if (p_ataDisk->bm_offset == 0 ) outportb(ATA_PRIMARY_DCR_AS,0b00000000);
                else outportb(ATA_SECONDARY_DCR_AS,0b00000000);
                if (  p_ataDisk->slavebit )
                    outportb(io_port + ATA_REG_HDDEVSEL, ATA_SLAVE_DRV_SELECTOR);
                else outportb(io_port + ATA_REG_HDDEVSEL, ATA_MASTER_DRV_SELECTOR);
                ide_400ns_delay(p_ataDisk);
                status = inportb(io_port+ATA_REG_STATUS);
                kernel.dmaBuffer.current_select = 0;
                return READ_DMA_FAIL;
            }
            else if ( status & ATA_SR_DRQ )break;
            else printk ("%d:Something else: %d\n",i,status);
        }
    }
    outportb(dma_port_address+BM0_COMMAND+p_ataDisk->bm_offset,(1 << 3)|(1 << 0));   
    return READ_DMA_SUCCESS;
}



Now, for bochs 2.6.9 everything works very well as virtualbox, and the pci_ide debug info shows the disk firing interrupts as expected after committing to the DMA command register.

On my already installed bochs 2.6.8 (the old one), still the ATA commands run successfully but the DMA does not fire the interrupts and the debug info stops at the debug line indicating that I have written successfully to the DMA command register to start the transfer.

Finally on qemu, It does not even go beyond the ATA extended read. After the read I get caught in the loop of checking the ATA status and never get out of it as the keeps on being busy and printing the busy message after each ata status read.

The disk I am trying to read from is the primary/slave ata.

I start my Qemu using the following command:

Code:
qemu-system-x86_64 -cpu host -m 4096 -smp 4 -drive file=./boot.qcow2,if=ide,index=0,media=disk -drive file=./data.qcow2,if=ide,index=1,media=disk  --enable-kvm


And I use the following bochsrc to start bochs in both versions.

Code:
config_interface: textconfig
display_library: x
romimage: file=/home/kmsobh/crossenv/bochs-2.6.8/bios/BIOS-bochs-latest
vgaromimage: file=/usr/share/vgabios/vgabios.bin
debug: action=ignore, pci_ide=report
error: action=report
info: action=ignore #,ioapic=report #pci=report, pic=report, pci_ide=report
#debug: action=ignore , cpu1=report #, e1000=report, ioapic=report #memory=report #pci_ide=report
memory: guest=8192, host=2048
boot: disk
ata0-master: type=disk, path="./images/boot.raw"
ata0-slave: type=disk, path="./images/data.raw"
cpu: count=4, ips=10000000
cpuid: x86_64=1,apic=x2apic
plugin_ctrl: unmapped=0


One remark that I do not know if it is important or not is that bochs 2.6.8 starts and get the bochs emulator window much much faster than 2.6.9, and as soon as the emulation starts both progress at the same speed.

Please let me know if you can figure out the problem.

I appreciate any help,

Thanks a lot,

Karim.


Top
 Profile  
 
 Post subject: Re: Bochs DMA Errors and invlaid DMA Bus Master port # PCI B
PostPosted: Thu Nov 01, 2018 8:58 am 
Offline
Member
Member

Joined: Tue Oct 29, 2013 1:13 pm
Posts: 207
Hi,

Just a quick update. I was trying to compare bochs two versions and I have inserted some printfs in the bochs code to identify what is the difference between the execution of my OS in both 2.6.8 and 2.6.9 and I found that in the method void bx_pci_ide_c::timer() as below the printf which prints "2 >>>>>> ..." is invoked in 2.8.6 which disallow reaching the firing of the interrupt and it keeps on printing it on the console infinitely just right after writing to the BM0 Command:

Code:
void bx_pci_ide_c::timer()
{
  int count;
  Bit32u size, sector_size;
  struct {
    Bit32u addr;
    Bit32u size;
  } prd;
  Bit8u channel = bx_pc_system.triggeredTimerParam();
  if (((BX_PIDE_THIS s.bmdma[channel].status & 0x01) == 0) ||
      (BX_PIDE_THIS s.bmdma[channel].prd_current == 0)) {
printf ("1 >>>>>>>> bx_pci_ide_c::timer()\n");
    return;
  }
  if (BX_PIDE_THIS s.bmdma[channel].cmd_rwcon &&
      !BX_PIDE_THIS s.bmdma[channel].data_ready) {
    printf ("2 >>>>>>>> bx_pci_ide_c::timer(): %d, %d\n",BX_PIDE_THIS s.bmdma[channel].cmd_rwcon,BX_PIDE_THIS s.bmdma[channel].data_ready);
    bx_pc_system.activate_timer(BX_PIDE_THIS s.bmdma[channel].timer_index, 1000, 0);
    return;
  }
  DEV_MEM_READ_PHYSICAL(BX_PIDE_THIS s.bmdma[channel].prd_current, 4, (Bit8u *)&prd.addr);
  DEV_MEM_READ_PHYSICAL(BX_PIDE_THIS s.bmdma[channel].prd_current+4, 4, (Bit8u *)&prd.size);
  size = prd.size & 0xfffe;
  if (size == 0) {
    size = 0x10000;
  }



I am still investigating what causes that, but with no luck till now. I f any one can figure it out please let me know.

Thanks,
Karim.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 189 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group