OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 12:44 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Problem with PCI on QEMU
PostPosted: Thu Feb 04, 2021 10:50 pm 
Offline
Member
Member

Joined: Sat Sep 07, 2019 5:17 pm
Posts: 34
I'm enumerating PCI by myself, configuring buses like there was no tommorrow, and playing a game called "Who is behind that PCI bus?".

However, i started writing some drivers, and then when i wrote the rtl driver:..

Code:
(qemu) info pci
  Bus  0, device   0, function 0:
    Host bridge: PCI device 1b36:0008
      PCI subsystem 1af4:1100
      id ""
  Bus  0, device   1, function 0:
    VGA controller: PCI device 1234:1111
      PCI subsystem 1af4:1100
      BAR0: 32 bit prefetchable memory at 0x4b000000 [0x4bffffff].
      BAR2: 32 bit memory at 0x40001000 [0x40001fff].
      BAR6: 32 bit memory at 0xffffffffffffffff [0x0000fffe].
      id ""
  Bus  0, device   2, function 0:
    Ethernet controller: PCI device 10ec:8139
      PCI subsystem 1af4:1100
      IRQ 0, pin A
      BAR0: I/O at 0x45000100 [0x450001ff].
      BAR1: 32 bit memory at 0x40002100 [0x400021ff].
      BAR6: 32 bit memory at 0xffffffffffffffff [0x0003fffe].
      id ""


This is fine at first point, but oh no, qemu hates me now:
Code:
(qemu) Invalid access at addr 0x45000152, size 1, region '(null)', reason: rejected


I honestly want to believe this is a bug with QEMU and not my OS PCI BAR allocator being weird.
No paging is enabled, kernel is multitasking but PCI enumeration occurs before scheduling the kernel.
I don't see any heap corruption. The BARs cannot be faulty tho, because they do not overlap.
The BARs are correctly aligned (the spec says that BARs must be aligned to their size, so 4096 byte bar is aligned to 4096 bytes).
The device is not behind a PCI bridge, this is managed by the root PCI controller, which spans the whole MMIO area, enough right?
Yes, bus mastering is enabled, and yes, IO and MEM register accesses are enabled too.
This is the first command send - write 0x00 to register 0x52 of the RTL to power it on.
And this is not x86, this is RISC-V (64 bits), So no BIOS or ACPI.

If this is a IO error, then why does my VGA driver work?, It can initialize anything and (sucessfuly) manage to resize the screen to any resolution.

In the other part, the rtl8139 driver dies like there was no tommorrow.

The code who causes this is here:
Code:
   case PCI_TURN_ON:
      /* Turn on the device */
      mmio_write8(io+0x52,0x00);


Which in turn calls:
Code:
void mmio_write8(uint8_t * port, uint8_t value) {
   (*port) = value;
}


And this causes a load fault :)

_________________
:-)


Top
 Profile  
 
 Post subject: Re: Problem with PCI on QEMU
PostPosted: Fri Feb 05, 2021 2:24 am 
Offline
Member
Member
User avatar

Joined: Sun Apr 30, 2017 12:16 pm
Posts: 68
Location: Poland
As far as I can see you allocated 0x45000152 for the IO bar and are trying to access it as if it's MMIO. To access it (on x86) you have to use in/out instructions (which limits the max address to 0xFFFF), or on other architectures, access them through the host bridge IO window (IO window host addr + IO port) if one exists.

BTW, what are you targeting that requires you to allocate BARs manually?
EDIT: oops, missed the part where you said you're targeting RISC-V, sorry.

_________________
Working on managarm.


Top
 Profile  
 
 Post subject: Re: Problem with PCI on QEMU
PostPosted: Mon Jun 14, 2021 1:11 am 
Offline
Member
Member
User avatar

Joined: Fri Jun 11, 2021 6:02 am
Posts: 96
Location: Belgium
I've stumbled upon this issue and after some hairloss I've figured out what to do (I think). I'm aware this thread is several months old but it shows up in Google searches so I figure it's still worth answering.

First: RISC-V doesn't have I/O ports, it only has MMIO. You should ignore any I/O space BARs as you can't use them and stick to memory space BARs.

Second: maybe you got this right, but you have to ensure the addresses are in a valid MMIO range, which you can get from the
Code:
ranges
property in the FDT.

As for why BARs need to be set manually: they're 0 (minus flags) by default in QEMU at least, so you need to set them yourself.

_________________
My OS is Norost B (website, Github, sourcehut)
My filesystem is NRFS (Github, sourcehut)


Top
 Profile  
 
 Post subject: Re: Problem with PCI on QEMU
PostPosted: Tue Jun 15, 2021 3:47 am 
Offline
Member
Member
User avatar

Joined: Sun Apr 30, 2017 12:16 pm
Posts: 68
Location: Poland
Demindiro wrote:
You should ignore any I/O space BARs as you can't use them and stick to memory space BARs.


This is not quite right. The device tree "ranges" property may also specify a window that's MMIO on the parent (CPU) side, but port IO on the child (PCI bus) side. This is accomplished by having bits 65-64 (since for PCI nodes child addresses are 96 bits long) of the child address be set to 01 (as opposed to 10 or 11 for memory windows).

To take advantage of this, use the child address as the base of the port you write into the BAR, then when you want to access the "ports" just write to window at the specified host address + any offset you also applied on the child side.

_________________
Working on managarm.


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: No registered users and 76 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