Resumidamente, tenho um endereço físico dentro do kernel (9.932.111.872 ou 0x250000000
), que aparentemente está alinhado a 4kB (tamanho da página). Quando uso a __va()
função do kernel para obter o endereço virtual do kernel , recebo algo como 0xf570660f
(diferente em cada inicialização), que não está alinhado a 4kB .
Estou em um sistema de 64 bits, então não há HIGHMEM e pensei que, devido ao modelo de memória liner, um endereço virtual de um endereço físico alinhado a 4kB também deveria ser alinhado a 4kB. Perdi algo? O endereço virtual não deveria ser phys_addr + PAGE_OFFSET
? Ou é a influência do sparsemem? Mas talvez também deva ser alinhado a 4kB?
Aqui estão mais detalhes:
Meu ambiente de trabalho está em uma VM QEMU x86 de 64 bits. Estou tentando usar um PMEM no DEV-DAX
modo como memória normal. Posso obter o endereço inicial físico dele ( 0x250000000
), que foi confirmado como correto. Então preciso transferi-lo para o endereço virtual no espaço do kernel para poder usá-lo conforme necessário. Aqui está um código:
static long nvpc_map_whole_dev(struct dax_device *dax_dev, void **kaddr, pfn_t *pfn)
{
// get the device
struct dev_dax_nvpc *dax_nvpc = (struct dev_dax_nvpc *)dax_get_private(dax_dev);
// get the virtual address and the pfn_t
*kaddr = __va(dax_nvpc->phys_start);
*pfn = phys_to_pfn_t(dax_nvpc->phys_start, PFN_MAP);
pr_info("[NVPC DEBUG]: paddr %#llx kaddr %p pfn %lu\n", dax_nvpc->phys_start, *kaddr, pfn_t_to_pfn(*pfn));
pr_info("[NVPC DEBUG]: kaddr-paddr %#llx\n", __pa(*kaddr));
return PHYS_PFN(dax_nvpc->size);
}
E aqui está o resultado que obtive:
Mostrado na linha marcada, o paddr
dax_nvpc->phys_start
, e o pfn
, estão ambos certos. Mas o kaddr
(endereço virtual) é confuso para mim. Então, quando transfiro de kaddr
volta para o endereço físico (a próxima linha de saída), o resultado fica correto.
Além do mais, posso fazer qualquer operação na memória de kaddr
até kaddr + dax_nvpc->size
, não há falha de página.
Alguém poderia me dizer por que o endereço virtual não está alinhado a 4kB? Estou sendo um idiota em algum lugar? Além disso, posso fazer algo para garantir que o endereço virtual também esteja alinhado a uma página?
Parece que encontrei a resposta. É a razão de
%p
entrarprintk
. Quando mudo%p
para%#llx
para uma verificação rápida, a saída do endereço do kernel fica alinhada em 4 KB conforme o esperado.O motivo pode ser encontrado aqui: Kernel Doc: printk-formats pointer-types .
%p
dentro do printk imprimirá um endereço de ponteiro com hash para evitar vazamento de informações do kernel. É por isso que o ponteiro parece estranho. Se você quiser verificar o endereço virtual real%px
, basta usar ou adicionarno_hash_pointers
ao parâmetro de inicialização. Ou você pode consultar o link para obter mais uso.Espero que isso ajude alguém.