IOS LLE: checkpoint NAND conformance and diagnostic tooling
Preserve formatted NAND boot and Wii Remote pairing, add DMA/SRAM conformance tests and a Wii comparison probe. Keep P1 profiling tools and native update A/B evidence; reject the unhelpful targeted SRAM shortcut.
This commit is contained in:
1 parent
b931671fde
commit
c230971f07
64 files changed
+6488
-238
No files matched your search
@@ -0,0 +1,291 @@
|
||||
# Protocole P1 — attribuer les ralentissements Wii LLE
|
||||
|
||||
Date : 19 septembre 2026. Statut au 22 septembre : **capture noyau locale validée ;
|
||||
coût du collecteur, cas PPC et chemin critique Wii non qualifiés**.
|
||||
Aucune nouvelle mise à jour n'est lancée par la rédaction de ce document.
|
||||
Il remplace la stratégie « modifier, refaire une mise à jour, comparer les FPS ».
|
||||
|
||||
## 1. Question et règle de décision
|
||||
|
||||
Sur les passages réellement lents, déterminer **quel travail ou quelle attente retarde
|
||||
la progression de l'émulation**, dans quelles fonctions, et pour combien de temps.
|
||||
Le résultat attendu n'est pas « un cœur à 100 % », mais une attribution vérifiable.
|
||||
|
||||
Une seule exécution de diagnostic est prévue après qualification du dispositif.
|
||||
Aucun nouveau correctif de performance avant un rapport d'attribution exploitable.
|
||||
Une capture incomplète ne justifie pas un correctif au hasard : on répare le dispositif,
|
||||
et on précise quelle information manque avant d'envisager une capture complémentaire.
|
||||
Une seule cause est ensuite traitée ; la validation porte d'abord sur sa charge locale.
|
||||
|
||||
## 2. Pourquoi A–F ne suffisent pas
|
||||
|
||||
- Les instantanés espacés d'environ 10 secondes ne décrivent ni les pics ni leurs piles.
|
||||
- Les FPS échantillonnés ne sont pas une distribution des temps de frame.
|
||||
- Un nombre d'accès mémoire ou d'instructions JIT ne mesure pas leur coût CPU.
|
||||
- `ARMCore::RunCycles` contient également `m_bus.AdvanceCycles` : son temps inclusif
|
||||
ne doit pas être présenté intégralement comme du calcul ARM.
|
||||
- `AdvanceCycles` appelle les périphériques, dont OHCI et le réseau : additionner
|
||||
ces temps imbriqués compterait plusieurs fois le même travail.
|
||||
- `Sampler.cpp` utilise `SuspendThread`/`ResumeThread` ; ses observations historiques
|
||||
ne deviennent pas une référence de temps sans perturbation.
|
||||
- Le lecteur F ne résout pas certaines adresses JIT. Une annotation absente n'est
|
||||
ni zéro travail JIT ni une preuve que tous les autres offsets sont incorrects.
|
||||
- Les 600–2 700 Mo de journal sont des repères approchés, pas une charge identique.
|
||||
- La durée entre messages utilisateur n'est pas la durée exacte de la mise à jour.
|
||||
- Les conditions hôte/serveur diffèrent. F est observé plus lent que E, mais la cause
|
||||
n'est pas isolée. Répéter simplement F avec un autre réglage ne résout pas cela.
|
||||
|
||||
## 3. Geler le scénario, sans toucher aux NAND existantes
|
||||
|
||||
Le diagnostic concerne le ralentissement actuel : source actuelle figée correspondant
|
||||
au comportement F, profilage détaillé des accès désactivé, **sans nouvelle optimisation**.
|
||||
Créer une build de diagnostic propre, non incrémentale, et ne pas remplacer les builds
|
||||
figées D/E/F. Conserver le patch et les empreintes des sources, y compris les fichiers
|
||||
non suivis utilisés, options de compilation, compilateur, EXE, PDB et paramètres.
|
||||
Vérifier l'identité EXE/PDB ; cela ne suffit pas, à elle seule, à valider un lecteur de types.
|
||||
|
||||
Utiliser un nouveau profil depuis la graine pré-mise à jour déjà vérifiée :
|
||||
SHA256 `07b2f4bc543cfd4203efc448538505e9d503b2727c16aaff8d8c0b286d8b4f0c`.
|
||||
Conserver les mêmes réglages Wii, réseau NAT, rendu, vitesse 100 %, horloges invitées,
|
||||
SD et persistance. Noter les différences de chemins et rien d'autre.
|
||||
Un démarrage du processus n'implique pas un cache disque Windows froid ; ne pas vider
|
||||
les caches système, changer l'affinité ou désactiver l'antivirus pour fabriquer un résultat.
|
||||
|
||||
Relever au départ et pendant la capture : charge des autres processus, CPU logique utilisé,
|
||||
état d'alimentation, fréquence disponible, mémoire/pression de pagination, disque et GPU.
|
||||
Ne pas lancer de compilation, benchmark, hachage massif, nettoyage ou autre test en parallèle.
|
||||
Ne pas fermer des applications utilisateur sans accord. Si un concurrent perturbe une fenêtre,
|
||||
la signaler et mesurer sa contribution plutôt que l'effacer du rapport.
|
||||
|
||||
## 4. Deux couches de mesure sur la même horloge
|
||||
|
||||
### A. Profil système Windows, indépendant des layouts C++
|
||||
|
||||
WPR, Xperf et WPA sont présents sur cette machine ; `wpr -profiles` a été vérifié.
|
||||
Employer un profil ETW ciblé, validé avant le test :
|
||||
|
||||
- CPU échantillonné avec piles, cible initiale 1 ms, intervalle réellement utilisé consigné ;
|
||||
- changements de contexte et réveils, pour séparer **Running / Ready / Waiting** par thread ;
|
||||
- chargement des modules, événements disque/fichiers, fautes matérielles de pagination ;
|
||||
- métadonnées d'activité réseau, sans contenu des paquets ;
|
||||
- fréquence/puissance si disponibles. Une donnée absente reste « indisponible ».
|
||||
|
||||
Les vues CPU échantillonné et CPU précis répondent à des questions différentes : localisation
|
||||
du calcul d'une part, ordonnancement/attentes d'autre part. Les combiner, sans confondre une
|
||||
pile d'attente avec une preuve d'attente disque. [Documentation Microsoft](https://learn.microsoft.com/en-us/troubleshoot/windows-server/support-tools/support-tools-xperf-wpa-wpr)
|
||||
|
||||
Ne plus utiliser de suspension de thread ou d'attachement au débogueur pour chronométrer.
|
||||
Pas de profilage heap complet, trace de chaque accès mémoire, ni capture de paquets par défaut.
|
||||
Filtrer l'analyse sur le PID/TID exact et conserver les processus concurrents pour expliquer
|
||||
le temps Ready. Ne pas supposer que le PID suffit après un redémarrage : enregistrer sa date
|
||||
de création. Aucun arrêt/annulation d'une session ETW tierce ; vérifier les sessions avant démarrage.
|
||||
|
||||
### B. Télémétrie native légère, versionnée
|
||||
|
||||
Publier les compteurs depuis le code qui les possède ; ne plus les déduire d'offsets PDB
|
||||
via `ReadProcessMemory`. Un schéma versionné comporte `run_id`, version, QPC/fréquence,
|
||||
PID/TID, génération du cœur/rechargement IOS et des compteurs monotones.
|
||||
L'export asynchrone est borné ; les débordements sont comptés. Aucune écriture de log
|
||||
synchrone à chaque instruction ou accès. Ne pas ajouter de verrou partagé au chemin mémoire.
|
||||
Récupérer les données sur leur thread propriétaire, sans lecture C++ concurrente non synchronisée.
|
||||
|
||||
- Temps invité écoulé et cycles ARM/PPC, séparés du temps hôte QPC.
|
||||
- Temps de frames réellement produites : histogramme p50/p95/p99 et longues frames,
|
||||
rapporté au mode vidéo du profil (50 ou 60 Hz). Une médiane de FPS n'est pas ce calcul.
|
||||
- Agrégats toutes les secondes ; chronologie d'analyse en fenêtres de 250 ms quand
|
||||
les événements le permettent. Marquer les fenêtres qui n'ont pas assez de données.
|
||||
- JIT : compilations, invalidations, instructions natives/fallback, accès lents existants,
|
||||
entrées en attente et sorties de slice, avec identifiant de génération après reset.
|
||||
- NAND : lectures/programmes/effacements, transactions, octets et erreurs ; séparer
|
||||
sérialisation/hash, appels d'écriture, `IOFile::Flush` et attente hôte observée.
|
||||
- Réseau : octets/trames hôte reçus, mise en file NAT, remise USB à IOS, occupation maximale
|
||||
et âge des files. Le débit reçu ne prouve pas le débit consommé par IOS.
|
||||
|
||||
Les chronomètres de régions fréquentes sont échantillonnés et calibrés, jamais posés sur
|
||||
chaque accès ARM. Les frontières plus rares (rechargement, compilations, gros transferts)
|
||||
peuvent produire des événements. Éviter un échantillonnage périodique aligné sur la boucle
|
||||
invitée ; conserver le taux de sélection et distinguer estimation et total exact.
|
||||
|
||||
### C. Rendre les échantillons JIT attribuables
|
||||
|
||||
Un PDB décrit le C++ compilé, pas automatiquement le code généré à l'exécution.
|
||||
Exporter, à compilation/invalidation, les intervalles d'adresses **hôte** du JIT ARM et
|
||||
du JIT PPC, dispatcher/trampolines compris, avec QPC et génération ; pour les blocs,
|
||||
indiquer PC invité, ARM/Thumb et identité du mapping. Ne pas extraire ni publier le firmware.
|
||||
Une adresse réutilisée après vidage du cache doit se résoudre selon la date de l'échantillon.
|
||||
|
||||
Classer l'IP feuille même si la pile ne traverse pas correctement une transition JIT/C++.
|
||||
Ne pas inventer de parent de pile manquant. Garder « pile tronquée » et « code non attribué »
|
||||
visibles ; ajouter une instrumentation ciblée si ces trous empêchent la décision.
|
||||
Le support `Common::JitRegister` existant côté PPC est un point d'intégration à examiner,
|
||||
pas une garantie que le JIT ARM ou l'unwinding Windows sont déjà couverts.
|
||||
|
||||
## 5. Points d'attribution dans ce dépôt
|
||||
|
||||
| Domaine | Points à observer | Preuve recherchée |
|
||||
|---|---|---|
|
||||
| Ordonnancement ARM | `Starlet::RunSlice`, `ARMCore::RunCycles` | Coût de dispatch, quanta/s, transitions, temps invité/hôte |
|
||||
| JIT ARM | `ARMJitX64::Run`, compilation, code généré, helpers | Part CPU feuille, blocs invités chauds, recompilations |
|
||||
| Mémoire ARM | `ReadMemorySlow`, `WriteMemorySlow`, traduction, bus | CPU exclusif des helpers et classes d'accès, pas leur seul nombre |
|
||||
| Périphériques | `StarletMemory::AdvanceCycles`, DMA, AES/SHA, OHCI/EHCI | CPU exclusif par fonction ; attente simulée séparée du travail hôte |
|
||||
| NAND | `CommitNANDPages`, `NANDJournal::Append`, `IOFile::Flush` | CPU de préparation vs appels fichiers vs attente disque réelle |
|
||||
| Réseau | `SlirpNetwork::Poll`, AX88772, remise OHCI | CPU NAT/USB, files, progression hôte versus progression invitée |
|
||||
| PPC / rendu | JIT PPC, threads vidéo, présentation | Concurrence réelle et dépendances de l'émulation, pas seulement FPS |
|
||||
| Hors émulation | Limiteur, audio, logs, collecteur, Windows | Attente voulue, contention, CPU de diagnostic, temps Ready |
|
||||
|
||||
Sur un même thread, présenter les **temps exclusifs** des régions imbriquées.
|
||||
Présenter aussi leurs temps inclusifs, mais dans une autre colonne, non additionnable.
|
||||
Ne pas additionner le CPU de plusieurs threads comme une durée murale de mise à jour.
|
||||
Pour les attentes, suivre la dépendance qui retarde le thread utile ; un thread GPU qui
|
||||
attend l'émulation n'est pas une cause de ralentissement GPU.
|
||||
`fflush` n'est pas une preuve de vidage physique sur disque : le niveau de persistance
|
||||
actuel reste inchangé et les attentes sont établies par les événements hôte.
|
||||
|
||||
## 6. Qualification obligatoire, sans demander de mise à jour à l'utilisateur
|
||||
|
||||
Avant de dire « lance la mise à jour », un contrôle local court doit démontrer :
|
||||
|
||||
1. EXE/PDB identifiés ; compteur versionné lu correctement ; horloges alignées ; un reset
|
||||
ne produit pas de deltas négatifs ; pas de perte silencieuse d'événements.
|
||||
2. Une boucle JIT connue est correctement attribuée ARM/PPC ; son coût CPU augmente
|
||||
comme prévu. Un cas d'attente connu est classé Waiting, pas « calcul JIT ».
|
||||
3. Les scopes imbriqués d'un test ont des temps exclusifs cohérents, sans double comptage.
|
||||
4. Un cas de journal synthétique et de réseau local, sans service Nintendo, est visible.
|
||||
5. Mesurer le surcoût ON/OFF du dispositif complet sur la même charge locale, dans le même
|
||||
binaire et en ordre alterné. Budget initial : **2 %** de temps mural/CPU, bruit affiché.
|
||||
Ce seuil est une règle de projet, pas une garantie d'ETW. S'il est dépassé ou non résolu
|
||||
par le bruit, alléger les fournisseurs/samples avant le test. Le contrôle ne garantit
|
||||
pas le même surcoût sur toutes les phases natives : relever aussi la charge du collecteur.
|
||||
|
||||
Pas de nouveau comportement invité, pas de changement de NAT, timers, JIT, NAND ou SVC.
|
||||
Les boucles SVC/polling éventuelles sont d'abord attribuées à du CPU/PC invité ; aucune
|
||||
émulation accélérée d'appel IOS ne découle d'un simple comptage d'instructions.
|
||||
|
||||
## 7. Une capture native, puis analyse hors ligne
|
||||
|
||||
1. Vérifier réserve disque et absence de test/build actif. Enregistrer le manifeste.
|
||||
2. Armer ETW et la télémétrie **avant** de lancer le profil isolé ; confirmer une fenêtre
|
||||
visible et des mesures valides. Ne pas se baser sur les messages utilisateur pour armer.
|
||||
3. L'utilisateur lance une seule mise à jour. Garder 10 s de référence avant l'activité.
|
||||
Tout marquage manuel reste approximatif ; les phases sont reconstruites à partir des
|
||||
événements synchronisés, files réseau, travail invité et commits NAND.
|
||||
4. Téléchargement, calcul et installation peuvent se chevaucher : ne pas leur imposer
|
||||
trois phases exclusives artificielles. Une file vide ne prouve pas une attente serveur.
|
||||
5. Garder environ 10 s après la réussite signalée, puis arrêter uniquement la capture.
|
||||
Ne pas arrêter Dolphin, modifier la NAND ou cliquer à la place de l'utilisateur.
|
||||
6. Garde-fous initiaux : 15 min de capture, budget disque 4 Gio et réserve 5 Gio ; le pilote
|
||||
doit arrêter proprement **sa** capture si une limite approche, conserver le préfixe et
|
||||
déclarer les phases manquantes. Une trace incomplète n'est pas un échec de la mise à jour.
|
||||
7. Vérifier les événements perdus et le coût du profilage. Ne pas charger WPA ni effectuer
|
||||
une grosse analyse/hachage pendant la mesure. Fermer ensuite Dolphin avec l'utilisateur
|
||||
pour les vérifications NAND, comme pour F.
|
||||
|
||||
Les traces en mode fichier sont adaptées à ce scénario contrôlé, mais ajoutent des E/S :
|
||||
les distinguer du journal NAND, relever le volume et ne pas supposer leur coût nul.
|
||||
Les pertes d'événements rendent certaines conclusions impossibles ; les vérifier explicitement.
|
||||
[Sessions ETW/WPR — Microsoft](https://learn.microsoft.com/en-us/windows-hardware/test/wpt/sessions)
|
||||
|
||||
## 8. Rapport exigé avant tout correctif
|
||||
|
||||
Analyser la capture entière et, au minimum, trois fenêtres lentes non chevauchantes de
|
||||
10 s si elles existent, ainsi qu'une fenêtre rapide de la même exécution. Une fenêtre lente
|
||||
est définie avant analyse : vitesse invitée moyenne < 90 % pendant au moins 2 s ; analyser
|
||||
aussi les longues frames indépendamment. Rapporter l'absence de fenêtres admissibles.
|
||||
Comparer des types d'activité similaires ; ne pas comparer une pause réseau à une installation.
|
||||
|
||||
Livrer :
|
||||
|
||||
- Chronologie superposant vitesse/frames, CPU Running/Ready/Waiting, NAND et files réseau.
|
||||
- Top fonctions/piles, part CPU exclusive/inclusive, nombre d'échantillons, contexte invité.
|
||||
- Temps critique perdu en calcul, Ready et attentes expliquées ; catégories inconnues visibles.
|
||||
- Coût par unité de travail quand disponible : CPU/transaction, CPU/Mio traité, compilations
|
||||
par instruction, etc. Un compteur n'a de sens que pour la même opération/sémantique.
|
||||
- Liste des observations qui réfutent les autres pistes ; distinguer preuve et hypothèse.
|
||||
|
||||
Gates de qualité initiaux : zéro perte sur les flux indispensables à l'intervalle analysé,
|
||||
au moins 95 % des échantillons CPU Dolphin attribués à un domaine, compteurs intègres et
|
||||
coût de collecte qualifié. Ce sont des critères d'analyse, non des promesses de précision.
|
||||
Une pile incomplète peut permettre de classer un domaine sans identifier sa cause interne :
|
||||
on ne valide alors pas un correctif visant une fonction non résolue. Pas de fausse certitude
|
||||
statistique obtenue en traitant des échantillons temporels corrélés comme des essais indépendants.
|
||||
|
||||
Un correctif est admissible seulement si :
|
||||
|
||||
1. La cause apparaît dans plusieurs fenêtres lentes avec une signature explicable.
|
||||
2. Sa part sur le chemin qui retarde l'émulation est chiffrée, avec son incertitude.
|
||||
3. Un cas local représentatif reproduit cette charge ou cette attente.
|
||||
4. Le gain global plausible est estimé avant modification. Par exemple, supprimer tout un
|
||||
poste responsable de 5 % du temps critique ne retire au mieux que 5 % de cette durée.
|
||||
5. Le correctif garde le comportement matériel et passe les tests ciblés/interpréteur.
|
||||
|
||||
Décision pratique : si le CPU est dans les helpers, travailler ces helpers ; s'il est
|
||||
dans le code invité, examiner les blocs et le travail IOS ; si Ready domine, étudier
|
||||
la contention hôte ; si les attentes d'E/S dominent, traiter leur dépendance réelle.
|
||||
Si les files NAT sont pleines mais peu consommées, ne pas accuser le serveur ; si elles
|
||||
sont vides, confirmer l'attente avec les échanges/états disponibles ou laisser la cause ouverte.
|
||||
Si aucun poste ne domine, le rapport le dit : on ne fabrique pas un unique responsable.
|
||||
|
||||
## 9. Validation minimale après diagnostic
|
||||
|
||||
D'abord une validation locale répétable du poste identifié, résultat invité exact et même
|
||||
charge. Puis une validation native ciblée du scénario corrigé, pas une série de réglages.
|
||||
La trace de diagnostic peut localiser une cause, mais son temps n'est pas automatiquement
|
||||
une référence équitable face à une build sans instrumentation. Pour revendiquer un gain
|
||||
global, conserver un dispositif équivalent et répéter seulement si la variabilité observée
|
||||
empêche la conclusion. Annoncer cette nécessité et sa raison, pas un nouveau test à l'aveugle.
|
||||
L'objectif est de réduire les essais utilisateur ; garantir à l'avance qu'un seul essai
|
||||
prouvera toute causalité serait trompeur.
|
||||
|
||||
## 10. Artefacts et limites
|
||||
|
||||
Conserver dans un nouveau répertoire local ignoré : manifeste, capture ETL, télémétrie
|
||||
versionnée, mapping JIT daté, coût de collecte, tableaux de fenêtres, piles chaudes,
|
||||
rapport des attentes, événements perdus et décision. Le rapport lisible va dans `docs`.
|
||||
Pas de clés NAND, mémoire brute invitée, mots de passe ou contenu réseau dans les exports.
|
||||
Les ETL peuvent contenir des chemins et noms de processus : conservation locale, pas de push.
|
||||
|
||||
État au 22 septembre 2026 : instrumentation opt-in `DOLPHIN_PERF_TRACE=1`, mapping
|
||||
temporel JIT ARM/PPC, scopes/counters versionnés, profil WPR ciblé, décodeur ETL et
|
||||
sonde locale ont été ajoutés. La build isolée passe et la sonde privée a validé
|
||||
13 contrôles locaux sur 13 sur deux captures, avec zéro perte d'événement.
|
||||
Sur deux paires alternées, la phase ARM avec trace privée dépasse la phase sans
|
||||
trace d'environ 1,7 % en moyenne, mais la dispersion est supérieure à cet écart.
|
||||
Le budget de 2 % n'est donc pas qualifié. Le démarrage/arrêt du logger privé
|
||||
ajoute environ 0,34 s à ces exécutions courtes ; ce coût ne mesure pas le
|
||||
surcoût du collecteur WPR pendant une mise à jour Wii.
|
||||
La session WPR ne démarrait pas dans le jeton Windows de cette tâche
|
||||
(`0xc5585011`, droit de profilage système absent). Une capture synthétique
|
||||
administrateur a depuis produit l'ETL `P1-local-004`, sans perte. L'analyse
|
||||
hors ligne, reproductible sous PowerShell 5.1, valide 9 427 échantillons CPU,
|
||||
694 context-switches, dix ancres QPC alignées à cinq ticks près, et le sommeil
|
||||
connu effectivement classé `Waiting`. Le PDB local résout les fonctions C++;
|
||||
le mapping temporel attribue les IP du JIT ARM. Les 112 événements Xperf
|
||||
invalides sont des métadonnées `ImageID` hors du PID cible. Voir
|
||||
[`Tools/PerformanceTrace/README.md`](../Tools/PerformanceTrace/README.md).
|
||||
Le lot WPR `P1-overhead-001` a terminé ses huit charges synthétiques sans perte
|
||||
ETW ; seul son calcul final a échoué faute de Python dans le PowerShell
|
||||
administrateur. Le calcul récupéré hors ligne donne quatre écarts ARM ON/OFF de
|
||||
+9,7 %, +25,0 %, -0,5 % et +1,0 %, tandis que les quatre bases OFF ont une
|
||||
étendue de 34,5 %. Cette variabilité interdit d'annoncer un coût fiable du
|
||||
collecteur ou de qualifier le seuil de 2 %. Le script vérifie maintenant Python
|
||||
avant toute capture et peut analyser un lot déjà enregistré avec `-AnalyzeOnly`.
|
||||
Les traces ON montrent en outre un indexeur C++ hôte (`cpptools.exe`) actif
|
||||
pendant chaque essai et des services Dell intermittents. Le profil a été allégé
|
||||
des piles `ReadyThread`, tout en conservant leurs événements ; sa nouvelle
|
||||
version n'est pas encore qualifiée par un lot ON/OFF stable.
|
||||
Le second lot avec ce profil (`P1-overhead-002`) a conservé zéro perte ETW mais
|
||||
36,5 % d'étendue entre bases OFF. L'analyse par processeur montre que la sonde
|
||||
rapide passe 78,7 % de ses échantillons sur les logiques 0–3 contre 28,9 % pour
|
||||
la sonde la plus lente ; les temps ARM correspondants sont 7,59 et 10,33 s.
|
||||
L'ETL identifie un i7-1255U hybride avec SMT sur 0–3. Le lanceur Wii fixait
|
||||
déjà Dolphin à ces processeurs, mais les sondes OFF/ON ne l'étaient pas.
|
||||
L'affinité a été ajoutée aux sondes et vérifiée localement (masque 15 observé).
|
||||
Quatre bases fixées gardent toutefois 8,3 % de dispersion ARM ; elles ne
|
||||
valident pas encore le seuil initial de 2 %. Il serait trompeur de demander un
|
||||
troisième lot administrateur sans résoudre cette variabilité résiduelle.
|
||||
Les événements natifs ne sont pas activés dans les profils utilisateur par défaut.
|
||||
Une build et une sonde locale réussies ne valident pas le budget de 2 % ni le
|
||||
comportement d'une mise à jour native. Le vérificateur local conserve
|
||||
`native_update_ready=false` tant que les gates PPC, chemin critique natif et
|
||||
coût du collecteur n'ont pas été validées.
|
||||
**Ne pas demander de nouvel essai utilisateur tant que ces gates ne passent pas.**
|
||||
Reference in new issue
Block a user