USB XHCI Event ring not working

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
slammar
Posts: 24
Joined: Fri Feb 07, 2020 7:35 pm
Libera.chat IRC: slammar

USB XHCI Event ring not working

Post by slammar »

Hello, I am desperate to make my xhci work, but I have no clue why it doesn't.
Currently I am just trying to make a "hello world" xhci driver which only prints the contents of the event TRB generated by a NOOP TRB in the command ring, but it just doesn't work in VirtualBox, so I tried to look around for another osdever who successfully did something similar in an operating system simple enough to study it's source code, and ended up with SanderOSUSB:
https://github.com/AdeRegt/SanderOSUSB/ ... dev/xhci.c

However, when I compile and test this operating system in VirtualBox, I get this error message:

Code: Select all

[XHCI] Incompatible device!
This message is printed from this line of code:
https://github.com/AdeRegt/SanderOSUSB/ ... hci.c#L788

What causes this message to be printed is that the Serial Bus Release Number Register's value (sbrn variable) is 0x20 instead of 0x30 or 0x31. The xhci specs clearly states in chapter 5.2.3 that the value of this register must be 0x30, 0x31 or 0x32. I checked the value of this register and it's value is 0x20 in VirtualBox. If that number represent the release of the usb specification the xhci is compilant with, there shouldn't be any problem regarding the usage of the Command Ring, since it does not involve any transaction with any usb device and (I think) the usb specification is not involved here and it should not be a problem (The usb protocol does not have anything to do with how the command ring should work, right?)

So I commented out that check to see if the event ring works: https://github.com/AdeRegt/SanderOSUSB/ ... ci.c#L1027

I commented out line 1033 and added an infinite loop to stop execution between lines 1036 and 1037. When I executed the operating system again this time instead the OS got stuck in the infinite loop at line 660. When I read the event ring from my operating system I only get zeroes, and I am starting to suspect that the xhci just doesn't work properly in VirtualBox. However, if that were the case, How do current operating systems like Linux or Windows make it work? I tried to study the xhci driver of linux, but it is a mess and the kernel is a monster extremely complex and not really worth to study to learn how to make my xhci driver work because it would take me forever to understand enough to find what I am doing wrong right now.

Can anyone explain why VirtualBox's xhci device return that Serial Bus Release Number Register's value and why apparently the Event Ring doesn't work?

The SanderOSUSB's developer didn't even bother to try to check event ring functionality in QEMU, as you can see here:
https://github.com/AdeRegt/SanderOSUSB/ ... ci.c#L1027
Why does QEMU fails miserably testing the ring? Can you make it work in QEMU, or is it doomed to not work at all?

And most importantly, Could anyone please share a repository with a proof of concept operating system to demonstrate xhci functionality (preferable if it works, at least, in Qemu and VirtualBox)? What I mean by this is an operating system as simple as possible that stores or reads a byte in a USB mass storage device or detect a USB keyboard key press. I know this is too much to ask for but if someone by chance has this, it would be extremely helpful to have it.

Thanks in advance.
Last edited by slammar on Thu Jun 11, 2020 2:16 pm, edited 1 time in total.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: USB XHCI not working in virtualbox

Post by BenLunt »

What I see here is that you probably have not set up Virtual Box'es xHCI emulation correctly. xHCI is not supported by default. You have to download and install the extension pack to support xHCI.

This extension pack is available at: https://www.virtualbox.org/wiki/Downloads

Ben
- http://www.fysnet.net/the_universal_serial_bus.htm
slammar
Posts: 24
Joined: Fri Feb 07, 2020 7:35 pm
Libera.chat IRC: slammar

Re: USB XHCI not working in virtualbox

Post by slammar »

I had the extension pack installed already, so that is not the problem.
Also, I tried the operating system in my laptop which has xhci, and it looks like the event ring doesn't work properly, but it is clear that is not the fault of my computer, but something the SanderOSUSB operating system is missing that I also do.

Could you please share a minimal operating system that shows how to send and receive data from and to usb devices?
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: USB XHCI not working in virtualbox

Post by PeterX »

slammar wrote:I had the extension pack installed already, so that is not the problem.

Could you please share a minimal operating system that shows how to send and receive data from and to usb devices?
I doubt that such is available because minimal OS and USB don't fit together well. Why don't you develop such an OS ypurself? Is reading the specs and tutorials and doing some work out of fashion?

Greetings
Peter
slammar
Posts: 24
Joined: Fri Feb 07, 2020 7:35 pm
Libera.chat IRC: slammar

Re: USB XHCI not working in virtualbox

Post by slammar »

PeterX wrote:
slammar wrote:I had the extension pack installed already, so that is not the problem.

Could you please share a minimal operating system that shows how to send and receive data from and to usb devices?
I doubt that such is available because minimal OS and USB don't fit together well. Why don't you develop such an OS ypurself? Is reading the specs and tutorials and doing some work out of fashion?

Greetings
Peter
Here is my attempt to make an USB operating system as simple as possible:
xhci_proof_of_concept-master.zip
(13.26 KiB) Downloaded 57 times
It only sends a NOOP TRB to the command ring and read the event ring to demonstrate some basic behaviour, unsucessfully because it only reads zeroes.

The reason why I don't develop such an OS myself is because I am, in fact, trying, but I can't because I am missing something and I don't know what.

Note: I am going to change the title from "USB XHCI not working in virtualbox" to "USB XHCI Event ring not working" because I realized it doesn't work in my laptop as well.
Last edited by slammar on Sun Jul 26, 2020 12:41 pm, edited 1 time in total.
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: USB XHCI Event ring not working

Post by PeterX »

Haiku does XHCI in C++. Maybe C++ makes it more debuggable?
https://github.com/haiku/haiku/blob/mas ... b/xhci.cpp

Greetings
Peter
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: USB XHCI Event ring not working

Post by BenLunt »

slammar wrote:What causes this message to be printed is that the Serial Bus Release Number Register's value (sbrn variable) is 0x20 instead of 0x30 or 0x31. The xhci specs clearly states in chapter 5.2.3 that the value of this register must be 0x30, 0x31 or 0x32. I checked the value of this register and it's value is 0x20 in VirtualBox.
I just confirmed, Virtual Box indeed returns 0x30.

You might check your PCI(e) enumeration code to be sure that you are loading the correct driver for the found card.

Ben

Edit/Update: As mentioned in a different post, I mistakenly thought the OP was talking about the Programming Interface value here. Therefore, my confirmation noted above is wrong. I confirmed the Programming Interface value, not the SBRN value. Sorry, my mistake.
Last edited by BenLunt on Sun Jul 26, 2020 8:59 pm, edited 1 time in total.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: USB XHCI Event ring not working

Post by BenLunt »

I was looking through your code and am wondering why you skip functions 1 through 7.

Code: Select all

    add eax, 0_0000000_00000000_00001_000_00000000b
    cmp eax, 1_0000001_00000000_00000_000_00000000b
For example, an EHCI controller will most likely always be on function 7 with companion controllers being on function 0 through 6. i.e.: Any companion controller must have a function number less than the parent controller.

With your current code, what if an xHCI controller is not on function 0, but one of the other functions?

An off-the-shelf add-on I/O card might have an SATA controller as well as an xHCI controller all on one card. The Device number would be the same, but the two functions would have different function numbers.

I would suggest that you wrap your read and write pci macros to preserve DX. It is very easy to forget that they modify DX when "calling" them from another function. By doing this, you can then remove the preservation of DX from your "find xHCI" code.

Also, why do you use a macro that uses three XOR instructions to exchange two registers when the x86 arch has an exchange instruction? In fact, when using the acum register, (e)ax, the instruction might be only a one byte instruction.

Anyway, none of this really explains why your code isn't working, other than if your xHCI controller is not on function 0 of a device.

I do have a question, at line 50 of kernel.asm, what value does ES have?

Ben
- http://www.fysnet.net/the_universal_serial_bus.htm
slammar
Posts: 24
Joined: Fri Feb 07, 2020 7:35 pm
Libera.chat IRC: slammar

Re: USB XHCI Event ring not working

Post by slammar »

I do have a question, at line 50 of kernel.asm, what value does ES have?
In the second line of kernel.asm you will see included a file that manages everything about protected mode:

Code: Select all

%include "./utils/protected_mode.asm"
In that file, the ES register's value is set at line 49 like this:

Code: Select all

mov ax, protected_mode.gdt_data - protected_mode.gdt_start
mov ds, ax
mov es, ax
The data segment descriptor of the GDT is set as follows:

Code: Select all

protected_mode.gdt_data:
    dw 0xFFFF       ; Segment Limit 15:00
    dw 0x0000       ; Base Address 15:00
    db 0x00         ; Base Address 23:16
       ; Present     Privilege      Descriptor type     Executable      Expansion-direction     Write-enable    Accessed
    db 0b1___________00_____________1___________________0_______________0_______________________1_______________0
       ; Granularity    32 bits     64 bits     Available   Segment Limit 19:16
    db 0b1______________1___________0___________0___________1111
    db 0x00         ; Base 31:24

protected_mode.gdt_end:
Therefore, the ES register's value corresponds with a data segment that comprises the whole memory.
I was looking through your code and am wondering why you skip functions 1 through 7
I had understood functions were something else that I didn't even understand and I thought PCI devices were only at function zero and other functions had another functionality or something.
Also, why do you use a macro that uses three XOR instructions to exchange two registers when the x86 arch has an exchange instruction? In fact, when using the acum register, (e)ax, the instruction might be only a one byte instruction.
Because I am a n00b at assembly and didn't know about the XCHG instruction.
I just confirmed, Virtual Box indeed returns 0x30
It's a relief that is just my fault and not VirtualBox's one. I am going to refactor my code to make it more organized to make sure I am not making mistakes.
Post Reply