My Project
Chargement...
Recherche...
Aucune correspondance
virtio.c
Aller à la documentation de ce fichier.
1
18#include <manux/virtio.h>
19#include <manux/debug.h>
20#include <manux/memoire.h> // allouerPages
21#include <manux/string.h> // memcpy
22#include <manux/i386.h> // barriereMemoire
23#include <manux/errno.h>
24#include <manux/io.h> // outb
25
26static int nbFournis =0;
27static int nbAcceptes =0;
28static int nbRendus =0;
29
30#define min(a, b) (((a)<(b))?(a):(b))
31#define max(a, b) (((a)>(b))?(a):(b))
32
33#ifdef MANUX_VIRTIO_AUDIT
37void virtioAfficherFile(VirtioFileVirtuelle * fv)
38{
39 printk("[7] File 0x%x (lg %d nxt %d), used_idx= %d, disp_idx=%d free_idx=%d (f=%d/a=%d/r=%d)\n",
40 fv,
41 fv->taille,
42 fv->prochainDescripteur,
43 fv->buffersUtilises->indice,
44 fv->buffersDisponibles->indice,
45 fv->nbDescripteursLibres,
46 nbFournis, nbAcceptes, nbRendus
47 );
48
49 printk("[7] Desc [@/l f n] : [%llx %ld %d %d][%llx %ld %d %d][%llx %ld %d %d]\n",
50 fv->tableDescripteurs[0].adresse,
51 fv->tableDescripteurs[0].longueur,
52 fv->tableDescripteurs[0].flags,
53 fv->tableDescripteurs[0].suivant,
54
55 fv->tableDescripteurs[1].adresse,
56 fv->tableDescripteurs[1].longueur,
57 fv->tableDescripteurs[1].flags,
58 fv->tableDescripteurs[1].suivant,
59
60 fv->tableDescripteurs[2].adresse,
61 fv->tableDescripteurs[2].longueur,
62 fv->tableDescripteurs[2].flags,
63 fv->tableDescripteurs[2].suivant
64 );
65 printk("[7] Used fl 0x%x, idx %d (i/l) : [%d/%ld][%d/%ld][%d/%ld]\n",
66 fv->buffersUtilises->flags,
67 fv->buffersUtilises->indice,
68 fv->buffersUtilises->elementsUtilises[0].indiceBuffer,
69 fv->buffersUtilises->elementsUtilises[0].longueur,
70 fv->buffersUtilises->elementsUtilises[1].indiceBuffer,
71 fv->buffersUtilises->elementsUtilises[1].longueur,
72 fv->buffersUtilises->elementsUtilises[2].indiceBuffer,
73 fv->buffersUtilises->elementsUtilises[2].longueur
74 );
75 printk("[7] Dispo fl 0x%x, idx %d (i) : [%d][%d][%d]\n",
76 fv->buffersDisponibles->flags,
77 fv->buffersDisponibles->indice,
78 fv->buffersDisponibles->indicesDesBuffer[0],
79 fv->buffersDisponibles->indicesDesBuffer[1],
80 fv->buffersDisponibles->indicesDesBuffer[2]
81 );
82}
83#endif // MANUX_VIRTIO_AUDIT
84
98static
99int virtioCreerFileVirtuelle(VirtioFileVirtuelle * fileVirtuelle,
100 uint16_t tailleFile)
101{
102 uint32_t taillePartie1; // Buffers + disponibles
103 uint32_t taillePartie2; // Utilisés
104 uint32_t nbTotalPages; // Combien de pages pour stocker ça ?
105 char * pointeur; // Pour les allocations
106
107 // La taille est fournie
108 fileVirtuelle->taille = tailleFile;
109
110 // Pour le moment, ils sont tous libres
111 fileVirtuelle->nbDescripteursLibres = tailleFile;
112
113 // La première partie est composée des descripteurs de buffer
114 taillePartie1 = tailleFile * sizeof(VirtioDescripteurBuffer);
115
116 // Suivis des descripteurs de buffers disponibles
117 taillePartie1 += 3 * sizeof(uint16_t) + tailleFile * sizeof(uint16_t);
118
119 // La seconde partie est composée des buffers utilisés
120 taillePartie2 = 3 * sizeof(uint16_t) + tailleFile * sizeof(VirtioElementUtilise);
121
122 // Combien faut-il de pages avec les contraintes d'alignement ?
123 nbTotalPages = NB_PAGES(taillePartie1) + NB_PAGES(taillePartie2);
124
125 // Allocation des pages nécessaires
126 pointeur = allouerPages(nbTotalPages);
127
128 // En cas d'échec, on remonte l'erreur
129 if (pointeur == NULL) {
130 return ENOMEM;
131 }
132
133 // La spécification insiste sur une initialisation à 0
134 memset(pointeur, 0, nbTotalPages * MANUX_TAILLE_PAGE);
135
136 // On peut enfin initialiser les pointeurs
137 fileVirtuelle->tableDescripteurs = (VirtioDescripteurBuffer *)pointeur;
138
139 // Les buffers disponibles sont collés derrière le dernier buffer
140 fileVirtuelle->buffersDisponibles =
141 (VirtioBufferDisponible *)&(fileVirtuelle->tableDescripteurs[tailleFile]);
142
143 // Les buffers utilisés sont au début de la page suivante
144 fileVirtuelle->buffersUtilises =
145 (VirtioBufferUtilise*) (pointeur + NB_PAGES(taillePartie1) * MANUX_TAILLE_PAGE);
146
147 fileVirtuelle->prochainDescripteur = 0;
148
149 // Pour savoir où on en est des récupérations de buffer
150 fileVirtuelle->dernierIndiceUtilise = 0;
151
152 printk_debug(DBG_KERNEL_VIRTIO, "%d elts, %d+%d octets, %d pages, desc=0x%x, dis=0x%x, uti=0x%x,\n",
153 tailleFile,
154 taillePartie1,
155 taillePartie2,
156 nbTotalPages,
157 fileVirtuelle->tableDescripteurs,
158 fileVirtuelle->buffersDisponibles,
159 fileVirtuelle->buffersUtilises);
160
161 return ESUCCES;
162}
163
174 int PCINum,
175 uint32_t masque)
176{
177 uint16_t adresseES; // L'adresse d'E/S pour dialoguer avec lui
178 uint16_t tailleFile; // Pour lire les tailles de files virtio
179 uint8_t etat; // Etat du périphérique
180 int numFile; // Pour boucler sur les files
181
183
184 // On va chercher un pointeur vers la description PCI
185 vp->pciEquipement = PCIEquipementNumero(PCINum);
186
187 // Un raccourci sur l'adresse pour alléger le code
188 adresseES = vp->pciEquipement->adresseES;
189
190 // On reset le périphérique (1)
192
193 // On lui dit qu'on l'a vu (2)
195
196 // On lui dit qu'on va le gérer (3)
198
199 // Lecture de ses caractéristiques (4)
200 inl((uint16_t)(adresseES + VIRTIO_HIST_CAPA_EQUIP), vp->caracteristiques);
201
202 // Un petit message de debug
203 printk_debug(DBG_KERNEL_VIRTIO, "Caract : 0x%x\n",
204 vp->caracteristiques);
205
206 // C'est donc la phase de "négociation", on va supprimer ce qu'on
207 // ne sait pas gérer
210 ;
211 printk_debug(DBG_KERNEL_VIRTIO, "Masque : 0x%x\n",
212 masque);
213
214 // On désélectionne les caractéristiques qui ne nous intéressent pas
215 vp->caracteristiques &= ~masque ;
216
217 printk_debug(DBG_KERNEL_VIRTIO, "Caract : 0x%x\n",
218 vp->caracteristiques);
219
220 // Négociation de ces caractéristiques (5)
221 outl((uint16_t)(adresseES + VIRTIO_HIST_CAPA_PILOTE), vp->caracteristiques);
222
223 // On acte définitivement ces caractéristiques
224 outb((uint16_t)(adresseES + VIRTIO_HIST_ETAT),
226
227 // On vérifie qu'il est OK (6)
228 inb((uint16_t)(adresseES + VIRTIO_HIST_ETAT), etat);
229
230 if ((etat & VIRTIO_FEATURES_OK) == 0) {
231 printk(PRINTK_ERREUR, "Le device virtio net refuse les caract. !\n");
232 return EINVAL;
233 }
234 printk_debug(DBG_KERNEL_VIRTIO, "Les files\n");
235
236 // Construction des files (7) comme décrit dans [3] section 2.3
237 for (numFile = 0 ; numFile < MANUX_VIRTIO_NB_MAX_FILES; numFile++) {
238 printk_debug(DBG_KERNEL_VIRTIO, "Creation file %d : \n", numFile);
239
240 // Lecture de la taille (1)(2)
241 outw((uint16_t)(adresseES + VIRTIO_HIST_FILE_SEL), numFile);
242 inw((uint16_t)(adresseES + VIRTIO_HIST_TAILLE_FILE), tailleFile);
243 printk_debug(DBG_KERNEL_VIRTIO, " . Taille : %d\n", tailleFile);
244
245 if (tailleFile) {
246 // Création des fameuses files (3)
247 virtioCreerFileVirtuelle(&(vp->filesVirtuelles[numFile]),
248 tailleFile);
249 printk_debug(DBG_KERNEL_VIRTIO, " . Creation ok\n");
250
251 // On donne l'adresse à l'équipement (3)
252 outw((uint16_t)(adresseES + VIRTIO_HIST_FILE_SEL), numFile);
254 ((uint32_t)vp->filesVirtuelles[numFile].tableDescripteurs)/MANUX_TAILLE_PAGE);
255 printk_debug(DBG_KERNEL_VIRTIO, " . @ %d\n",
256 ((uint32_t)vp->filesVirtuelles[numFile].tableDescripteurs)/MANUX_TAILLE_PAGE);
257 }
258 }
260
261 // On dit au périphérique qu'on est bon, ...
262 outb((uint16_t)(adresseES + VIRTIO_HIST_ETAT),
267
269
270 return ESUCCES;
271}
272
284 uint16_t id,
285 void * bu, int lg,
286 uint16_t fl)
287{
288 return virtioFournirBuffers(vp, id, &bu, &lg, 1, fl);
289}
290
305 uint16_t id,
306 void * bu[], int lg[], int nb,
307 uint16_t fl)
308{
309 int n;
310 VirtioFileVirtuelle * fv = &(vp->filesVirtuelles[id]);
312 int prochainDesc = fv->prochainDescripteur;
313 uint32_t ad;
314
315 nbFournis+=nb;
316
317 for (n = 0 ; (n < nb) && (fv->nbDescripteursLibres); n++) {
318 // On va chercher un descripteur de buffer (2.4.1.1 (a))
319 // on sait qu'il en reste puisqu'on les compte
320 vb = &(fv->tableDescripteurs[(prochainDesc + n)%fv->taille]);
321
322 // printk("[7](0x%x) ", vb);
323
324 // L'adresse des données (2.4.1.1 (b))
325 ad = (uint32_t)bu[n];
326 vb->adresse = (uint64_t)ad;
327
328 // La longueur des données (2.4.1.1 (c))
329 vb->longueur = lg[n];
330
331 // On l'initialise en lecture/écriture (2.4.1.1 (d))
332 vb->flags = fl;
333
334 // On chaîne (2.4.1.1 (e))
335 if ((n < nb -1) && (fv->nbDescripteursLibres > 1)) {
336 vb->flags |= VRING_DESC_F_NEXT;
337 vb->suivant = (fv->prochainDescripteur + n + 1)%fv->taille;
338 } else {
339 vb->suivant = 0;
340 }
341
342 // On le met dans les disponibles (2.4.1.2)
343 if (n == 0) { // WARNING pour moi il y a doute ici !
344 fv->buffersDisponibles->indicesDesBuffer
345 [(fv->buffersDisponibles->indice+n)%fv->taille] =
346 prochainDesc;
347 }
348
349 // Un de moins qui soit disponible
350 fv->nbDescripteursLibres--;
351 }
352
353 if (n == 0) {
354 //printk("[7]x");
355 return n;
356 }
357
358 barriereMemoire(); // WARNING, c'est là ?
359
360 // On incremente le nombre de dispo (2.4.1.3)
361 fv->buffersDisponibles->indice = fv->buffersDisponibles->indice + 1;
362
363 // On a utilisé n buffers
364 fv->prochainDescripteur = (fv->prochainDescripteur + n) % fv->taille;
365
367
368 // On prévient l'équipement
369 outw((uint16_t)(vp->pciEquipement->adresseES + VIRTIO_HIST_FILE_NOTIF), id);
370 nbAcceptes += n;
371
372 return n;
373}
374
388 void * bu[], int lg[], int nb)
389{
390 uint16_t indiceBuffer;
391 uint32_t longueur; // du buffer en cours de traitement
392 int result = 0;
393 int finDeChaine;
394 uint32_t ad;
395
396 // Ai-je vraiment des choses à récupérer ?
397 if (fv->dernierIndiceUtilise == fv->buffersUtilises->indice) {
398 return result;
399 }
400
401 barriereMemoire(); // WARNING, c'est là ?
402
403 while ((fv->dernierIndiceUtilise != fv->buffersUtilises->indice) && (result < nb)) {
404 // Récupération de l'indice du descripteur libéré
405 indiceBuffer = fv->buffersUtilises->elementsUtilises
406 [fv->dernierIndiceUtilise % fv->taille].indiceBuffer;
407 longueur = fv->buffersUtilises->elementsUtilises
408 [fv->dernierIndiceUtilise % fv->taille].longueur;
409 do {
410 // On récupère les données et leur longueur
411 ad = (uint32_t)fv->tableDescripteurs[indiceBuffer].adresse;
412 //printk("{%d @ %d}\n", longueur, ad);
413 bu[result] = (void *) ad;
414 lg[result] = min(longueur, fv->tableDescripteurs[indiceBuffer].longueur);
415 longueur -= lg[result];
416
417 result++; // Ca en fait un de plus !
418
419 // Cela peut être le premier d'une chaîne
420 finDeChaine = !(fv->tableDescripteurs[indiceBuffer].flags & VRING_DESC_F_NEXT);
421 indiceBuffer = fv->tableDescripteurs[indiceBuffer].suivant;
422
423 // On continue tant qu'il y en a et qu'on a de la place pour
424 // les fournir
425 } while ((result < nb)
426 && (!finDeChaine));
427 /* if (!finDeChaine) {
428 printk("[7] Ca pue du cul !\n");
429 } else {
430 printk("[7] Fin de chaine !\n");
431 }*/
432 // On vient de traiter un buffer (peut-être une chaîne)
433 fv->dernierIndiceUtilise++;
434 }
435 // On a donc récupéré result descripteurs
436 fv->nbDescripteursLibres += result;
437 nbRendus += result;
438
439 // virtioAfficherFile(fv);
440 //printk("[7] f %d, a %d, r %d\n", nbFournis, nbAcceptes, nbRendus);
441 return result;
442}
443
445{
446 // fv->buffersUtilises->flags = 1;
447 fv->buffersDisponibles->flags = 1;
448}
449
451{
452 fv->buffersUtilises->flags = 0;
453 fv->buffersDisponibles->flags = 0;
454}
#define MANUX_TAILLE_PAGE
#define EINVAL
Definition errno.h:14
#define ENOMEM
Definition errno.h:13
#define ESUCCES
Definition errno.h:10
#define barriereMemoire()
Definition i386.h:26
void * allouerPages(uint32_t nombre)
Definition memoire.c:284
#define NB_PAGES(n)
Definition memoire.h:22
void printk(char *format,...)
Fonction principale d'affichage dans le noyau.
Definition printk.c:166
#define PRINTK_ERREUR
Definition printk.h:29
#define NULL
Definition stddef.h:10
void * memset(void *dest, int val, size_t n)
Definition string.c:25
unsigned long uint32_t
Definition types.h:20
unsigned short uint16_t
Definition types.h:16
unsigned long long uint64_t
Definition types.h:28
unsigned char uint8_t
Definition types.h:12
#define outb(port, octet)
Emission d'un octet sur un port.
Definition io.h:13
#define outw(port, mot)
Emission d'un mot sur un port.
Definition io.h:25
#define inw(port, adresseMot)
Lecture d'un mot depuis un port.
Definition io.h:31
#define inb(port, adresseOctet)
Lecture d'un octet depuis un port.
Definition io.h:19
#define inl(port, adresseLong)
Lecture d'un long depuis un port.
Definition io.h:43
#define outl(port, lng)
Emission d'un long sur un port.
Definition io.h:37
#define DBG_KERNEL_VIRTIO
Definition debug.h:31
#define printk_debug(lvl, fmt, args...)
Definition debug.h:86
PCIEquipement * PCIEquipementNumero(int n)
Definition pci.c:226
#define VIRTIO_HIST_CAPA_PILOTE
Definition virtio.h:63
#define VIRTIO_ACKNOWLEDGE
Definition virtio.h:46
#define VIRTIO_RESET
Definition virtio.h:45
#define VIRTIO_HIST_FILE_NOTIF
Definition virtio.h:68
VirtioDescripteurBuffer
Definition virtio.h:88
#define VIRTIO_HIST_CAPA_EQUIP
Definition virtio.h:62
VirtioElementUtilise
Definition virtio.h:106
VirtioFileVirtuelle
Definition virtio.h:133
#define VIRTIO_HIST_TAILLE_FILE
Definition virtio.h:66
#define VIRTIO_HIST_FILE_SEL
Definition virtio.h:67
#define VIRTIO_DRIVER
Definition virtio.h:47
#define VIRTIO_HIST_ETAT
Definition virtio.h:69
#define VIRTIO_DRIVER_OK
Definition virtio.h:48
VirtioBufferUtilise
Definition virtio.h:116
#define MANUX_VIRTIO_NB_MAX_FILES
Definition virtio.h:32
#define VIRTIO_F_RING_EVENT_IDX
Definition virtio.h:55
#define VIRTIO_HIST_ADDRESS_FILE
Definition virtio.h:64
VirtioBufferDisponible
Definition virtio.h:98
#define VRING_DESC_F_NEXT
Definition virtio.h:75
#define VIRTIO_FEATURES_OK
Definition virtio.h:49
VirtioPeripherique
Definition virtio.h:142
#define VIRTIO_F_RING_INDIRECT_DESC
Definition virtio.h:54
int virtioFournirBuffer(VirtioPeripherique *vp, uint16_t id, void *bu, int lg, uint16_t fl)
Fourniture d'un buffer au périphérique.
Definition virtio.c:283
void virtioFileAutoriserInterruption(VirtioFileVirtuelle *fv)
Definition virtio.c:450
int virtioInitPeripheriquePCI(VirtioPeripherique *vp, int PCINum, uint32_t masque)
Definition virtio.c:173
void virtioFileInterdireInterruption(VirtioFileVirtuelle *fv)
Definition virtio.c:444
int virtioFournirBuffers(VirtioPeripherique *vp, uint16_t id, void *bu[], int lg[], int nb, uint16_t fl)
Fournir plusieurs buffers au périphérique.
Definition virtio.c:304
int virtioFileRecupererBuffers(VirtioFileVirtuelle *fv, void *bu[], int lg[], int nb)
on va récupérer des buffers
Definition virtio.c:387
#define min(a, b)
Definition virtio.c:30