MMIO не устанавливается на QEMU с xHCI - PullRequest
0 голосов
/ 25 марта 2020

Я сделал подтверждение концепции загрузчика, который записывает значение куда-то в памяти, а затем устанавливает регистр базового адреса устройства xhci так, чтобы он указывал на это местоположение, чтобы ранее записанное значение было перезаписано xhci при чтении через ММИО. Тем не менее, он работает только на VirtualBox, а не в qemu, и я понятия не имею, почему.

Это код (я сделал его настолько простым, насколько это возможно, но все еще кажется каким-то большим):

PCI_CONFIG_ADDRESS equ 0xCF8
PCI_CONFIG_DATA equ 0xCFC

PCI_BAR_0_OFFSET equ 0x10
PCI_BAR_1_OFFSET equ 0x14

%macro write_pci_register 0
    mov dx, PCI_CONFIG_ADDRESS
    out dx, eax
    mov eax, ebx
    mov dx, PCI_CONFIG_DATA
    out dx, eax
%endmacro

; PCI_ADDRESS:
; ; Enable Bit    Reserved    Bus Number  Device Number   Function Number Register Offset
; ; 31            30 - 24     23 - 16     15 - 11         10 - 8          7 - 0
; QEMU: 1_0000000_00000000_00010_000_00000000b --> 0x8000_1000
; VBOX: 1_0000000_00000000_00110_000_00000000b --> 0x8000_3000

PCI_DEV_ADDRESS equ 0x8000_1000

; BAR_0:
; QEMU: 1111111111111111_1100000000000100
; VBOX: 1111111111111111_0000000000000000

org 0x7C00
bits 16

mov ax, 0x0500 >> 4
mov ss, ax
mov esp, 0x7C00 - 0x0500
mov ax, 0
mov ds, ax

; Disable cache
mov eax, cr0
and eax, 1011_1111_1111_1111__1111_1111_1111_1111b
mov cr0, eax
invd

; Write anything to the MMIO address space
mov ax, 0x1000
mov es, ax
mov byte [es:0x00], 0x7D

; Set MMIO
mov eax, PCI_DEV_ADDRESS | PCI_BAR_0_OFFSET
mov ebx, 0x10000
write_pci_register
mov eax, PCI_DEV_ADDRESS | PCI_BAR_1_OFFSET
mov ebx, 0x00
write_pci_register

; Read the value back
mov ax, 0x1000
mov es, ax
mov byte al, [es:0x00]

; Print anything to screen if the value changed
cmp al, 0x7D
je end
mov ax, 0xB800
mov es, ax
mov word [es:0x00], 0x3300 | 'X'

end:
cli
hlt
jmp end

times 510-($-$$) db 0
dw 0xAA55

Этот код должен печатать что-то на экране, если значение эффективно изменилось, что происходит только с virtualbox.

Это команды, которые я использую для проверки с помощью qemu:

nasm -l kernel.lst kernel.asm ; \
qemu-system-x86_64 \
    -device qemu-xhci \
    -drive format=raw,file=kernel

Вот команды, которые я использую для тестирования с VBox:

VBoxManage createvm \
    --name "X" \
    --ostype "Other" \
    --register \
    --basefolder "$(pwd)/vbox" \
    --uuid "e0b08add-d834-4af5-89e8-05abec11aa78" \
    --default ; \
VBoxManage modifyvm "e0b08add-d834-4af5-89e8-05abec11aa78" --usbxhci on ; \
nasm -l kernel.lst kernel.asm ; \
dd if=/dev/zero of=kernel.raw bs=1024 count=2048 ; \
dd if=kernel of=kernel.raw conv=notrunc ; \
VBoxManage convertfromraw kernel.raw kernel.vdi --format VDI ; \
VBoxManage storageattach "X" \
    --storagectl "IDE" \
    --port 0 \
    --device 0 \
    --type hdd \
    --medium  "$(pwd)"/kernel.vdi ; \
VBoxManage startvm "X"

Адрес устройства PCI жестко задан для упрощения кода.

Версия VBox: 6.1.0 r135406
Версия Qemu: 4.1.0

...