includedlibrary
@includedlibrary

Из-за чего GetMemoryMap вылетает с ошибкой?

Пытаюсь получить список сегментов памяти через вызов GetMemoryMap. Первый раз функция отрабатывает корректно и возвращает необходимый объём буфера, затем я успешно выделяю память с помощью AllocatedPages, после снова вызываю GetMemoryMap, и qemu вылетает с ошибкой:
KVM internal error. Suberror: 1
emulation failure
RAX=0000000007f28240 RBX=0000000007f11588 RCX=000000000685f398 RDX=0000000006727100
RSI=0000000007f116e8 RDI=000000000685f318 RBP=0000000007f11578 RSP=0000000007f11518
R8 =0000000007f11588 R9 =0000000000006000 R10=000000000685f188 R11=00000000d848021d
R12=0000000000000000 R13=000000000685fa18 R14=0000000006727100 R15=000000000678c1e8
RIP=00000000000b0000 RFL=00000282 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0038 0000000000000000 ffffffff 00a09b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0030 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT=     00000000079de000 00000047
IDT=     0000000007272018 00000fff
CR0=80010033 CR2=0000000000000000 CR3=0000000007c01000 CR4=00000668
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
EFER=0000000000000d00
Code=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <ff> ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

Я пробовал использовать AllocateMemoryPool вместо AllocatePages, также пробовал статичный буфер размером 8192 байта (необходимый размер буфера не превышает 6000 байт), но qemu всё равно падает с ошибкой. Почему так происходит?

Код:
#define ROUNDUP(x,b) (((unsigned long)x+b-1)&(~(b-1)))
#define PAGEUP(x) ROUNDUP(x, PAGE_SIZE)
#define PAGE_SIZE 4096

#define handle_error(err) do { \
    printf(L"Error: %s\r\n", str_status(err)); \
    exit(2); \
} while(0)

EfiMemoryDescriptor* get_memory_map(size_t *map_key) {
    puts(L"Retrieve size for memory map buffer");
    size_t descriptor_size;
    uint32_t descriptor_version;
    size_t buffer_size = 0;
    size_t err = system_table->boot_services->get_memory_map(
        &buffer_size,
        NULL,
        map_key,
        &descriptor_size,
        &descriptor_version
    );
    if(error_code(err) != EfiBufferTooSmall)
        handle_error(err);

    puts(L"Allocate memory for memory map buffer");
    EfiMemoryDescriptor *buffer = NULL;
    size_t num_pages = PAGEUP(buffer_size) / PAGE_SIZE;
    buffer_size = num_pages * PAGE_SIZE;
    err = system_table->boot_services->allocate_pages(
        AllocateAnyPages,
        EfiLoaderData,
        num_pages,
        (uint64_t*)&buffer
    );
    if(err != 0)
        handle_error(err);

    puts(L"Retrieve memory map");
    err = system_table->boot_services->get_memory_map(
        &buffer_size,
        buffer,
        map_key,
        &descriptor_size,
        &descriptor_version
    );
    if(err != 0)
        handle_error(err);

    return buffer;
}

size_t efi_main(EfiHandle _image_handle, EfiSystemTable *_system_table) {
    image_handle = _image_handle;
    system_table = _system_table;

    size_t map_key;
    get_memory_map(&map_key);
    system_table->boot_services->exit_boot_services(image_handle, map_key);

    return 0;
}


Ссылка на репозиторий.
  • Вопрос задан
  • 68 просмотров
Решения вопроса 1
includedlibrary
@includedlibrary Автор вопроса
Оказалось, что проблема не в коде. Если отключить KVM, то всё работает, как нужно
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы