Como posso reservar um bloco de memória do kernel do Linux?


25

Eu tenho um dispositivo que precisa de um bloco de memória reservado exclusivamente para ele, sem a interferência do sistema operacional. Existe alguma maneira de informar ao BIOS ou ao SO que um bloco de memória está reservado e não deve ser usado?

Estou usando este dispositivo em uma máquina openSUSE.

Respostas:


23

O que você está pedindo é chamado DMA. Você precisa escrever um driver para reservar esta memória.

Sim, eu sei que você disse que não queria que o sistema operacional intervenha, e um driver se torna parte do sistema operacional, mas, na ausência de uma reserva de driver, o kernel acredita que toda a memória pertence a ele. (A menos que você diga ao kernel para ignorar o bloco de memória, de acordo com a resposta de Aaron).

O capítulo 15 (PDF) de " Linux Device Drivers, 3 / e " de Rubini, Corbet e Kroah-Hartmann aborda o DMA e tópicos relacionados.

Se você quiser uma versão em HTML disso, encontrei a versão da segunda edição do capítulo online em outros lugares. Cuidado que a 2ª edição tem mais de uma década, tendo sido lançada quando o kernel 2.4 era novo. Tem havido muito trabalho no subsistema de gerenciamento de memória do kernel desde os dias, portanto ele pode não se aplicar muito bem.


Com o DMA, posso escolher quais endereços físicos usar? O kernel me dará um bloco contíguo de memória? É garantido que esteja sempre disponível?
Nathan Fellman

1
Suas perguntas são respondidas a partir da página 442 do PDF que eu indiquei.
Warren Young

24

Se você deseja que o sistema operacional o ignore totalmente , é necessário fazer um furo na memória usando " memmap." Veja esta referência . Por exemplo, se você quiser 512M na barreira de 2GB, poderá " memmap=512M$2G" colocar na linha de comando do kernel.

Você precisará verificar o seu dmesgpara encontrar um buraco contíguo para roubar, para não pisar em nenhum dispositivo; Isso é específico para sua placa-mãe + placas.

Esta não é a maneira recomendada de fazer as coisas - consulte a resposta de Warren Young para saber como fazê-lo corretamente (drivers do kernel + DMA). Estou respondendo a pergunta exata que você fez. Se você planeja fazer isso para os usuários finais, eles o odiarão se você fizer isso com eles ... confie em mim, essa é a única razão pela qual eu soube essa resposta.


Edit: Se você estiver usando o grub2 w / grubby (por exemplo, CentOS 7), você precisa se livrar do $ . Deve haver um único \antes $. Exemplo:

$ sudo -v
$ sudo grubby --update-kernel=ALL --args=memmap='128M\\$0x57EF0000'
$ sudo grubby --info $(sudo grubby --default-kernel) | grep memmap
args="ro crashkernel=auto ... memmap=128M\$0x57EF0000"

1
Embora sua resposta responda diretamente à minha pergunta, a resposta de Warren parece ser a melhor maneira de fazer isso. :-)
Nathan Fellman

1
@ WarrenYoung Eu não tenho idéia do que você deve fazer com isso. Eu acho que " uint8_t *ptr = 0x8000000" com o meu exemplo? Ou isso pode falhar ... Não sei mesmo. Novamente, eu sabia a resposta porque era um usuário final de uma placa PCI mal projetada, na qual tive que alocar manualmente um buffer abaixo da marca 4G e depois informar ao driver onde estava esse espaço; pode não ser possível na terra do usuário.
Aaron D. Marasco

2
Apenas por sorrisos, olhei um pouco mais fundo nisso e parece que você precisa MMAP_FIXED | MMAP_ANON. Sem um dispositivo DMA personalizado para brincar, não posso dizer se ele realmente faz o que o OP queria, mas minha caixa do CentOS felizmente me deu um bloco de 8 MB a 512 MB quando falei memmap=8M$512Mno GRUB. Nem sequer requer acesso root, como eu temia. Mas mesmo que isso faça a coisa certa, ainda acho que você provavelmente precisará de um driver para lidar com interrupções e coisas do tipo.
Warren Young

3
@ AaronD.Marasco: Não, mmap()as páginas são zeradas antes que o código da terra do usuário as veja. Isso é feito por segurança, para que os dados não vazem de um processo para o outro. Outro motivo para usar um driver, pois pode ser necessário preservar o conteúdo do buffer DMA no momento do carregamento do driver. Ah, a propósito, a mmap()chamada localizada arbitrariamente é bem- sucedida mesmo sem a memmapopção de inicialização do kernel, pelo menos enquanto ninguém estiver usando a memória localizada onde você pediu. A opção de inicialização sem dúvida aumenta as chances de sucesso, mas não é estritamente necessária.
Warren Young

1
@ AaronD.Marasco hmm, tudo bem. interessante. obrigado por esse link, é uma boa leitura.
Woodrow Barlow

5

Para reservar um bloco de memória do kernel no Linux baseado em ARM, você também pode usar um reserved-memorynó no arquivo da árvore de dispositivos (dts). Na documentação do kernel (veja aqui ), há um exemplo:

memory {
    reg = <0x40000000 0x40000000>;
};

reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    /* global autoconfigured region for contiguous allocations */
    linux,cma {
        compatible = "shared-dma-pool";
        reusable;
        size = <0x4000000>;
        alignment = <0x2000>;
        linux,cma-default;
    };

    display_reserved: framebuffer@78000000 {
        reg = <0x78000000 0x800000>;
    };

    multimedia_reserved: multimedia@77000000 {
        compatible = "acme,multimedia-memory";
        reg = <0x77000000 0x4000000>;
    };
};

0

Primeiro, digite este comando para verificar sua configuração atual:

sysctl vm.min_free_kbytes

Para alterar o valor definido, edite /etc/sysctl.conf. Procure a linha:

vm.min_free_kbytes=12888

Se não existir, crie-o (junto com o valor desejado). Os seguintes valores são aceitáveis:

8192
12288
16384
20480

8M é extremamente conservador; pode sentar-se confortavelmente em 16M. Depois de alterar o valor, execute isso e nenhuma reinicialização é necessária:

sudo sysctl -p

2
Por favor, não anule suas postagens; exclua-o ou sinalize-o para que um moderador o remova.
precisa saber é o seguinte
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.