Développement de Diosix
Prioriser Sécurité > Sûreté > Exactitude > Maintenabilité. Écrire du code Zig 0.17.0 et de l'assembleur RISC-V idiomatique, auto-documenté, sûr en mémoire et strictement limité pour que chaque modification passe reviewing-diosix du premier coup sans retouche pré-commit.
Directives Clés
- Code Fonctionnel, Complet et Compilable (Prérequis): Chaque modification doit compiler proprement à la fois pour la construction de la VM Racine/hyperviseur et la suite de tests unitaires hôte (
./scripts/build.shet./scripts/build.sh test). Ne jamais laisser de code cassé, deTODOfactices, de chemins de production simulés ou de fonctionnalités partiellement implémentées. - Limites de Lignes et de Fichiers (Décomposer en Sous-Dossiers, Jamais Tronquer): Toute ligne de code et commentaire doit être <= 80 colonnes. Les fichiers sources doivent faire <= 500 lignes. Lorsqu'un fichier dépasse 500 lignes, ne jamais tronquer sa fonctionnalité ou ses tests ; le décomposer dans un sous-dossier dédié (
panes/vm.zig,vm/run.zig,tests/gui.zig) plutôt que de multiplier les fichiers plats avec préfixe (panes_vm.zig,vm_run.zig,tests_gui.zig), et connecter chaque sous-module dans le bloctestdu parent (_ = @import("vm/run.zig");). - Sous-Dossiers Plutôt que Noms avec Préfixe et Zéro Copier-Coller: Utiliser des noms de fichiers concis en
snake_casesans préfixe redondant de projet, répertoire ou frère (utiliserapi.zig,main.c,vm/info.zig, ettests/nav.zig, jamaisdiosix_api.zig,diosix-alsa-init.c,vm_info.zig, outests_nav.zig). Ne jamais dupliquer des primitives partagées (commeSpinlock, l'arithmétique d'alignement de pages, les validateurs de parcours de chemins, ou les constantes ABI) entre modules ; les importer depuishypervisor/interface/,hypervisor/core/atomic.zig, oucommon.zig. - Dispatch Idiomatique: Ne jamais écrire de chaînes
if (std.mem.eql(...)) else if (...)pour des commandes, drapeaux ou clés de configuration. Définir uneenum, analyser avecstd.meta.stringToEnum(EnumType, slice), et dispatcher avecswitch. - Types ABI Explicites à Largeur Fixe, Hexadécimal en Minuscules et Masques de Bits Nommés: Utiliser des types à largeur fixe explicites (
u64,u32,u16,u8) dans toutes les structures ABI/matérielles (extern struct,packed struct) et les registres d'état invité 64 bits — jamaisusizeouunsigned longdu C. Toujours annoter les variables locales initialisées à partir de@min/@maxavec un littéral de temps de compilation (const w: usize = @min(n, 1280);) pour que Zig n'infère pas un type entier étroit (u11) qui déborde plus tard. Écrire tous les littéraux hexadécimaux en minuscules (0xfff,0xffff_ffff, jamais0xFFF), et remplacer les masques/offsets magiques ((vaddr & 0xfff) > 0xffc) par des constantes nommées et des fonctions auto-documentées (PAGE_OFFSET_MASK,crossesPageBoundary(vaddr, @sizeOf(u32))). - Allocation Dynamique Plutôt que Supposition Statique: Seul le code d'amorçage M-mode précoce exécuté avant l'initialisation du tas peut utiliser des tampons statiques fixes. Une fois qu'un allocateur est disponible, allouer et agrandir les tampons dynamiquement plutôt que de deviner des tailles de tampon de pile fixes (par exemple, éviter
var buf: [4096]u8). - Propriété de la Mémoire et Nettoyage: Associer chaque allocation (
alloc,create,dupe,print,mmap) immédiatement àdeferouerrdefer. Mettre à zéro les pages invité libérées et les secrets cryptographiques (std.crypto.secureZero). - Isolation d'Hyperviseur d'Entreprise: Ne jamais paniquer en M-mode à cause d'une entrée ou d'un état invité ; retourner une erreur SBI ou terminer l'arborescence d'invités fautive. Copier la mémoire partagée invitée une fois (
@memcpy) dans la mémoire appartenant à l'hyperviseur avant validation pour éviter les vulnérabilités de double récupération (TOCTOU). - Mécanisme dans le Code, Politique dans la Configuration de Construction/Exécution: Ne jamais coder en dur des paramètres stratégiques ou des valeurs par défaut ajustables dans le code Zig. Déplacer les paramètres ajustables et les configurations vers la configuration au moment de la construction (
build.zigoptions /boot/hypervisor.conf) ou des fichiers de configuration au moment de l'exécution (/etc/diosix/*.toml, en gardantkey = "value"sur une seule ligne <= 80 colonnes). - Construire les Binaires et Images au Moment de la Construction, Pas à la Volée en Zig: Éviter d'assembler des binaires ELF, des cales de code machine ou des images média mot par mot à l'exécution en Zig. Garder les cales dans des fichiers assembleur ou Zig compilés pendant la construction, utiliser des scripts dédiés pour construire les images média, et ne jamais placer les sorties de construction générées dans
tools/overlay-common/(utiliser.zig-cache/overlay-dynamic/). - Tests Unitaires Colocalisés et Tests d'Intégration Séparés: Placer les blocs de test unitaires
testdans le fichier source qu'ils testent (en appelantstd.testing.refAllDecls(@This())). Placer les tests d'intégration multi-composants dans des répertoirestests/dédiés. - Compatibilité Ascendante Sans Accumulation de Solutions de Rechange Obsolètes: Préserver la compatibilité pour les contrats externes (ABI d'hyperappel SBI, ioctls
/dev/diosix, commandes CLIdsx/schémas JSON documentés, et fichiers/etc/diosix/*.tomlrédigés par les utilisateurs), mais ne jamais accumuler de tableaux de repli multi-chemins (DEFAULT_GUEST_CANDIDATES) pour la tuyauterie interne co-versionnée. Lorsque le producteur et le consommateur sont livrés ensemble dans ce dépôt, mettre à jour atomiquement tous les producteurs, consommateurs et tests dans l'arbre pour utiliser un seul chemin ou symbole canonique, et gérer les mises à niveau de disposition de disque persistantes une fois à la frontière d'amorçage/installation plutôt que de sonder des chemins historiques indéfiniment. - En Cas de Doute, Arrêter et Demander au Responsable Principal: Ne jamais deviner sur les décisions architecturales, les exigences ambiguës ou les capacités de sous-systèmes manquantes. S'arrêter et demander au responsable principal avant de continuer.
Environnements d'Exécution M-Mode vs U-Mode
| Aspect | Hyperviseur M-Mode (hypervisor/) | Outillage U-Mode (tools/) |
|---|---|---|
| Cible | riscv64-freestanding-none | riscv64-linux-musl (ou hôte dans les tests) |
| Amorçage Pré-Tas | Blocs statiques par cœur (0..31) dans entry.s | N/A (environnement de processus OS prêt à main) |
| Allocateur | pcore.this().allocator.allocator() par cœur | std.heap.SafeAllocator / page_allocator / ArenaAllocator |
| Politique de Crash | Ne jamais paniquer sur une entrée invitée ; isoler et terminer la VM invitée fautive | Retourner une erreur descriptive et un code de sortie propre |
| Accès Matériel | CSR/MMIO direct (doit être protégé par if (is_test) pour les tests unitaires hôtes) | ioctls /dev/diosix (api.zig), DRM/evdev, appels système Linux |
Guides de Référence Ciblés
Lire le fichier de référence approprié avant d'écrire ou de modifier du code :
- Idiomes et Builtins Zig 0.17.0 : Syntaxe Zig 0.17 à jour (
@backingInt,@splat,allocator.print,SafeAllocator,stringToEnum,@ptrCastpourextern struct, types ABI à largeur fixe, annotations de type@min, formatage 80 colonnes avec virgules finales, et pureté du cache de construction). - Gestion de la Mémoire et Tampons Dynamiques : Modèles d'allocateur M-mode vs U-mode, croissance des tampons dynamiques, discipline
defer/errdefer, mise à zéro des secrets, et initialisation des pointeurs de sortie. - Architecture et TigerStyle : Implémentation complète des fonctionnalités, découpage modulaire des fichiers sans perdre les tests unitaires, aucune duplication par copier-coller, boucles bornées, appariement d'assertions, et hygiène de la superposition/configuration.
- RISC-V et Hyperviseur d'Entreprise : Conventions assembleur RV64, simulation CSR, confinement du rayon d'explosion, motif de prévention de double récupération, ordonnancement des spinlocks sûrs pour les IRQ, et isolation G-stage/PMP.