제 바람은 개념적으로 간단합니다. 게스트에 원하는 파일이 호스트에 있습니다(실제로는 /sys/bus/pci/device/....의 PCIe 리소스 파일이지만 그다지 관련이 없습니다). 메모리는 어딘가에서 사용할 수 있습니다. 에서 양쪽의 변경 사항이 다른 쪽을 반영하도록 합니다. 내 목표는 실제로 호스트에서 제한된 PCIe 주소 공간 세그먼트를 매핑하는 것이므로 전체 게스트 RAM을 효율적으로 매핑할 수 없습니다. 아래 목록은 제가 추가하려고 시도한 기본 명령입니다. 목표는 매핑된 메모리 ID "bar0.ram"을 얻는 것입니다.어딘가에손님의 기억 속에
qemu-system-ppc -M ppce500 -cpu e500 -m 64M -d guest_errors,unimp -bios $PWD/test.elf -s -object memory-backend-file,size=1m,id=bar0.ram,mem-path=/sys/bus/pci/devices/0000\:04\:00.0/resource0,share=on -monitor telnet:127.0.0.1:4999,server,nowait -nographic
ARM이나 x86에서는 이것이 더 쉬울 수도 있지만 PPC는 영구 메모리, nvram, 다른 파일로 지원되는 여러 메모리 슬롯 또는 유사한 트릭(시작 방법을 알아낼 수 있음)을 제공하지 않습니다. ivshmem을 제공하지만 이를 게스트 주소 공간에 투명하게 매핑하는 방법을 알 수 없습니다.
퍼지 유용한/관련 자료:
답변1
이것이 내가 겪고 있는 문제를 해결하는 잘못된 방법이길 바라지만 효과가 있습니다. 저는 QEMU를 어리석은 방식으로 해킹했습니다.
hw/ppc/e500.c에서 전역 변수를 만들었고 해당 변수가 설정되었을 때 초기 레지스터 메모리 뒤에 전역 변수에 있던 내용을 기반으로 또 다른 하위 영역을 추가했습니다. 네, 제가 메모리 주소를 하드코딩한 걸 보셨죠.
@@ -893,6 +893,8 @@ static void ppce500_power_off(void *opaque, int line, int on)
}
}
+MemoryRegion *magicbar0 = NULL;
+
void ppce500_init(MachineState *machine)
{
MemoryRegion *address_space_mem = get_system_memory();
@@ -985,6 +987,12 @@ void ppce500_init(MachineState *machine)
/* Register Memory */
memory_region_add_subregion(address_space_mem, 0, machine->ram);
+ {
+ if (magicbar0)
+ {
+ memory_region_add_subregion(address_space_mem, 0x8000000, magicbar0);
+ }
+ }
dev = qdev_new("e500-ccsr");
object_property_add_child(OBJECT(machine), "e500-ccsr", OBJECT(dev));
또한, Softmmu/memory.c에서 매직 영역 이름을 찾아 전역 변수에 저장했습니다. 못생겼어요. 그렇죠. 포기하고 전역 변수를 사용하기 전에 너무 오랫동안 QOM에 대해 머리를 숙였습니다.
@@ -1618,6 +1618,9 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
object_unparent(OBJECT(mr));
error_propagate(errp, err);
}
+ extern MemoryRegion *magicbar0;
+ if (!strcmp(name, "bar0.ram"))
+ magicbar0 = mr;
}
void memory_region_init_ram_from_fd(MemoryRegion *mr,
내가 한 일은 아마도 불필요했을 것입니다.
- MMU와 친구들이 원활하게 작동할 수 있도록 매핑하려는 막대를 포함하여 전체 메모리 범위를 포괄하는 호스트 RAM이 있었습니다. 다행히 두 번째 매핑은 세그먼트의 첫 번째 매핑을 덮어쓸 수 있습니다.
- 나는 할당된 RAM의 양을 두 배로 늘렸습니다. 어느 시점에서는 메모리의 절반만 사용하고 있었습니다.
- 게스트에게 데이터 캐싱을 비활성화하도록 했습니다(어쨌든 시도해 보았습니다).
- 이것은 베어 메탈 프로그램이므로 RAM 일부의 기본 매핑 위의 주소 공간에 대한 액세스를 제공하는 전체 RAM TLB 캐시를 만들었습니다.
내가 실행한 명령은 다음과 같습니다.
qemu-system-ppc -M ppce500,memory-backend=foo.ram -cpu e500 -m 256M,slots=2,maxmem=1g -d guest_errors,unimp -bios $PWD/test.elf -s -object memory-backend-file,size=256m,id=foo.ram,mem-path=$PWD/realmemory,share=on,prealloc=on -object memory-backend-file,size=1m,id=bar0.ram,mem-path=/sys/bus/pci/devices/0000\:04\:00.0/resource0,share=on -monitor telnet:127.0.0.1:4999,server,nowait -nographic -S
이 모든 작업을 수행한 후 위 명령을 사용하면 info mtree
원하는 결과가 표시됩니다.
0000000000000000-000000000fffffff (prio 0, ram): foo.ram
0000000008000000-00000000080fffff (prio 0, ram): bar0.ram
더 좋은 점은 주소 0x800_0000에서 메모리를 처리함으로써 친구가 게스트에게 해당 카드(또는 운영 체제)에 대한 PCIe 드라이버가 없어도 호스트 뒤에 있는 PCIe 카드를 성공적으로 읽고 쓸 수 있다는 것입니다.
기록을 위해 (그리고 내 생각으로는) 게스트에서 다음 어셈블러를 사용하여 데이터 캐싱을 비활성화했습니다.
#define CONFIG_SYS_HID0_FINAL (HID0_ICE | HID0_ABE | HID0_EMCP)
lis r3, CONFIG_SYS_HID0_FINAL@h
ori r3, r3, CONFIG_SYS_HID0_FINAL@l
SYNC
mtspr SPRN_HID0, r3
TLB 항목(예, 하드코딩된 RAM 크기)을 추가하기 위해 게스트에서 다음 C를 사용하고 있습니다.
set_tlb(1,
0x0000000,
0x0000000,
MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX,
0,
0,
2,
BOOKE_PAGESZ_256M,
0);
여기까지 온 사람이라면 내가 하게 된 일 대신 QEMU API를 사용하여 작동하는 답변을 누군가 제공할 수 있기를 바랄 것입니다.