Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

alloc en mode réel (i386)

4 réponses
Avatar
Cyrille Szymanski
Bonjour,

je cherche à allouer un bloc mémoire et obtenir son
adresse en mode réel pour passer cette adresse à une
interruption vm86 sous FreeBSD (i386_vm86(2)).

J'ai pensé à deux méthodes :
1_ Appeler malloc() normalement, récupérer la LDT et
faire le calcul moi-même. Mais a mon avis l'adressage
virtuel fera que c'est pas possible.
2_ Utiliser mmap() et écrire moi même un malloc pour
allouer/déallouer les blocs.

Y a-t-il une méthode plus simple ?

--
cns

4 réponses

Avatar
jmz
Cyrille Szymanski writes:

Bonjour,

je cherche à allouer un bloc mémoire et obtenir son
adresse en mode réel pour passer cette adresse à une
interruption vm86 sous FreeBSD (i386_vm86(2)).

J'ai pensé à deux méthodes :
1_ Appeler malloc() normalement, récupérer la LDT et
faire le calcul moi-même. Mais a mon avis l'adressage
virtuel fera que c'est pas possible.
2_ Utiliser mmap() et écrire moi même un malloc pour
allouer/déallouer les blocs.

Y a-t-il une méthode plus simple ?


Quelque chose comme ça : ?

buf = vm_page_alloc_contig (size, 0x100000, 0x1000000-1, PAGE_SIZE);
if (!buf) {
device_printf (dev, "can't allocate %dK of physical memoryn", size/1024);
goto failure;
}
buf = vtophys (buf);
device_printf (dev, "%dK of physical memory allocated (address=0x%x)n",
size/1024, buf);

Jean-Marc
--
Jean-Marc Zucconi -- PGP Key: finger [KeyID: 400B38E9]

Avatar
Cyrille Szymanski
On 2004-04-11, Jean-Marc Zucconi wrote:
je cherche à allouer un bloc mémoire et obtenir son
adresse en mode réel pour passer cette adresse à une
interruption vm86 sous FreeBSD (i386_vm86(2)).


Quelque chose comme ça : ?

buf = vm_page_alloc_contig (size, 0x100000, 0x1000000-1, PAGE_SIZE);
if (!buf) {
device_printf (dev, "can't allocate %dK of physical memoryn", size/1024);
goto failure;
}
buf = vtophys (buf);
device_printf (dev, "%dK of physical memory allocated (address=0x%x)n",
size/1024, buf);


C'est pas mal, il me reste juste à convertir cette adresse en segment:offset
et le tour est joué.

Par contre je ne trouve pas les pages man de vm_page_alloc_contig et vtophys
et il me semble que c'est parce qu'elles ont été bannies depuis la création
de bus_dma.

Est-ce aussi simple à faire avec bus_dma ? J'ai survolé l'article
Jason R. Thorpe, "A Machine-Independent DMA Framework for NetBSD"
mais il n'est pas donné de code source, je ne peux pas me rendre compte
de ce que ça donne.

Merci pour la réponse.
--
cns


Avatar
pornin
According to Cyrille Szymanski :
1_ Appeler malloc() normalement, récupérer la LDT et
faire le calcul moi-même. Mais a mon avis l'adressage
virtuel fera que c'est pas possible.


Je dis ça un peu hors-contexte, mais il s'avère que le i386 possède
trois "modes", qui sont le mode réel, le mode protégé et le mode vm86.
Le mode vm86 est une émulation du mode réel, avec le mode protégé
toujours actif en dessous, et notamment la pagination. Ce qui veut dire
que les adresses virtuelles restent inchangée au passage en vm86.

À noter cependant que la pagination (i.e., la correspondance entre les
adresses virtuelles et les adresses réelles) change à chaque commutation
entre deux processus.


--Thomas Pornin

Avatar
Cyrille Szymanski
Je dis ça un peu hors-contexte, mais il s'avère que le i386 possède
trois "modes", qui sont le mode réel, le mode protégé et le mode vm86.
Le mode vm86 est une émulation du mode réel, avec le mode protégé
toujours actif en dessous, et notamment la pagination. Ce qui veut dire
que les adresses virtuelles restent inchangée au passage en vm86.


Pour les pointeurs < 2^20 je peux donc calculer une adresse
16:16 en faisant un segment = (ptr >> 8), offset = ptr & 0xF.

Pour allouer de la mémoire en dessous de la limite des 1M, j'ai essayé
d'utiliser mmap :

fd_zero = open("/dev/zero", O_RDONLY);

m = mmap((void *)0x10000, 0x10000,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, fd_zero, 0);

et ensuite je passe l'adresse 1000:0000 au gestionnaire d'interruption
appelé en vm86 mais cela génère une page fault (alors que l'écriture/
lecture en mode protégé fonctionne).

C'est pas comme-ça qu'il faut faire ?

Merci pour votre aide.
--
cns