vmalloc_to_pfn возвращает 32-битный адрес в системе Linux 32. Почему он отсекает старшие биты физического адреса PAE?

Я использую vmalloc_to_pfn() для получения физического адреса в 32-битной системе PAE Linux. Похоже, vmalloc_to_pfn() возвращает "unsigned long", что означает, что он 32-битный в 32-битной системе, 64-битный в 64-битной системе. В 64-битном Linux unsigned long - 64-битный, и у меня нет проблем.

Проблема: Использование этой функции для преобразования виртуального в физическое:

VA: 0xf8ab87fc PA с использованием vmalloc_to_pfn: 0x36f7f7fc. Но я на самом деле ожидаю: 0x136f7f7fc.

Физический адрес находится в диапазоне от 4 до 5 ГБ. Но я не могу получить точный физический адрес, я получаю только отрубленный 32-битный адрес. Есть ли другой способ получить настоящий физический адрес?

1 ответ

Я сам изучаю это, и я на 32-разрядной - так что это не совсем ответ. Но копаясь в том же материале, я вижу источник vmalloc_to_pfn говорит:

/*
 * Map a vmalloc()-space virtual address to the physical page frame number.
 */
unsigned long vmalloc_to_pfn(const void *vmalloc_addr)
{
        return page_to_pfn(vmalloc_to_page(vmalloc_addr));
}
EXPORT_SYMBOL(vmalloc_to_pfn);

Таким образом, он не должен фактически возвращать адрес - он должен возвращать "номер кадра страницы" (PFN). По отношению к этому:

http://www.tldp.org/LDP/tlk/mm/memory.html

Используя приведенный выше пример снова, виртуальный фрейм страницы Y процесса 1 отображается на физический фрейм страницы 4, который начинается с 0x8000 (4 x 0x2000). Добавление в смещение байта 0x194 дает нам окончательный физический адрес 0x8194.

Таким образом, очевидно, нужно умножить PFN на PAGE_SIZE чтобы получить реальный адрес - что делает его странным, почему вы получаете "возвращает 32-битный адрес в системе Linux 32", чтобы работать вообще (но опять же, я не эксперт - возможно, PFN эквивалентен адресу для 32 немного?). Вероятно, был бы минимальный рабочий пример модуля в вопросе OP и вывода для обеих платформ для сравнения.

В любом случае, я только что заметил, что у вас есть - что расширение физического адреса (PAE) может иметь значение в поисковом вызове; очевидно, значение, сохраняемое как PFN в Page Global Directory (PGD), зависит от архитектуры и определяется по-разному в зависимости от него:

typedef unsigned long   pgdval_t; // arch/x86/include/asm/pgtable-2level_types.h
typedef u64     pgdval_t;  // arch/x86/include/asm/pgtable-3level_types.h
typedef unsigned long   pgdval_t; // arch/x86/include/asm/pgtable_64_types.h

Подводя итог - просто используя vmalloc_to_pfn() Вероятно, не вся история в получении физического адреса.

Другие вопросы по тегам