MMIO Registers all empty [resolved]

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
0b1
Member
Member
Posts: 35
Joined: Sun Feb 04, 2018 8:04 pm

MMIO Registers all empty [resolved]

Post by 0b1 »

Has anybody successfully queried the MAC address from an 8254 NIC on QEMU?

I can get the interrupt and BAR0 via I/O, but I am unable to get the MAC address from MMIO or from EEPROM.

There are several online examples that follow BareMetal's example to the letter, as does mine. But my MMIO addresses are all blank.

PC Configuration (from QEMU monitor):

Code: Select all

  Bus  0, device   3, function 0:
    Ethernet controller: PCI device 8086:100e
      IRQ 11.
      BAR0: 32 bit memory at 0xfeb80000 [0xfeb9ffff].
      BAR1: I/O at 0xc000 [0xc03f].
      BAR6: 32 bit memory at 0xffffffffffffffff [0x0003fffe].
      id ""
Contents of memory retrieved via GDB:

Code: Select all

gdb) x/128bx 0xfeb80000
0xfeb80000:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80008:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80010:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80018:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80020:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80028:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80030:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80038:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80040:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80048:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80050:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80058:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80060:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80068:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80070:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xfeb80078:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
A dump of PCI configuration space:
PCI Register dump
PCI Register dump
pci-registers.PNG (10.5 KiB) Viewed 2119 times
My OS seedling run 64 bit. The only thing I can think of is:
- Do I need to somehow initialize MMIO for this card before I can use it?
- I blindly set up 1GB page tables for the lower 512GB, regardless of memory presence. Could this be interfering?

Before I do a lot of experimental rework that may be a dead-end, does anyone have any ideas??

Thanks in advance!

DP
Last edited by 0b1 on Mon Jul 02, 2018 10:44 am, edited 1 time in total.
Code or code not. There is no try.
quirck
Member
Member
Posts: 42
Joined: Sun Nov 23, 2008 5:56 am
Location: Russia, Saint-Petersburg

Re: MMIO Registers all empty

Post by quirck »

Hi!

A quick question: do you set mac address when launching qemu?

From qemu user manual:
-nic [tap|bridge|user|l2tpv3|vde|netmap|vhost-user|socket][,...][,mac=macaddr][,model=mn]

This option is a shortcut for configuring both the on-board (default) guest NIC hardware and the host network backend in one go. The host backend options are the same as with the corresponding -netdev options below. The guest NIC model can be set with model=modelname. Use model=help to list the available device types. The hardware MAC address can be set with mac=macaddr.

The following two example do exactly the same, to show how -nic can be used to shorten the command line length (note that the e1000 is the default on i386, so the model=e1000 parameter could even be omitted here, too):

qemu-system-i386 -netdev user,id=n1,ipv6=off -device e1000,netdev=n1,mac=52:54:98:76:54:32
qemu-system-i386 -nic user,ipv6=off,model=e1000,mac=52:54:98:76:54:32
0b1
Member
Member
Posts: 35
Joined: Sun Feb 04, 2018 8:04 pm

Re: MMIO Registers all empty

Post by 0b1 »

Hi Quirck,

Thanks for the quick response. I tried that and got the same response -- empty MMIO.

I had a brainwave a took as look at QEMU's monitor against my original command line...

Code: Select all

info registers
hub0port1: e1000.1: index=0,type=nic,model=e1000,macaddr=52:54:00:12:34:57
hub0port0: e1000.0: index=0,type=nic,model=e1000,macaddr=52:54:00:12:34:56
So the QEMU, or at least the NIC, appears to think it has a MAC addresss.

My init code looks at lot like the others...

Code: Select all

nic_8254_init:
   ;initializes the NIC, following BareMetal et al.  
   ;contains various debug statements and commented-out code. Debug statements do a full save/restore of the stack.

	;inputs:
	;	 RDX - PCI Map entry address of the card 

	MOV R8, RDX		;save RDX

	;write the model into the PCI map
	MOV RSI, MSG_8254_MODEL
	MOV RDI, RDX
	ADD RDI, pci_map_entry.vendor_model
	MOV RCX, (pci_map_entry_size - pci_map_entry.vendor_model)					;size of 'class description
	REP MOVSB	

	;get the BAR0 address 
	XOR RAX, RAX
	MOV EAX, [R8 + pci_map_entry.location]    ;contains the enable bit and B:D:F already-shifted
	OR EAX, PCI_REGISTER_BAR0 << 2
	CALL pci_read_register
	MOV [nic_8254_base_address], RAX
	
	DEBUG_WRITE_VAR 'BAR0 address is ', [nic_8254_base_address]

	XOR RAX, RAX
	MOV EAX, [R8 + pci_map_entry.location]
	OR EAX, PCI_REGISTER_IRQ << 2
	CALL pci_read_register
	MOV [nic_8254_irq], AL

	DEBUG_WRITE_VAR 'IRQ  is ', [nic_8254_irq]

	 ; ;Enable PCI Bus Mastering
	 ; MOV EAX, [R8 + pci_map_entry.location]
	 ; OR EAX, 0x01 << 2				; Get Status/Command. TODO: replace with constant	 
	 ; CALL pci_read_register
	 ; BTS EAX, 2
	 ; MOV EBX, EAX
	 ; MOV EAX, [R8 + pci_map_entry.location]
	 ; CALL pci_write_register

	;Get the MAC address
	MOV RSI, [nic_8254_base_address]
	; Low 4 bytes...
	MOV EAX, [RSI + 0x5400]	
	MOV [nic_8254_mac_address], EAX
 	MOV [nic_8254_mac_address], AL
	SHR EAX, 8
	MOV [nic_8254_mac_address + 1], AL
	SHR EAX, 8
	MOV [nic_8254_mac_address + 2], AL
	SHR EAX, 8
	MOV [nic_8254_mac_address + 3], AL
	;and high 2 bytes...
	MOV EAX, [RSI + 0x5404]			
	MOV [nic_8254_mac_address + 4], AL
	SHR EAX, 8
	MOV [nic_8254_mac_address + 5], AL

	DEBUG_WRITE_VAR 'MAC Address from MMIO is ', [nic_8254_mac_address]
	
	;try again from EEPROM
	MOV RSI, [nic_8254_base_address]
	MOV EAX, 0x00000001
	MOV [RSI+0x14], eax
	MOV EAX, [rsi+0x14]
	SHR EAX, 16
	MOV [nic_8254_mac_address], AL
	SHR EAX, 8
	MOV [nic_8254_mac_address + 1], AL
	MOV EAX, 0x00000101
	MOV [RSI+0x14], EAX
	MOV EAX, [RSI + 0x14]
	SHR EAX, 16 
	MOV [nic_8254_mac_address + 2], AL
	SHR EAX, 8
	MOV [nic_8254_mac_address + 3], AL
	MOV EAX, 0x0000020
	
	MOV [RSI + 0x14], EAX
	MOV EAX, [RSI +0x14]
	SHR EAX, 16 
	MOV [nic_8254_mac_address + 4], AL
	SHR EAX, 8
	MOV [nic_8254_mac_address + 5], AL
	
	DEBUG_WRITE_VAR 'MAC Address from EEPROM is ', [nic_8254_mac_address]	
			
	MOV ESI, [R8 + pci_map_entry.location] ;**DEBUG_BREAK**
	SHOW_PCI_REGISTERS
	WAIT_FOREVER
	
        MOV RDX, R8		;restore RDX

	RET
nic_8254_init_done:
For this NIC family on VMWARE, I get the same results.
I might try another NIC, eg RTL8139(?) and see if I get similar results.

Thanks again!

David
Code or code not. There is no try.
quirck
Member
Member
Posts: 42
Joined: Sun Nov 23, 2008 5:56 am
Location: Russia, Saint-Petersburg

Re: MMIO Registers all empty

Post by quirck »

I don't immediately see any problem in your code, something along these lines works for me in both qemu and bochs.
I can only think of something overwriting [nic_8254_base_address], is it declared as qword?

And you have a typo when reading last MAC bytes from EEPROM: the trailing 1 has disappeared

Code: Select all

   MOV [nic_8254_mac_address + 3], AL
   MOV EAX, 0x00000201
0b1
Member
Member
Posts: 35
Joined: Sun Feb 04, 2018 8:04 pm

Re: MMIO Registers all empty

Post by 0b1 »

Thanks for Catching the typo.

It's helpful just to know this can work on QEMU, so thanks for that as well.

I just have to figure out what I need to do differently. Perhaps my Page Tables are somehow causing a conflict.

Btw, would you share your .bxrc BOCHS config, or at least the network card config? When i add a NIC and start BOHCS it locks up the host PC. Having a comparison might help.

Thanks again.

David
Code or code not. There is no try.
quirck
Member
Member
Posts: 42
Joined: Sun Nov 23, 2008 5:56 am
Location: Russia, Saint-Petersburg

Re: MMIO Registers all empty

Post by quirck »

For this test I used the following lines in bochs config:

Code: Select all

pci: enabled=1, chipset=i440fx, slot1=pcivga, slot2=e1000
e1000: enabled=1, mac=b0:c4:20:00:00:01, ethmod=slirp, script=slirp.conf
I use precompiled win32 version of bochs-2.6.9. But I haven't yet succeeded in making bochs connect to the internet.. :)

I don't think paging can cause this issue unless there is a bug in its setup so that the linear addresses are translated not as you expect. It might interfere by specifying cache type, it's better to mark memory-mapped IO as uncacheable (though it should already have been done with MTRRs, I think). Maybe qemu cached the accesses, so that when reading EEPROM, you got those 0x00000x01 back, hence zeroes. But it shouldn't prevent reading correct mac from MMIO at [rsi+0x5400], so there's something else. Also, formally after writing to [rsi+0x14] you should wait until bit 4 becomes set, and only then trust the value read back, but emulators are quick to reply.

Could you provide a link to full source (or minimal working code that experiences the issue) so that it can be compiled and tested? I'm going on vacation soon and won't have the necessary environment for this, though, so let's hope that more people will join our conversation :)
0b1
Member
Member
Posts: 35
Joined: Sun Feb 04, 2018 8:04 pm

Re: MMIO Registers all empty

Post by 0b1 »

Hi Quirck,

Your bochs configuration worked for me. Now I have three environments working once again. I am very grateful!
I will update my other post with the resolution.

My tests with the page tables concur with your opinion ... page tables and the cache bit made no difference.

I will do some experimentation based on your suggested in these posts and see if I can narrow things down.
Having a working bochs again is a big help.

I have been reading illustrated TCP/IP volume II. It is very good and leads me to believe there is a lot of room for simplification in the stack and buffer management. I hope to be able to put together a rudimentary stack based on those examples.
If I get to the internet first, I will share :) Then again, I may still be figuring out how to get a MAC address

Thanks again!

David
Code or code not. There is no try.
0b1
Member
Member
Posts: 35
Joined: Sun Feb 04, 2018 8:04 pm

Re: MMIO Registers all empty [resolved]

Post by 0b1 »

Quirck, your suggestion of
I don't think paging can cause this issue unless there is a bug in its setup so that the linear addresses are translated not as you expect.
was exactly right. I set these up when I was still relatively new and they appeared to work. In fact, they were not right. Correcting these corrected the problem, at least on QEMU. I am still seeing partial or missing MAC addresses in BOCHs, VMWare, and VirtualBox, but at least now I have a successful implementation against which to compare.

Thank you so much!

David
Code or code not. There is no try.
Post Reply