-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdb.json
1 lines (1 loc) · 443 KB
/
db.json
1
{"meta":{"version":1,"warehouse":"5.0.1"},"models":{"Asset":[{"_id":"themes/butterfly/source/css/index.styl","path":"css/index.styl","modified":0,"renderable":1},{"_id":"themes/butterfly/source/css/var.styl","path":"css/var.styl","modified":0,"renderable":1},{"_id":"themes/butterfly/source/img/404.jpg","path":"img/404.jpg","modified":0,"renderable":1},{"_id":"themes/butterfly/source/img/avatar.JPG","path":"img/avatar.JPG","modified":0,"renderable":1},{"_id":"themes/butterfly/source/img/avatar.png","path":"img/avatar.png","modified":0,"renderable":1},{"_id":"themes/butterfly/source/img/favicon.png","path":"img/favicon.png","modified":0,"renderable":1},{"_id":"themes/butterfly/source/img/friend_404.gif","path":"img/friend_404.gif","modified":0,"renderable":1},{"_id":"themes/butterfly/source/draw.io/USB结构体.drawio","path":"draw.io/USB结构体.drawio","modified":0,"renderable":1},{"_id":"themes/butterfly/source/draw.io/test.txt","path":"draw.io/test.txt","modified":0,"renderable":1},{"_id":"themes/butterfly/source/draw.io/kvm-qemu添加内存.drawio","path":"draw.io/kvm-qemu添加内存.drawio","modified":0,"renderable":1},{"_id":"themes/butterfly/source/draw.io/未命名绘图.drawio","path":"draw.io/未命名绘图.drawio","modified":0,"renderable":1},{"_id":"themes/butterfly/source/js/main.js","path":"js/main.js","modified":0,"renderable":1},{"_id":"themes/butterfly/source/js/tw_cn.js","path":"js/tw_cn.js","modified":0,"renderable":1},{"_id":"themes/butterfly/source/js/utils.js","path":"js/utils.js","modified":0,"renderable":1},{"_id":"themes/butterfly/source/js/search/local-search.js","path":"js/search/local-search.js","modified":0,"renderable":1},{"_id":"themes/butterfly/source/js/search/algolia.js","path":"js/search/algolia.js","modified":0,"renderable":1},{"_id":"source/images/Spinlock/spinlock嵌套-1.svg","path":"images/Spinlock/spinlock嵌套-1.svg","modified":0,"renderable":0},{"_id":"source/images/Workqueue/Workqueue结构体-1.drawio.svg","path":"images/Workqueue/Workqueue结构体-1.drawio.svg","modified":0,"renderable":0},{"_id":"source/images/MMU/MAIR_EL1-1.png","path":"images/MMU/MAIR_EL1-1.png","modified":0,"renderable":0},{"_id":"source/images/MMU/MAIR_EL1-2.png","path":"images/MMU/MAIR_EL1-2.png","modified":0,"renderable":0},{"_id":"source/images/MMU/PTE-1.png","path":"images/MMU/PTE-1.png","modified":0,"renderable":0},{"_id":"source/images/MMU/MAIR_EL1-3.png","path":"images/MMU/MAIR_EL1-3.png","modified":0,"renderable":0},{"_id":"source/images/MMU/PTE-2.png","path":"images/MMU/PTE-2.png","modified":0,"renderable":0},{"_id":"source/images/MMU/TCR寄存器位图.png","path":"images/MMU/TCR寄存器位图.png","modified":0,"renderable":0},{"_id":"source/images/MMU/TTBR表示的地址范围.drawio.svg","path":"images/MMU/TTBR表示的地址范围.drawio.svg","modified":0,"renderable":0}],"Cache":[{"_id":"source/_posts/Cgroup.md","hash":"276485442e7e7f6d700150c262e810f34f1956a5","modified":1723898685288},{"_id":"source/categories/index.md","hash":"a144ad12c705bfdc4ea71b8e30a0839c480c4c49","modified":1723287051038},{"_id":"source/tags/index.md","hash":"6f5799cc90df0dbf30e1c2fab1dfa3a34b48fec5","modified":1723287431739},{"_id":"source/_posts/Ebuf.md","hash":"c0577fcacb3d6f06c55d42b74a5f8b250de439e6","modified":1723812831254},{"_id":"source/_posts/DeviceTree.md","hash":"c695fc6550ae1fa2604447e76fface6b224dd973","modified":1723812831254},{"_id":"source/_posts/CpuTopology.md","hash":"545c02a33671b82a644fe5d06816e53161a5881a","modified":1723629682766},{"_id":"source/_posts/HugeTLB.md","hash":"819513948845cdb9e09c04d0fc35ff580c9d8269","modified":1723306417995},{"_id":"source/_posts/FileSystem.md","hash":"999bfc2720fccb6cd5be591939112b805ac3de97","modified":1723306408241},{"_id":"source/_posts/DeviceModel.md","hash":"784c1dc728fc2cec461a1a73be4d453d6499ef53","modified":1723554923309},{"_id":"source/_posts/Ftrace.md","hash":"56dd43320b78259ee30ac21f58b6e978c4cc2b8c","modified":1723629682766},{"_id":"source/_posts/Gic.md","hash":"c67adfc2a1b5fc26e6f0b85e8b6f83e528270743","modified":1723812831255},{"_id":"source/_posts/Linux踩内存问题定位.md","hash":"4bfca6b579de6a9374c97cfad81b745e0cc9ddb4","modified":1723812831255},{"_id":"source/_posts/Kprobe.md","hash":"cd224567c080c2da635c799ba971a78e358a6db7","modified":1723554923309},{"_id":"source/_posts/GccTool.md","hash":"6b97f961319b677aded23457277b886b629c1916","modified":1723554923309},{"_id":"source/_posts/Kvm.md","hash":"986e2c91cd6ba9ff58b10111734bd462f4f83b83","modified":1723306478666},{"_id":"source/_posts/Mte.md","hash":"c85a09d6d3f93f5ed17354259051a32aae866d36","modified":1723554923309},{"_id":"source/_posts/Net.md","hash":"c7b0a18aa03fe15b8cd117003e4fb8a2079df9b6","modified":1723812831256},{"_id":"source/_posts/Mmu.md","hash":"134766aab2466e6f0276ae82551e94f01cb11ec4","modified":1723812831256},{"_id":"source/_posts/Memblock.md","hash":"ed642d26e6faf89fbe7ba31eea2acd6ace0ffbde","modified":1723812831255},{"_id":"source/_posts/NumaPerf.md","hash":"c5d7d4f5dda4db8e459e6f6d27d48495bf05b9dc","modified":1723629682766},{"_id":"source/_posts/I2c Protocol.md","hash":"c36df1871e842b510e3b6d5dffd33e9f98acefce","modified":1723458171119},{"_id":"source/_posts/Numa.md","hash":"139d66c1f66965bb28092b7b6de6847f79decc02","modified":1723812831256},{"_id":"source/_posts/PowerManage.md","hash":"0ead00f8020487572897a18f6d0f94a5ef52ec0f","modified":1723812831256},{"_id":"source/_posts/Perf.md","hash":"85033d52065b1347c6ed39729115f9c7847c76ed","modified":1723629682766},{"_id":"source/_posts/Pgtable.md","hash":"ede4399965edab82932eb608388523946077f7c7","modified":1723562774424},{"_id":"source/_posts/Proc-pagemap.md","hash":"02ebe0dd3c9e9ecb4896843a2c06c86eb2ed4c16","modified":1723629682766},{"_id":"source/_posts/Proc-meminfo.md","hash":"aa12633d0d360ce8dceecd528a32a108c3f70a58","modified":1723629682766},{"_id":"source/_posts/Ptrace.md","hash":"505118f6b9451f340aad2c8f159d260ad2a7522a","modified":1723554923310},{"_id":"source/_posts/ProcessSchedule.md","hash":"2321ce1fa177134d96b5303ae20dbea3ed02b33b","modified":1723812831257},{"_id":"source/_posts/Prctl.md","hash":"b26fd192860c8b99fb5c26192d7cd0cb664f823e","modified":1723458224627},{"_id":"source/_posts/Security.md","hash":"b38becb5abfac2d04d0893582d0a2af8540c1101","modified":1723629682766},{"_id":"source/_posts/Smmu.md","hash":"01de13903e90897cf83d4714b2dc4b50b1df3095","modified":1723812831257},{"_id":"source/_posts/Sysrq.md","hash":"d9b4d9e0c7acae91018782545c470c2986fde643","modified":1723564078971},{"_id":"source/_posts/TLB.md","hash":"75c8fc188a96fe4380ed191bcc03f1cd464e6d8f","modified":1723812831257},{"_id":"source/_posts/TraceEvent.md","hash":"2b1ae1f80a04f6b7a91bec530adc1ee2e83e1e71","modified":1723306465065},{"_id":"source/_posts/Tasklet.md","hash":"5eaa9eb26c8f9dd89f732b71609724d13116c98d","modified":1723629682767},{"_id":"source/_posts/Rcu.md","hash":"999dc8d6e91a0fc503a6a6a1a1b39be66072c07a","modified":1723306428756},{"_id":"source/_posts/Timer.md","hash":"3074406106814bc263eb544d4b480f207a85feaf","modified":1723629682767},{"_id":"source/_posts/StartUp.md","hash":"5ed745775b773f1b7f6adff566a44f84a6680120","modified":1723565227365},{"_id":"source/_posts/Workqueue.md","hash":"2f150ad72a1564e4c425473083c426941862840f","modified":1723812831257},{"_id":"source/images/MMU/MAIR_EL1-1.png","hash":"77d9f5557fed2f1dfc71f4e1d531b8ba14b6acfd","modified":1723561710471},{"_id":"source/images/MMU/PTE-1.png","hash":"d78c464a3736bd135ad4eb8bc9b06dd047b1a91c","modified":1723562346280},{"_id":"source/images/MMU/PTE-2.png","hash":"a1cb1e4b7a084344a59f9eb4b1373de0a7ba98ab","modified":1723562364202},{"_id":"source/_posts/Spinlock.md","hash":"60284ad1bfa689ac67f7eb3a601569fcc477e857","modified":1723567160843},{"_id":"source/images/MMU/TTBR表示的地址范围.drawio.svg","hash":"9d7f8d8d8c91d8143e59ec8f7cd6b35e5cf18a94","modified":1723371499761},{"_id":"source/_posts/Vmcore.md","hash":"8ac2809f4cc50f1b42634470ad011b6a9dc48f12","modified":1723554923310},{"_id":"source/_posts/Virt.md","hash":"d202b57d9a54a7f8c9b0181f48d806de280d1ae9","modified":1723717551989},{"_id":"source/images/Spinlock/spinlock嵌套-1.svg","hash":"19c284b39227c12d06a2fa0611bc0da7733752b2","modified":1723566777503},{"_id":"source/images/MMU/TCR寄存器位图.png","hash":"e8aec1a1b950737e109eccc0ab5c27293cb48e3d","modified":1723383472792},{"_id":"source/images/MMU/MAIR_EL1-2.png","hash":"7d693539760d0d81c1c5ca1aac265ee385daca02","modified":1723561879262},{"_id":"source/images/MMU/MAIR_EL1-3.png","hash":"25d932916e28d21cb8b0ade8d096cf37ec91acd9","modified":1723561933970},{"_id":"themes/butterfly/_config.yml","hash":"0f30e41f9bedbfaeae259fba4952979114af1632","modified":1722958058709},{"_id":"themes/butterfly/LICENSE","hash":"1128f8f91104ba9ef98d37eea6523a888dcfa5de","modified":1722946893303},{"_id":"themes/butterfly/.DS_Store","hash":"9a724c0f7ee603cb6d683a26c9f00f26df83a74f","modified":1722959186685},{"_id":"themes/butterfly/package.json","hash":"314b0271ba3f668d0d6081b499b2d24e90dab25e","modified":1722946893311},{"_id":"themes/butterfly/README_CN.md","hash":"148da187d16033624ceccce8b8561835296f5a5a","modified":1722946893303},{"_id":"themes/butterfly/plugins.yml","hash":"d807fbb62163bb6fc5a83a24ebd69ac14cf45f67","modified":1722946893311},{"_id":"themes/butterfly/languages/en.yml","hash":"af5603b1a888f167dc80be6d53a19437b5cf6bef","modified":1722946893303},{"_id":"themes/butterfly/languages/default.yml","hash":"90a6dc361de67532437d819a55ec64945ca5404b","modified":1722946893303},{"_id":"themes/butterfly/layout/archive.pug","hash":"bb32c9c476372de747dfa563b83f77d7a917a77d","modified":1722946893303},{"_id":"themes/butterfly/languages/zh-TW.yml","hash":"03629d1d13a7be09d4933aa5dc0dcbe45e79140c","modified":1722946893303},{"_id":"themes/butterfly/layout/category.pug","hash":"710708cfdb436bc875602abf096c919ccdf544db","modified":1722946893303},{"_id":"themes/butterfly/languages/zh-CN.yml","hash":"5004faee365139521f161babd66649a8107e4008","modified":1722946893303},{"_id":"themes/butterfly/layout/index.pug","hash":"e1c3146834c16e6077406180858add0a8183875a","modified":1722946893311},{"_id":"themes/butterfly/layout/post.pug","hash":"fc9f45252d78fcd15e4a82bfd144401cba5b169a","modified":1722946893311},{"_id":"themes/butterfly/layout/page.pug","hash":"baf469784aef227e4cc840550888554588e87a13","modified":1722946893311},{"_id":"themes/butterfly/layout/tag.pug","hash":"0440f42569df2676273c026a92384fa7729bc4e9","modified":1722946893311},{"_id":"themes/butterfly/README.md","hash":"4e01b47448d9f3a02afc04eef644e2321253f6f4","modified":1722946893303},{"_id":"themes/butterfly/.github/FUNDING.yml","hash":"da5e77f5e0cdb7e11b36546fb6796d10e3dfbe5d","modified":1722946893302},{"_id":"themes/butterfly/.github/ISSUE_TEMPLATE/bug_report.yml","hash":"6e34b565ea013812d5e363b6de5fa1f9078d4e12","modified":1722946893302},{"_id":"themes/butterfly/.github/ISSUE_TEMPLATE/config.yml","hash":"7b4831ae8f8f8c55dd1b856781210c517c63e6dd","modified":1722946893302},{"_id":"themes/butterfly/.github/ISSUE_TEMPLATE/feature_request.yml","hash":"996640605ed1e8e35182f0fd9a60a88783b24b03","modified":1722946893302},{"_id":"themes/butterfly/layout/includes/404.pug","hash":"cb49f737aca272ccfeb62880bd651eccee72a129","modified":1722946893304},{"_id":"themes/butterfly/.github/workflows/publish.yml","hash":"05857c2f265246d8de00e31037f2720709540c09","modified":1722946893302},{"_id":"themes/butterfly/layout/includes/footer.pug","hash":"02390a5b6ae1f57497b22ba2e6be9f13cfb7acac","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/additional-js.pug","hash":"aca0ec7ef69b21d1f242c62fed389468a0f0e1a2","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/head.pug","hash":"ecec62305aaa596bb1dfbb46c13d06fb5a9628cf","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/layout.pug","hash":"7fa9ae4b70b87fc97e992dde5944681f92b59bea","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/rightside.pug","hash":"db275f7fbe4438b54cd813b695f4834e10aa234f","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/pagination.pug","hash":"4c85de4dea4dca4e5088097a79bd6d7009cbf8ef","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/sidebar.pug","hash":"9f0e9e039f304439007460fa0a7c8ac18e0ffd37","modified":1722946893306},{"_id":"themes/butterfly/scripts/events/404.js","hash":"83cd7f73225ccad123afbd526ce1834eb1eb6a6d","modified":1722946893311},{"_id":"themes/butterfly/scripts/events/cdn.js","hash":"21fb5aabe043486d095c4c8cce361ed85ba88a26","modified":1722946893311},{"_id":"themes/butterfly/.github/workflows/stale.yml","hash":"ac62b989b5550c756e1986fcc68f243170705383","modified":1722946893302},{"_id":"themes/butterfly/scripts/events/comment.js","hash":"5351e0bc09e6b5b3f6d30f333a2520626a28ca3a","modified":1722946893312},{"_id":"themes/butterfly/scripts/events/merge_config.js","hash":"2ac43fd4103ba3c6897da7c13015cb05f39fd695","modified":1722946893312},{"_id":"themes/butterfly/scripts/events/stylus.js","hash":"e196a99733d7f90899bceed5d12488e8234817d5","modified":1722946893312},{"_id":"themes/butterfly/scripts/events/init.js","hash":"428b94c7b9e83f7ea36227dee66bfe3c23aee4a8","modified":1722946893312},{"_id":"themes/butterfly/scripts/filters/post_lazyload.js","hash":"860f967ecf3c6a6ea785b560a7aae4d0757cd18a","modified":1722946893312},{"_id":"themes/butterfly/scripts/events/welcome.js","hash":"8ad9911b755cba13dde2cc055c3f857a6b0dd20e","modified":1722946893312},{"_id":"themes/butterfly/scripts/filters/random_cover.js","hash":"a8eef3f37428436554f58a2b6bac7c255fbdf38d","modified":1722946893312},{"_id":"themes/butterfly/scripts/helpers/aside_archives.js","hash":"2ec66513d5322f185d2071acc052978ba9415a8e","modified":1722946893312},{"_id":"themes/butterfly/scripts/helpers/findArchiveLength.js","hash":"7caf549810f971c34196fb9deac2d992545bdff9","modified":1722946893312},{"_id":"themes/butterfly/scripts/helpers/aside_categories.js","hash":"96f861151e3b889ef0ffe78821d489ad2625ee43","modified":1722946893312},{"_id":"themes/butterfly/scripts/helpers/inject_head_js.js","hash":"d5c7e61257b08a9648404f6f48ce4d471cd5fa55","modified":1722946893313},{"_id":"themes/butterfly/scripts/helpers/page.js","hash":"e2a8a09bfe47da26eab242a36f516e6c452c799a","modified":1722946893313},{"_id":"themes/butterfly/scripts/helpers/series.js","hash":"821e973d41f7b3b64cde91e0e836ea49c43e3c06","modified":1722946893313},{"_id":"themes/butterfly/scripts/helpers/related_post.js","hash":"4677be4175da6800c0b3b8c1614e593f73df8831","modified":1722946893313},{"_id":"themes/butterfly/scripts/tag/flink.js","hash":"ab62919fa567b95fbe14889517abda649991b1ee","modified":1722946893313},{"_id":"themes/butterfly/scripts/tag/gallery.js","hash":"418684993a3a3a2ac534257a2d9ecbcead6808c1","modified":1722946893313},{"_id":"themes/butterfly/scripts/tag/button.js","hash":"93229d44b35b9da92e647b89d6d3087085974a29","modified":1722946893313},{"_id":"themes/butterfly/scripts/tag/label.js","hash":"19773218877281ccffed921431e87148413a7c20","modified":1722946893313},{"_id":"themes/butterfly/scripts/tag/inlineImg.js","hash":"512c68a22ae4a58d6a6b24b368a0c00c2ccb4fcb","modified":1722946893313},{"_id":"themes/butterfly/scripts/tag/mermaid.js","hash":"5c2a07df5874b5377540884e4da14dd21489378f","modified":1722946893313},{"_id":"themes/butterfly/scripts/tag/hide.js","hash":"365db87ddfc582bf8c15cb440c48bed95106e4b1","modified":1722946893313},{"_id":"themes/butterfly/scripts/tag/note.js","hash":"1acefc59ead75ebd8cafee36efc7da4fa426d088","modified":1722946893313},{"_id":"themes/butterfly/scripts/tag/score.js","hash":"5cb273e95846874e3a58074074c501df23c5e912","modified":1722946893313},{"_id":"themes/butterfly/scripts/tag/timeline.js","hash":"4526c75e5bf84609d67e92b6af3524bcb278e852","modified":1722946893314},{"_id":"themes/butterfly/scripts/tag/tabs.js","hash":"ffc62222f8d7b4d44c1c0726c8a08824a2201039","modified":1722946893314},{"_id":"themes/butterfly/source/css/var.styl","hash":"152b6bd4b6285165541a71f5a1c913f8ee6a602b","modified":1722946893318},{"_id":"themes/butterfly/source/css/index.styl","hash":"755490867fd8afe47d5cce24faea2ca172b0c4dd","modified":1722946893318},{"_id":"themes/butterfly/source/img/404.jpg","hash":"fb4489bc1d30c93d28f7332158c1c6c1416148de","modified":1722946893318},{"_id":"themes/butterfly/source/img/avatar.JPG","hash":"8f393cf35ca25ce834024337a3b9d82794089451","modified":1722957915000},{"_id":"themes/butterfly/source/img/avatar.png","hash":"0b36c77ba8f9b99336b07a059e45b7dbcbf5ebd9","modified":1722955796959},{"_id":"themes/butterfly/source/.DS_Store","hash":"0326899d45b25c6ce269c1a7ea2ca46461dc8263","modified":1722959191706},{"_id":"themes/butterfly/source/img/favicon.png","hash":"3cf89864b4f6c9b532522a4d260a2e887971c92d","modified":1722946893318},{"_id":"themes/butterfly/scripts/tag/series.js","hash":"830b1d592278b9f676df0cf9a91b1eeda2456aec","modified":1722946893314},{"_id":"themes/butterfly/source/draw.io/test.txt","hash":"7d0a1e6a061b02ee7d07bf65462298f22eb0c770","modified":1722959220021},{"_id":"themes/butterfly/source/draw.io/USB结构体.drawio","hash":"5552c75ca2d5545f11ec44197af4437e0d92482c","modified":1723200795491},{"_id":"themes/butterfly/source/draw.io/kvm-qemu添加内存.drawio","hash":"20888a5668bbd8a8e186d9186550e0406a690a5f","modified":1723200795491},{"_id":"themes/butterfly/source/draw.io/未命名绘图.drawio","hash":"7524effdb40f7f6adb5dbef69b5d010fd7f81e0b","modified":1723200795491},{"_id":"themes/butterfly/source/img/friend_404.gif","hash":"8d2d0ebef70a8eb07329f57e645889b0e420fa48","modified":1722946893318},{"_id":"themes/butterfly/source/js/main.js","hash":"0dac585446445e0c419b86eec5580bc9b0657dc6","modified":1722946893319},{"_id":"themes/butterfly/source/js/tw_cn.js","hash":"f8d2e3f31468991a7f5171cbfdb157dfb86d3372","modified":1722946893319},{"_id":"themes/butterfly/source/js/utils.js","hash":"8e6b48d294e7aeaba8ff6348c43b2271cf865547","modified":1722946893319},{"_id":"themes/butterfly/layout/includes/head/analytics.pug","hash":"67e1c3b48e4ca7ee0b2c76d3ca7476b9883cf105","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/head/Open_Graph.pug","hash":"8aa8d799aedbfd811195b84a451bc4b6e2647c12","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/head/config.pug","hash":"63fed4548367a3663cdbaffa1df48167b0a2397b","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/head/config_site.pug","hash":"7df90c8e432e33716517ab918b0a125bc284041b","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/head/pwa.pug","hash":"3d492cfe645d37c94d30512e0b230b0a09913148","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/head/google_adsense.pug","hash":"95a37e92b39c44bcbea4be7e29ddb3921c5b8220","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/head/preconnect.pug","hash":"5208fe1e75d97a05fd9bdd6cc53c59d8b741b94b","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/header/menu_item.pug","hash":"31346a210f4f9912c5b29f51d8f659913492f388","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/header/index.pug","hash":"944d6e9dd50df3395f3a2c7ad9db667d50dea4ed","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/head/site_verification.pug","hash":"e2e8d681f183f00ce5ee239c42d2e36b3744daad","modified":1722946893304},{"_id":"themes/butterfly/layout/includes/header/post-info.pug","hash":"f50e6a17073677933c5bc78481bf587a4a9e6da0","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/header/social.pug","hash":"5de9a82032cdad1db3b868b797460921cd775fc2","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/mixins/article-sort.pug","hash":"90554c2ca5ba946f4c02e1bc5fe2859cef1b1594","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/mixins/post-ui.pug","hash":"6f310ca7b392021632b987557607d5b6d18052bb","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/header/nav.pug","hash":"f61659aa457d1a2d1baa3a13157996cfac4d6609","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/loading/fullpage-loading.pug","hash":"9e8c5788602b29a527ef35fe8a20076a5fa969bd","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/page/categories.pug","hash":"5276a8d2835e05bd535fedc9f593a0ce8c3e8437","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/page/flink.pug","hash":"f9ce83978b217a71a2eb8761dc14b09866faa3f4","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/page/default-page.pug","hash":"12c65c174d26a41821df9bad26cdf1087ec5b0ca","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/page/tags.pug","hash":"9621991359e22b14049346f1cf87bdedc94edf5a","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/loading/pace.pug","hash":"6ab4e301c92586505d6cddce1b3ad23b7c79010d","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/loading/index.pug","hash":"131f344d68b4c241d6e03849b243ee792fcd3cea","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/post/reward.pug","hash":"a096ff8eb6b2a22395be881f827ff2a686ba5596","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/post/post-copyright.pug","hash":"5574804fdea5edf7fd52aad2caf030614d5e7f2f","modified":1722946893305},{"_id":"themes/butterfly/layout/includes/third-party/aplayer.pug","hash":"c7cfade2b160380432c47eef4cd62273b6508c58","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/third-party/pangu.pug","hash":"0f024e36b8116118233e10118714bde304e01e12","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/pjax.pug","hash":"12e57491e94fa00d953bbda9db0b6d6169e2358c","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/prismjs.pug","hash":"ffb9ea15a2b54423cd4cd441e2d061b8233e9b58","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/effect.pug","hash":"1d39670ee6225f85f5c53bf5c84f3fd6e19290e8","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/subtitle.pug","hash":"8044b9c18b34b019ffe26b7383e7e80356b5e4b5","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_ad.pug","hash":"60dc48a7b5d89c2a49123c3fc5893ab9c57dd225","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_announcement.pug","hash":"ae392459ad401a083ca51ee0b27526b3c1e1faed","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_author.pug","hash":"03c6afabbf1ac729c7fb21c7ec06da0190b0fdc7","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_archives.pug","hash":"86897010fe71503e239887fd8f6a4f5851737be9","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_bottom_self.pug","hash":"13dc8ce922e2e2332fe6ad5856ebb5dbf9ea4444","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_post_series.pug","hash":"bd5ad01277f8c6ddf8a3a29af1518e5fe6eed23f","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_categories.pug","hash":"d1a416d0a8a7916d0b1a41d73adc66f8c811e493","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_post_toc.pug","hash":"a658a274c5f7896ee5122725bee45548693bdd66","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_recent_post.pug","hash":"e5aac7b28ed4123d75797263c64e74ac547945bc","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_tags.pug","hash":"eceb4420a64c720f0d2741e89d6229bbb3d87353","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_top_self.pug","hash":"ae67c6d4130a6c075058a9c1faea1648bcc6f83e","modified":1722946893311},{"_id":"themes/butterfly/layout/includes/widget/index.pug","hash":"66f7a8b0cebc05c575ec3cb70b08d6854029d87a","modified":1722946893311},{"_id":"themes/butterfly/source/css/_global/function.styl","hash":"f19694a42dbe28eda4b39a1696e8fbcd277bc76c","modified":1722946893314},{"_id":"themes/butterfly/layout/includes/widget/card_newest_comment.pug","hash":"7834bf7c711e739fd33cfcd0b53d151013b3d449","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/widget/card_webinfo.pug","hash":"35ce167c5a275211bfc1fa3d49adfde5b404d98f","modified":1722946893311},{"_id":"themes/butterfly/source/css/_layout/aside.styl","hash":"94fc033276c34d264cabaeb52c82786440e773f4","modified":1722953748475},{"_id":"themes/butterfly/source/css/_highlight/highlight.styl","hash":"4dcd468e4d11a0ac75406162678feffcd89fee00","modified":1722946893314},{"_id":"themes/butterfly/source/css/_highlight/theme.styl","hash":"bcd384c8b2aa0390c9eb69ac1abbfd1240ce1da4","modified":1722946893315},{"_id":"themes/butterfly/source/css/_global/index.styl","hash":"c8ff6ddd5bfe1190b7b8056b68ce41114fd79dcb","modified":1722946893314},{"_id":"themes/butterfly/source/css/_layout/comments.styl","hash":"134811b2d696f9ed2c0cd578f3886f1c60770c0a","modified":1722946893315},{"_id":"themes/butterfly/source/css/_layout/chat.styl","hash":"f9a5d3f1fc5ed0ed2ee4c1eaa58ed650d11ddebd","modified":1722946893315},{"_id":"themes/butterfly/source/css/_layout/head.styl","hash":"18d08be0cd9b1f8c049d4b922e80f8163a55c947","modified":1722946893315},{"_id":"themes/butterfly/source/css/_layout/footer.styl","hash":"83a7a70eb0532ea9c4267939fe484af915fca01e","modified":1722946893315},{"_id":"themes/butterfly/source/css/_layout/pagination.styl","hash":"fb9f78bfbb79579f1d752cb73fb6d25c8418e0fd","modified":1722946893315},{"_id":"themes/butterfly/source/css/_layout/loading.styl","hash":"ac2aeee9926f75b2a0098efe1c114126987430f2","modified":1722946893315},{"_id":"themes/butterfly/source/css/_layout/post.styl","hash":"a2eb44fa5eaea1325319a2064439cf36d0f35a2f","modified":1722946893315},{"_id":"themes/butterfly/source/css/_layout/relatedposts.styl","hash":"d53de408cb27a2e704aba7f7402b7caebe0410d8","modified":1722946893315},{"_id":"themes/butterfly/source/css/_layout/reward.styl","hash":"d6cf26ffb8a0343eda1cde65b6b73b0ddbe8fcfc","modified":1722946893316},{"_id":"themes/butterfly/source/css/_layout/rightside.styl","hash":"f845b9b4efdee750f70c023aab27432611f83059","modified":1722946893316},{"_id":"themes/butterfly/source/css/_layout/sidebar.styl","hash":"b7a6a585dbc38d177c9aba75df3a467415d0488a","modified":1722946893316},{"_id":"themes/butterfly/source/css/_layout/third-party.styl","hash":"5556c9bf4f53a90cb9b4945cd76a8849bd67f3f3","modified":1722946893316},{"_id":"themes/butterfly/source/css/_mode/darkmode.styl","hash":"0db591a1f4ed5adcb8668a549bbee5c9d62682cf","modified":1722946893316},{"_id":"themes/butterfly/source/css/_mode/readmode.styl","hash":"e549d24ad81a7d93326a509ff8dcfcc58c80729e","modified":1722946893316},{"_id":"themes/butterfly/source/css/_page/404.styl","hash":"50dbb9e6d98c71ffe16741b8c1b0c1b9771efd2b","modified":1722946893316},{"_id":"themes/butterfly/source/css/_page/archives.styl","hash":"c9e98027f2dd730ce389c2047f62ebb748955fcf","modified":1722946893316},{"_id":"themes/butterfly/source/css/_page/categories.styl","hash":"f01ee74948cedb44e53cd3bb1ef36b7d2778ede7","modified":1722946893316},{"_id":"themes/butterfly/source/css/_page/common.styl","hash":"4e320e16d49bc18085045937681f7331a1e243ca","modified":1722946893316},{"_id":"themes/butterfly/source/css/_page/homepage.styl","hash":"d4ebc41b5c855dd75f47de7345d62f85ce7cf073","modified":1722946893316},{"_id":"themes/butterfly/source/css/_page/flink.styl","hash":"98d755b686ee833e9da10afaa40c4ec2bd66c19a","modified":1722946893316},{"_id":"themes/butterfly/source/css/_page/tags.styl","hash":"580feb7e8b0822a1be48ac380f8c5c53b1523321","modified":1722946893316},{"_id":"themes/butterfly/source/css/_search/index.styl","hash":"20a3134e1302b62bfc881f4ec43f398267111f22","modified":1722946893317},{"_id":"themes/butterfly/source/css/_tags/gallery.styl","hash":"5cddbb5f4eae695a26685e415d821b523e0f17bf","modified":1722946893317},{"_id":"themes/butterfly/source/css/_tags/button.styl","hash":"45f0c32bdea117540f6b14ebac6450d7142bd710","modified":1722946893317},{"_id":"themes/butterfly/source/css/_tags/hexo.styl","hash":"d76c38adf1d9c1279ef4241835667789f5b736e0","modified":1722946893317},{"_id":"themes/butterfly/source/css/_tags/inlineImg.styl","hash":"df9d405c33a9a68946b530410f64096bcb72560c","modified":1722946893317},{"_id":"themes/butterfly/source/css/_tags/tabs.styl","hash":"2d02e52b360f6e6cae47c293ae57ed78e2554663","modified":1722946893317},{"_id":"themes/butterfly/source/css/_tags/label.styl","hash":"66c59e193d794cdb02cca7bd1dc4aea5a19d7e84","modified":1722946893317},{"_id":"themes/butterfly/source/css/_tags/hide.styl","hash":"ce489ca2e249e2a3cf71584e20d84bdb022e3475","modified":1722946893317},{"_id":"themes/butterfly/source/css/_tags/note.styl","hash":"909bb5079b26b6ee68177919f522566503654058","modified":1722946893317},{"_id":"themes/butterfly/source/css/_tags/timeline.styl","hash":"f071156d439556e7463ed4bc61ceee87170d5d08","modified":1722946893318},{"_id":"themes/butterfly/source/css/_third-party/normalize.min.css","hash":"2c18a1c9604af475b4749def8f1959df88d8b276","modified":1722946893318},{"_id":"themes/butterfly/source/js/search/local-search.js","hash":"e1f60ebac53a3f596fd0a4769b4f9275c48c6542","modified":1722946893319},{"_id":"themes/butterfly/source/js/search/algolia.js","hash":"108988d046da9a4716148df43b3975217c8ceaae","modified":1722946893319},{"_id":"themes/butterfly/layout/includes/third-party/abcjs/abcjs.pug","hash":"f7299f9fef5bf94bb58c8cd3be8ee660ad2f9cd4","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/third-party/chat/crisp.pug","hash":"2fb098a7aa45010a8cd212dc0bd5308c6e7c63e3","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/abcjs/index.pug","hash":"f58f1648d2d71311bafca4833f20b605bb5f18c8","modified":1722946893306},{"_id":"themes/butterfly/source/css/_search/algolia.styl","hash":"649a054e73278b6724bd4dd9b94724791ec5c928","modified":1722946893317},{"_id":"themes/butterfly/layout/includes/third-party/chat/chatra.pug","hash":"ddce8352b371a1fb426bdb6c33f587eb37a69647","modified":1722946893307},{"_id":"themes/butterfly/source/css/_search/local-search.styl","hash":"961589da3c0a532c4709a4a4ea96bd579257f766","modified":1722946893317},{"_id":"themes/butterfly/layout/includes/third-party/chat/daovoice.pug","hash":"9b57a8e13de8fc51a5f550854e47164fd8ac1be8","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/chat/tidio.pug","hash":"dd61eca6e9a45f63e09bdefba89fe285a81ba096","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/chat/messenger.pug","hash":"e39a9c37adf4cb15a2ba3b2cc65542ffea88650d","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/chat/index.pug","hash":"618e1b7f9204049b07beb9e1363c844a78a9ace3","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/artalk.pug","hash":"71af0b679e00290b0854384368b3c7e9b3e5f26a","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/fb.pug","hash":"0344477a2cf38698318ead2681c63ac12f01586e","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/disqus.pug","hash":"c5f7081ca29db8cc80f808dfc29e36d5fa22fd7e","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/index.pug","hash":"b2d274db84ef22fbd6d5ea8f4404821898934209","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/remark42.pug","hash":"001e8be47854b891efe04013c240c38fed4185eb","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/twikoo.pug","hash":"56c028ba0ea8fac19f0125114d765dfc56ce2b48","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/waline.pug","hash":"3a5ccfc69bd8ccb4b8f3ce3502023f7914f2a022","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/valine.pug","hash":"39427e107230a10790972349c9dd4c4f31d55eb7","modified":1722946893306},{"_id":"themes/butterfly/layout/includes/third-party/comments/artalk.pug","hash":"f77f0fdeac2bc8a72f71a58f9b75aa39f0a108c8","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/comments/disqus.pug","hash":"62f16a602e57e5f7f7c5249dd37b42d436dc032a","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/comments/disqusjs.pug","hash":"3bc4c1b91568561f0491bdac65b75aa0bfd01f27","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/comments/giscus.pug","hash":"2d7b0b09678adba09481e3152e0b32962677f650","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/comments/index.pug","hash":"a9709905593d960954e2dd572f09f48a6c2b1ef7","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/comments/facebook_comments.pug","hash":"46aec6466959baec1c3d71a5dbc510fbeb00c91d","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/comments/gitalk.pug","hash":"0d378ee8a671982a46213a4bfb223b4f3409aea9","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/comments/js.pug","hash":"00ed91c52939b9675b316137f854d13684c895a6","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/comments/remark42.pug","hash":"f15699abb8c7a255aabad0222ae53eee387c66a3","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/comments/livere.pug","hash":"63cea2b5c8f7b59f5919379d61a2bb2ce8ed7623","modified":1722946893307},{"_id":"themes/butterfly/layout/includes/third-party/comments/twikoo.pug","hash":"5c29b5887e2e6cd81e1f13b32da53d9c139b788b","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/comments/valine.pug","hash":"46865e3f52096acb07d0212174b4e8751b123aea","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/comments/waline.pug","hash":"7aa443b4881448979b810864e206e58c9ed787e3","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/comments/utterances.pug","hash":"1995a654ba7ad62775a0a6e2922209cd1a85f2e3","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/math/index.pug","hash":"b8ae5fd7d74e1edcef21f5004fc96147e064d219","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/math/mathjax.pug","hash":"fc072ac839401174b5d3cf9acd3b694246c23a55","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/math/katex.pug","hash":"dfcbd9881be569ea420eff1a6b00e4f4dbe2138e","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/math/mermaid.pug","hash":"6b67982bb7a3713b5bffd6a23ba2810425c504d0","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/artalk.pug","hash":"53c190f2945d39b2d4c479e3bb1e6c6851d767c2","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/disqus-comment.pug","hash":"2609bc2656aaaa9b59e8d575e711776512a62192","modified":1722946893308},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/github-issues.pug","hash":"0f0b46d637a9a1b6ae35148923abecc80b866276","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/index.pug","hash":"4ec0642f2d5444acfab570a6f8c7868e7ff43fde","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/remark42.pug","hash":"de2c4d02b520dd49a0a59fc0f33295e5bbb2c624","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/twikoo-comment.pug","hash":"4104f96faa6040f111ebfb9a90eeb470857c3b86","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/valine.pug","hash":"1f9f51023e9e33081c2add2ca73643c0edc5e9d5","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/search/algolia.pug","hash":"9c3c109a12d2b6916e8b4965cca12f521510ead9","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/search/index.pug","hash":"a99a41334387ee9a46c6f8e8212331a29a10d159","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/search/docsearch.pug","hash":"b928be14d1b47a9fadb1bcc5f5072a7328752d4b","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/waline.pug","hash":"24804ab6da9727ed793655c1262fa3f1a9746f70","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/share/addtoany.pug","hash":"85c92f8a7e44d7cd1c86f089a05be438535e5362","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/search/local-search.pug","hash":"3335024ba91f55ccf3858571b7898f46881c455c","modified":1722946893309},{"_id":"themes/butterfly/layout/includes/third-party/share/share-js.pug","hash":"c7dd2b2ae9b23aa0a60fffd7df9e9f76ef52033e","modified":1722946893310},{"_id":"themes/butterfly/layout/includes/third-party/share/index.pug","hash":"3ba49cfe186e9ca05faf9f0d0113611ec47e9b38","modified":1722946893309},{"_id":"themes/butterfly/source/css/_highlight/highlight/diff.styl","hash":"cf1fae641c927621a4df1be5ca4a853b9b526e23","modified":1722946893314},{"_id":"themes/butterfly/source/css/_highlight/highlight/index.styl","hash":"18804c58239d95798fa86d0597f32d7f7dd30051","modified":1722946893315},{"_id":"themes/butterfly/source/css/_highlight/prismjs/index.styl","hash":"5dc2e0bcae9a54bfb9bdcc82d02ae5a3cf1ca97d","modified":1722946893315},{"_id":"themes/butterfly/source/css/_highlight/prismjs/diff.styl","hash":"5972c61f5125068cbe0af279a0c93a54847fdc3b","modified":1722946893315},{"_id":"themes/butterfly/source/css/_highlight/prismjs/line-number.styl","hash":"25914321762e30aacc610bc4dfb9de3e1cb556a3","modified":1722946893315},{"_id":"source/images/Workqueue/.$Workqueue结构体-1.drawio.svg.dtmp","hash":"2b27fee8b2315862ec090ef1bcec597276e65abb","modified":1723864542909},{"_id":"source/images/Workqueue/Workqueue结构体-1.drawio.svg","hash":"68245fd601cb92ec231baef2605f57ba916f473f","modified":1723812831261},{"_id":"public/content.json","hash":"796f97ea2cc246e7bdbb71b5ebcdc0becb0b3916","modified":1723898488497},{"_id":"public/2024/08/17/Cgroup/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/TLB/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/Smmu/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/Workqueue/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/Mmu/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/Net/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/Numa/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/PowerManage/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/ProcessSchedule/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/Gic/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/Memblock/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/Linux踩内存问题定位/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/DeviceTree/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/16/Ebuf/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/15/Virt/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/14/Tasklet/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/14/Timer/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/14/Ftrace/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/14/CpuTopology/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/14/NumaPerf/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/14/Perf/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/14/Proc-meminfo/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/14/Proc-pagemap/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/14/Security/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/13/StartUp/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/13/Sysrq/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/13/Vmcore/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/13/DeviceModel/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/13/GccTool/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/13/Mte/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/13/Kprobe/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/13/Ptrace/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/12/Pgtable/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/12/I2c Protocol/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/12/Prctl/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/10/TraceEvent/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/10/Kvm/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/10/HugeTLB/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/09/Rcu/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/09/Spinlock/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/2024/08/09/FileSystem/index.html","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/tags/index.html","hash":"e46486c78363e62bb7239e361f8d2c2ce361174d","modified":1723898488497},{"_id":"public/categories/index.html","hash":"2ad0466282582671e515163bc0c6c4ac9a9d27ce","modified":1723898488497},{"_id":"public/archives/index.html","hash":"81fb0a99edf52a2fbbb8470b1c791072aa60d745","modified":1723898488497},{"_id":"public/archives/page/2/index.html","hash":"4a09c231ecba46a2fe1fa7423815d5037e1bdac3","modified":1723898488497},{"_id":"public/archives/page/3/index.html","hash":"51177dd0982485ce595b04a9192b041a3e4edbf5","modified":1723898488497},{"_id":"public/archives/page/5/index.html","hash":"5c01819fdfdc34e688343d047ce74d5174f6f929","modified":1723898488497},{"_id":"public/archives/page/4/index.html","hash":"7aa09ea20baf59136ced42e5f05abd33a6fcee8c","modified":1723898488497},{"_id":"public/archives/2024/index.html","hash":"ec6745b7ce4d054a309be90dac2c456321632b7d","modified":1723898488497},{"_id":"public/archives/2024/page/2/index.html","hash":"c5d1de154aea98bb88d7d443ae3b9c845cc981f2","modified":1723898488497},{"_id":"public/archives/2024/page/3/index.html","hash":"3a2d8720b42256936c68789c9e62fa975c4f4772","modified":1723898488497},{"_id":"public/archives/2024/page/4/index.html","hash":"52c2db487195778dc6938a00474100b7a70eb864","modified":1723898488497},{"_id":"public/archives/2024/page/5/index.html","hash":"55e828bc61b1a7c42cb3689ea994faed46be459f","modified":1723898488497},{"_id":"public/archives/2024/08/index.html","hash":"5ec0758d3364dcde2b60ea77843af0c82fe319b8","modified":1723898488497},{"_id":"public/archives/2024/08/page/2/index.html","hash":"ca8ca7651ec060560b5f27269216a787a3887b7a","modified":1723898488497},{"_id":"public/archives/2024/08/page/3/index.html","hash":"8f0cfc78a86fec3d5aa400e167e3a4ac63014b23","modified":1723898488497},{"_id":"public/archives/2024/08/page/4/index.html","hash":"84b26b0fab7b89ccff7ea501b5c1db151921d13a","modified":1723898488497},{"_id":"public/archives/2024/08/page/5/index.html","hash":"2ccd62e2eee60ce3b050a981dc63c01f8e8fe634","modified":1723898488497},{"_id":"public/index.html","hash":"dabf8f1a4060c26998ea7607db5694176376f803","modified":1723898488497},{"_id":"public/page/2/index.html","hash":"b1fd417fd2fabe739e1aa71b8fa14dd9282e3928","modified":1723898488497},{"_id":"public/page/3/index.html","hash":"129864aa39f72b80068a60bc2d4bfac4c26d6fb0","modified":1723898488497},{"_id":"public/tags/Linux-Cgroup/index.html","hash":"dd43038f93ca1374abeb2cb8c46b28920fa45559","modified":1723898488497},{"_id":"public/tags/Linux-Driver/index.html","hash":"95bcf5d9424cebc4df1b602571e82f7682d90b06","modified":1723898488497},{"_id":"public/page/5/index.html","hash":"9f13af8f7d9dc0391f3ff8b61937e90d734db425","modified":1723898488497},{"_id":"public/page/4/index.html","hash":"40640da1d26808f60114bee59e2d85e1999a19a9","modified":1723898488497},{"_id":"public/tags/Linux-DeviceTree/index.html","hash":"c2133a09ebe7b8d6485472f386f18c9191ba9379","modified":1723898488497},{"_id":"public/tags/Linux-Ebuf/index.html","hash":"b38c89bfbdb78671d8a37d6becd856bdcb98d3d2","modified":1723898488497},{"_id":"public/tags/Linux-Trace/index.html","hash":"a6804bc843fdd144ecea7b97698d4f0013a6ef99","modified":1723898488497},{"_id":"public/tags/Gcc-Tool/index.html","hash":"6908b7767f509906a3af5da4d2af18b5dcbd3982","modified":1723898488497},{"_id":"public/tags/Gic/index.html","hash":"c071106c4fce3123a26eb721792de51d4de5b129","modified":1723898488497},{"_id":"public/tags/Aarch64/index.html","hash":"f46ee661a54568d5d70ae598fe030f7d77698858","modified":1723898488497},{"_id":"public/tags/Linux-File-System/index.html","hash":"1a3412a55dd99f6bc21bac380a30cf15f788c055","modified":1723898488497},{"_id":"public/tags/I2c-Protocol/index.html","hash":"0caef517d5fa328bf64d6ea25d6ede4edc66f6c0","modified":1723898488497},{"_id":"public/tags/Linux-Virt/index.html","hash":"6ecfb196c593769d3b72e97abb822a68ad09eaa9","modified":1723898488497},{"_id":"public/tags/Linux-MM/index.html","hash":"b4b77d6e6f5c15a6895081df610d61b818e670b7","modified":1723898488497},{"_id":"public/tags/Linux-Memblock/index.html","hash":"5504bb2cadf10e51f423ef745035b1557e12fb5c","modified":1723898488497},{"_id":"public/tags/Linux-Debug/index.html","hash":"08a4755c196c85efe1a53eb21c437c83576ea81c","modified":1723898488497},{"_id":"public/tags/Mte/index.html","hash":"f4f0d01ca2d30fa1e06a72fd75d291b586d2c936","modified":1723898488497},{"_id":"public/tags/Mmu/index.html","hash":"37dd5dc72f7373733c64e507763eab825ee81336","modified":1723898488497},{"_id":"public/tags/Linux-Net/index.html","hash":"6dcf7a9cc9944dd2603dd3078e630cf2d8c8cf38","modified":1723898488497},{"_id":"public/tags/Linux-Numa/index.html","hash":"b27e8f090e8af00b9fc5225732fe4f1e01ed9e52","modified":1723898488497},{"_id":"public/tags/Linux-Perf/index.html","hash":"efac25dce6e958233a43546fc0a5f62a452aad24","modified":1723898488497},{"_id":"public/tags/Pgtable/index.html","hash":"d84f4ca3a2db9c80b11b8031798f187029d26ed3","modified":1723898488497},{"_id":"public/tags/Linux-PowerManage/index.html","hash":"c8005f094f534a82ef3d8038e46de99b51198e25","modified":1723898488497},{"_id":"public/tags/Linux-Prctl/index.html","hash":"224066dd456a1fcf4dcd1b25ac40e4ee315dee9d","modified":1723898488497},{"_id":"public/tags/Linux-Process/index.html","hash":"e9a63ce7fbe227199b5472c78ed12b923fb4092e","modified":1723898488497},{"_id":"public/tags/Linux-Proc-pagemap/index.html","hash":"bdfd19b94071fdac16a81f96b5c0c80f10ec8241","modified":1723898488497},{"_id":"public/tags/Linux-Proc-meminfo/index.html","hash":"4597dc35bb0064920d8e7d25a53aa88409bf5e0f","modified":1723898488497},{"_id":"public/tags/Linux-Smmu/index.html","hash":"c922fa018c24f7d05527dc4e231a427df0d6d766","modified":1723898488497},{"_id":"public/tags/Linux-Security/index.html","hash":"694910bb23fb1531f9cddd8687ee25fa6b577c03","modified":1723898488497},{"_id":"public/tags/Linux-RCU/index.html","hash":"afea63b39086a23b01f7584d7a38f8e437bca6ce","modified":1723898488497},{"_id":"public/tags/Linux-Spinlock/index.html","hash":"06841fa01f4319188b7fbda869f4d7a265054d18","modified":1723898488497},{"_id":"public/tags/Linux-Sysrq/index.html","hash":"033c02bba3523e8b4654da43fc2a04167b1f4fdc","modified":1723898488497},{"_id":"public/tags/Linux-Tasklet/index.html","hash":"949b4d4aa4b42d18d5c89c305594414b5c6dcd1a","modified":1723898488497},{"_id":"public/tags/Linux-StartUp/index.html","hash":"f53de3130ad8491cdc7b19ccc4162e919f9c2db7","modified":1723898488497},{"_id":"public/tags/TLB/index.html","hash":"9e33a28526f2f153026e4c211c3083335f9ee3fd","modified":1723898488497},{"_id":"public/tags/Linux-Vmcore/index.html","hash":"ca314cec848477b75ec4a33816abe25a35617604","modified":1723898488497},{"_id":"public/tags/Linux-Timer/index.html","hash":"93f371d1e4ff6a41996dd0466b3106f0a451f2ba","modified":1723898488497},{"_id":"public/tags/Linux-Workqueue/index.html","hash":"262d274f82f9705b7b6790d7d7678bc0d1b1eb47","modified":1723898488497},{"_id":"public/categories/Linux/index.html","hash":"990c656390fdffbb0cfc4b91d723a4a019bcaa9f","modified":1723898488497},{"_id":"public/categories/Linux/page/4/index.html","hash":"efab0b3fd2d73eaff1f8907838e96d398f0d591b","modified":1723898488497},{"_id":"public/categories/Linux/page/2/index.html","hash":"53fea736a0c98463a1171eceb037b88829054256","modified":1723898488497},{"_id":"public/categories/Gcc-Tool/index.html","hash":"15938df6b7e1ef13ee21a6569f8e270e2cafe30a","modified":1723898488497},{"_id":"public/categories/Linux/page/3/index.html","hash":"f4372277dcd3dff2dbc3c3928938befb389b7cc4","modified":1723898488497},{"_id":"public/categories/Aarch64/index.html","hash":"6d64f226cddd9b42017452f3842a1ee674b2b4ac","modified":1723898488497},{"_id":"public/categories/I2C/index.html","hash":"4e2f296822fd8395ee206a24062c9617a89d6a95","modified":1723898488497},{"_id":"public/img/404.jpg","hash":"fb4489bc1d30c93d28f7332158c1c6c1416148de","modified":1723898488497},{"_id":"public/img/avatar.JPG","hash":"8f393cf35ca25ce834024337a3b9d82794089451","modified":1723898488497},{"_id":"public/img/favicon.png","hash":"3cf89864b4f6c9b532522a4d260a2e887971c92d","modified":1723898488497},{"_id":"public/img/avatar.png","hash":"0b36c77ba8f9b99336b07a059e45b7dbcbf5ebd9","modified":1723898488497},{"_id":"public/draw.io/USB结构体.drawio","hash":"5552c75ca2d5545f11ec44197af4437e0d92482c","modified":1723898488497},{"_id":"public/draw.io/test.txt","hash":"7d0a1e6a061b02ee7d07bf65462298f22eb0c770","modified":1723898488497},{"_id":"public/img/friend_404.gif","hash":"8d2d0ebef70a8eb07329f57e645889b0e420fa48","modified":1723898488497},{"_id":"public/draw.io/kvm-qemu添加内存.drawio","hash":"20888a5668bbd8a8e186d9186550e0406a690a5f","modified":1723898488497},{"_id":"public/draw.io/未命名绘图.drawio","hash":"7524effdb40f7f6adb5dbef69b5d010fd7f81e0b","modified":1723898488497},{"_id":"public/images/MMU/PTE-1.png","hash":"d78c464a3736bd135ad4eb8bc9b06dd047b1a91c","modified":1723898488497},{"_id":"public/images/MMU/MAIR_EL1-1.png","hash":"77d9f5557fed2f1dfc71f4e1d531b8ba14b6acfd","modified":1723898488497},{"_id":"public/images/MMU/PTE-2.png","hash":"a1cb1e4b7a084344a59f9eb4b1373de0a7ba98ab","modified":1723898488497},{"_id":"public/images/MMU/TTBR表示的地址范围.drawio.svg","hash":"9d7f8d8d8c91d8143e59ec8f7cd6b35e5cf18a94","modified":1723898488497},{"_id":"public/images/Spinlock/spinlock嵌套-1.svg","hash":"19c284b39227c12d06a2fa0611bc0da7733752b2","modified":1723898488497},{"_id":"public/images/MMU/TCR寄存器位图.png","hash":"e8aec1a1b950737e109eccc0ab5c27293cb48e3d","modified":1723898488497},{"_id":"public/css/index.css","hash":"e6d66ab7bbc382088c0ee9042093c37b1e18aaa5","modified":1723898488497},{"_id":"public/css/var.css","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1723898488497},{"_id":"public/js/main.js","hash":"0dac585446445e0c419b86eec5580bc9b0657dc6","modified":1723898488497},{"_id":"public/js/tw_cn.js","hash":"f8d2e3f31468991a7f5171cbfdb157dfb86d3372","modified":1723898488497},{"_id":"public/js/search/algolia.js","hash":"108988d046da9a4716148df43b3975217c8ceaae","modified":1723898488497},{"_id":"public/js/search/local-search.js","hash":"e1f60ebac53a3f596fd0a4769b4f9275c48c6542","modified":1723898488497},{"_id":"public/js/utils.js","hash":"8e6b48d294e7aeaba8ff6348c43b2271cf865547","modified":1723898488497},{"_id":"public/images/MMU/MAIR_EL1-2.png","hash":"7d693539760d0d81c1c5ca1aac265ee385daca02","modified":1723898488497},{"_id":"public/images/MMU/MAIR_EL1-3.png","hash":"25d932916e28d21cb8b0ade8d096cf37ec91acd9","modified":1723898488497},{"_id":"public/images/Workqueue/Workqueue结构体-1.drawio.svg","hash":"68245fd601cb92ec231baef2605f57ba916f473f","modified":1723898488497}],"Category":[{"name":"Linux","_id":"clzy4nfv50004qwq21w7igwdh"},{"name":"Gcc Tool","_id":"clzy4nfv8000mqwq2gvzq3hr1"},{"name":"Aarch64","_id":"clzy4nfv9000tqwq24xr26zdp"},{"name":"I2C","_id":"clzy4nfva0017qwq21ps1ang8"}],"Data":[],"Page":[{"title":"tags","date":"2024-08-10T10:56:20.000Z","type":"tags","_content":"","source":"tags/index.md","raw":"---\ntitle: tags\ndate: 2024-08-10 18:56:20\ntype: \"tags\"\n---\n","updated":"2024-08-10T10:57:11.739Z","path":"tags/index.html","comments":1,"layout":"page","_id":"clzy4nfv10000qwq26bia9e5x","content":"","cover":false,"excerpt":"","more":""},{"title":"categories","date":"2024-08-10T10:49:49.000Z","type":"categories","_content":"","source":"categories/index.md","raw":"---\ntitle: categories\ndate: 2024-08-10 18:49:49\ntype: \"categories\"\n---\n","updated":"2024-08-10T10:50:51.038Z","path":"categories/index.html","comments":1,"layout":"page","_id":"clzy4nfv40002qwq28zzvgh0m","content":"","cover":false,"excerpt":"","more":""}],"Post":[{"title":"Cgroup","_content":"\n{% plantuml %}\n Bob->Alice : hello\n{% endplantuml %}\n\n```plantuml\n@startuml\n class Example {\n - String name\n - int number \n \n +void getName()\n +void getNumber()\n +String toString()\n }\n@enduml\n```","source":"_posts/Cgroup.md","raw":"\n---\ntitle: Cgroup\ncategories: \n- Linux\ntags:\n- Linux Cgroup\n---\n\n{% plantuml %}\n Bob->Alice : hello\n{% endplantuml %}\n\n```plantuml\n@startuml\n class Example {\n - String name\n - int number \n \n +void getName()\n +void getNumber()\n +String toString()\n }\n@enduml\n```","slug":"Cgroup","published":1,"date":"2024-08-17T12:40:18.491Z","updated":"2024-08-17T12:44:45.288Z","_id":"clzy4nfv30001qwq28ysbewz7","comments":1,"layout":"post","photos":[],"content":"<img src=\"http://www.plantuml.com/plantuml/svg/SyfFqhLppCbCJbMmKiX8pSd91m00\">\n\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">@startuml</span><br><span class=\"line\"> class Example {</span><br><span class=\"line\"> - String name</span><br><span class=\"line\"> - int number </span><br><span class=\"line\"> </span><br><span class=\"line\"> +void getName()</span><br><span class=\"line\"> +void getNumber()</span><br><span class=\"line\"> +String toString()</span><br><span class=\"line\"> }</span><br><span class=\"line\">@enduml</span><br></pre></td></tr></table></figure>","cover":false,"excerpt":"","more":"<img src=\"http://www.plantuml.com/plantuml/svg/SyfFqhLppCbCJbMmKiX8pSd91m00\">\n\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">@startuml</span><br><span class=\"line\"> class Example {</span><br><span class=\"line\"> - String name</span><br><span class=\"line\"> - int number </span><br><span class=\"line\"> </span><br><span class=\"line\"> +void getName()</span><br><span class=\"line\"> +void getNumber()</span><br><span class=\"line\"> +String toString()</span><br><span class=\"line\"> }</span><br><span class=\"line\">@enduml</span><br></pre></td></tr></table></figure>"},{"title":"DeviceModel","_content":"\n\n","source":"_posts/DeviceModel.md","raw":"---\ntitle: DeviceModel\ncategories: \n- Linux\ntags:\n- Linux Driver\n---\n\n\n","slug":"DeviceModel","published":1,"date":"2024-08-13T13:15:23.309Z","updated":"2024-08-13T13:15:23.309Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv40003qwq275l30yxs","content":"","cover":false,"excerpt":"","more":""},{"title":"DeviceTree","_content":"\n## 编译与反编译命令\n1. 编译命令\ndtc -O dtb -o dest.dtb src.dts\n\n2. 反编译命令\ndtc -I dtb -O dts src.dtb > des.dts\n\n## 预留内存\n### reserved-memory方式\n1. 在reserve-memory区域添加要预留的内存。\n 下面就是在该区域添加了reserve:buffer@0区域。no-map表示该区域不要被映射进内核。预留后/proc/iomem也显示System RAM区域小于内存量。\n```c\nreserved-memory {\n #address-cells = <2>;\n #size-cells = <2>;\n ranges;\n reserved: buffer@0 {\n no-map;\n reg = <0x0 0x70000000 0x0 0x10000000>;\n };\n};\n```\n2. 在驱动dts节点添加引用\n```c\nreserved-driver@0 {\n compatible = \"xlnx,reserved-memory\";\n memory-region = <&reserved>;\n};\n```\n3. 在驱动代码中读驱动dts节点并使用\n```c\n/* Get reserved memory region from Device-tree */\nnp = of_parse_phandle(dev->of_node, \"memory-region\", 0);\nif (!np) {\n dev_err(dev, \"No %s specified\\n\", \"memory-region\");\n goto error1;\n}\n \nrc = of_address_to_resource(np, 0, &r);\nif (rc) {\n dev_err(dev, \"No memory address assigned to the region\\n\");\n goto error1;\n}\n \nlp->paddr = r.start;\nlp->vaddr = memremap(r.start, resource_size(&r), MEMREMAP_WB);\ndev_info(dev, \"Allocated reserved memory, vaddr: 0x%0llX, paddr: 0x%0llX\\n\", \n(u64)lp->vaddr, lp->paddr);\n```\n\n### 通过DMA API预留\n```c\nreserved-memory {\n #address-cells = <2>;\n #size-cells = <2>;\n ranges;\n \n reserved: buffer@0 {\n compatible = \"shared-dma-pool\";\n no-map;\n reg = <0x0 0x70000000 0x0 0x10000000>;\n };\n};\n \nreserved-driver@0 {\n compatible = \"xlnx,reserved-memory\";\n memory-region = <&reserved>;\n};\n```\n然后在驱动代码中使用dma接口申请。\n```c\n/* Initialize reserved memory resources */\nrc = of_reserved_mem_device_init(dev);\nif(rc) {\n dev_err(dev, \"Could not get reserved memory\\n\");\n goto error1;\n}\n \n/* Allocate memory */\ndma_set_coherent_mask(dev, 0xFFFFFFFF);\nlp->vaddr = dma_alloc_coherent(dev, ALLOC_SIZE, &lp->paddr, GFP_KERNEL);\ndev_info(dev, \"Allocated coherent memory, vaddr: 0x%0llX, paddr: 0x%0llX\\n\", \n(u64)lp->vaddr, lp->paddr);\n\n```\n\n\n### CMA内存预留\nCMA跟上面DMA API预留方式一致,但多了两个属性。\n需要的属性:\nreusable;\nlinux,cma-default\n```\nreserved-memory {\n #address-cells = <2>;\n #size-cells = <2>;\n ranges;\n \n reserved: buffer@0 {\n compatible = \"shared-dma-pool\";\n reusable;\n reg = <0x0 0x70000000 0x0 0x10000000>;\n linux,cma-default;\n };\n };\n```\n这样在设备启动的时候会显示:\n```\n[ 0.000000] Reserved memory: created CMA memory pool at 0x0000000070000000, size \n256 MiB\n[ 0.000000] Reserved memory: initialized node buffer@0, compatible id shared-dma-\npool\n```\n\n## simple-bus关键字\n","source":"_posts/DeviceTree.md","raw":"---\ntitle: DeviceTree\ncategories: \n- Linux\ntags:\n- Linux DeviceTree\n---\n\n## 编译与反编译命令\n1. 编译命令\ndtc -O dtb -o dest.dtb src.dts\n\n2. 反编译命令\ndtc -I dtb -O dts src.dtb > des.dts\n\n## 预留内存\n### reserved-memory方式\n1. 在reserve-memory区域添加要预留的内存。\n 下面就是在该区域添加了reserve:buffer@0区域。no-map表示该区域不要被映射进内核。预留后/proc/iomem也显示System RAM区域小于内存量。\n```c\nreserved-memory {\n #address-cells = <2>;\n #size-cells = <2>;\n ranges;\n reserved: buffer@0 {\n no-map;\n reg = <0x0 0x70000000 0x0 0x10000000>;\n };\n};\n```\n2. 在驱动dts节点添加引用\n```c\nreserved-driver@0 {\n compatible = \"xlnx,reserved-memory\";\n memory-region = <&reserved>;\n};\n```\n3. 在驱动代码中读驱动dts节点并使用\n```c\n/* Get reserved memory region from Device-tree */\nnp = of_parse_phandle(dev->of_node, \"memory-region\", 0);\nif (!np) {\n dev_err(dev, \"No %s specified\\n\", \"memory-region\");\n goto error1;\n}\n \nrc = of_address_to_resource(np, 0, &r);\nif (rc) {\n dev_err(dev, \"No memory address assigned to the region\\n\");\n goto error1;\n}\n \nlp->paddr = r.start;\nlp->vaddr = memremap(r.start, resource_size(&r), MEMREMAP_WB);\ndev_info(dev, \"Allocated reserved memory, vaddr: 0x%0llX, paddr: 0x%0llX\\n\", \n(u64)lp->vaddr, lp->paddr);\n```\n\n### 通过DMA API预留\n```c\nreserved-memory {\n #address-cells = <2>;\n #size-cells = <2>;\n ranges;\n \n reserved: buffer@0 {\n compatible = \"shared-dma-pool\";\n no-map;\n reg = <0x0 0x70000000 0x0 0x10000000>;\n };\n};\n \nreserved-driver@0 {\n compatible = \"xlnx,reserved-memory\";\n memory-region = <&reserved>;\n};\n```\n然后在驱动代码中使用dma接口申请。\n```c\n/* Initialize reserved memory resources */\nrc = of_reserved_mem_device_init(dev);\nif(rc) {\n dev_err(dev, \"Could not get reserved memory\\n\");\n goto error1;\n}\n \n/* Allocate memory */\ndma_set_coherent_mask(dev, 0xFFFFFFFF);\nlp->vaddr = dma_alloc_coherent(dev, ALLOC_SIZE, &lp->paddr, GFP_KERNEL);\ndev_info(dev, \"Allocated coherent memory, vaddr: 0x%0llX, paddr: 0x%0llX\\n\", \n(u64)lp->vaddr, lp->paddr);\n\n```\n\n\n### CMA内存预留\nCMA跟上面DMA API预留方式一致,但多了两个属性。\n需要的属性:\nreusable;\nlinux,cma-default\n```\nreserved-memory {\n #address-cells = <2>;\n #size-cells = <2>;\n ranges;\n \n reserved: buffer@0 {\n compatible = \"shared-dma-pool\";\n reusable;\n reg = <0x0 0x70000000 0x0 0x10000000>;\n linux,cma-default;\n };\n };\n```\n这样在设备启动的时候会显示:\n```\n[ 0.000000] Reserved memory: created CMA memory pool at 0x0000000070000000, size \n256 MiB\n[ 0.000000] Reserved memory: initialized node buffer@0, compatible id shared-dma-\npool\n```\n\n## simple-bus关键字\n","slug":"DeviceTree","published":1,"date":"2024-08-16T12:53:51.254Z","updated":"2024-08-16T12:53:51.254Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv60006qwq2g68adhqv","content":"<h2 id=\"编译与反编译命令\"><a href=\"#编译与反编译命令\" class=\"headerlink\" title=\"编译与反编译命令\"></a>编译与反编译命令</h2><ol>\n<li><p>编译命令<br>dtc -O dtb -o dest.dtb src.dts</p>\n</li>\n<li><p>反编译命令<br>dtc -I dtb -O dts src.dtb > des.dts</p>\n</li>\n</ol>\n<h2 id=\"预留内存\"><a href=\"#预留内存\" class=\"headerlink\" title=\"预留内存\"></a>预留内存</h2><h3 id=\"reserved-memory方式\"><a href=\"#reserved-memory方式\" class=\"headerlink\" title=\"reserved-memory方式\"></a>reserved-memory方式</h3><ol>\n<li>在reserve-memory区域添加要预留的内存。<br>下面就是在该区域添加了reserve:buffer@0区域。no-map表示该区域不要被映射进内核。预留后/proc/iomem也显示System RAM区域小于内存量。<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">reserved-memory {</span><br><span class=\"line\"> <span class=\"meta\">#address-cells = <span class=\"string\"><2></span>;</span></span><br><span class=\"line\"> <span class=\"meta\">#size-cells = <span class=\"string\"><2></span>;</span></span><br><span class=\"line\"> ranges;</span><br><span class=\"line\"> reserved: buffer@<span class=\"number\">0</span> {</span><br><span class=\"line\"> no-<span class=\"built_in\">map</span>;</span><br><span class=\"line\"> reg = <<span class=\"number\">0x0</span> <span class=\"number\">0x70000000</span> <span class=\"number\">0x0</span> <span class=\"number\">0x10000000</span>>;</span><br><span class=\"line\"> };</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure></li>\n<li>在驱动dts节点添加引用<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">reserved-driver@<span class=\"number\">0</span> {</span><br><span class=\"line\"> compatible = <span class=\"string\">"xlnx,reserved-memory"</span>;</span><br><span class=\"line\"> memory-region = <&reserved>;</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure></li>\n<li>在驱动代码中读驱动dts节点并使用<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* Get reserved memory region from Device-tree */</span></span><br><span class=\"line\">np = of_parse_phandle(dev->of_node, <span class=\"string\">"memory-region"</span>, <span class=\"number\">0</span>);</span><br><span class=\"line\"><span class=\"keyword\">if</span> (!np) {</span><br><span class=\"line\"> dev_err(dev, <span class=\"string\">"No %s specified\\n"</span>, <span class=\"string\">"memory-region"</span>);</span><br><span class=\"line\"> <span class=\"keyword\">goto</span> error1;</span><br><span class=\"line\">}</span><br><span class=\"line\"> </span><br><span class=\"line\">rc = of_address_to_resource(np, <span class=\"number\">0</span>, &r);</span><br><span class=\"line\"><span class=\"keyword\">if</span> (rc) {</span><br><span class=\"line\"> dev_err(dev, <span class=\"string\">"No memory address assigned to the region\\n"</span>);</span><br><span class=\"line\"> <span class=\"keyword\">goto</span> error1;</span><br><span class=\"line\">}</span><br><span class=\"line\"> </span><br><span class=\"line\">lp->paddr = r.start;</span><br><span class=\"line\">lp->vaddr = memremap(r.start, resource_size(&r), MEMREMAP_WB);</span><br><span class=\"line\">dev_info(dev, <span class=\"string\">"Allocated reserved memory, vaddr: 0x%0llX, paddr: 0x%0llX\\n"</span>, </span><br><span class=\"line\">(u64)lp->vaddr, lp->paddr);</span><br></pre></td></tr></table></figure></li>\n</ol>\n<h3 id=\"通过DMA-API预留\"><a href=\"#通过DMA-API预留\" class=\"headerlink\" title=\"通过DMA API预留\"></a>通过DMA API预留</h3><figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">reserved-memory {</span><br><span class=\"line\"> <span class=\"meta\">#address-cells = <span class=\"string\"><2></span>;</span></span><br><span class=\"line\"> <span class=\"meta\">#size-cells = <span class=\"string\"><2></span>;</span></span><br><span class=\"line\"> ranges;</span><br><span class=\"line\"> </span><br><span class=\"line\"> reserved: buffer@<span class=\"number\">0</span> {</span><br><span class=\"line\"> compatible = <span class=\"string\">"shared-dma-pool"</span>;</span><br><span class=\"line\"> no-<span class=\"built_in\">map</span>;</span><br><span class=\"line\"> reg = <<span class=\"number\">0x0</span> <span class=\"number\">0x70000000</span> <span class=\"number\">0x0</span> <span class=\"number\">0x10000000</span>>;</span><br><span class=\"line\"> };</span><br><span class=\"line\">};</span><br><span class=\"line\"> </span><br><span class=\"line\">reserved-driver@<span class=\"number\">0</span> {</span><br><span class=\"line\"> compatible = <span class=\"string\">"xlnx,reserved-memory"</span>;</span><br><span class=\"line\"> memory-region = <&reserved>;</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n<p>然后在驱动代码中使用dma接口申请。</p>\n<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* Initialize reserved memory resources */</span></span><br><span class=\"line\">rc = of_reserved_mem_device_init(dev);</span><br><span class=\"line\"><span class=\"keyword\">if</span>(rc) {</span><br><span class=\"line\"> dev_err(dev, <span class=\"string\">"Could not get reserved memory\\n"</span>);</span><br><span class=\"line\"> <span class=\"keyword\">goto</span> error1;</span><br><span class=\"line\">}</span><br><span class=\"line\"> </span><br><span class=\"line\"><span class=\"comment\">/* Allocate memory */</span></span><br><span class=\"line\">dma_set_coherent_mask(dev, <span class=\"number\">0xFFFFFFFF</span>);</span><br><span class=\"line\">lp->vaddr = dma_alloc_coherent(dev, ALLOC_SIZE, &lp->paddr, GFP_KERNEL);</span><br><span class=\"line\">dev_info(dev, <span class=\"string\">"Allocated coherent memory, vaddr: 0x%0llX, paddr: 0x%0llX\\n"</span>, </span><br><span class=\"line\">(u64)lp->vaddr, lp->paddr);</span><br><span class=\"line\"></span><br></pre></td></tr></table></figure>\n\n\n<h3 id=\"CMA内存预留\"><a href=\"#CMA内存预留\" class=\"headerlink\" title=\"CMA内存预留\"></a>CMA内存预留</h3><p>CMA跟上面DMA API预留方式一致,但多了两个属性。<br>需要的属性:<br>reusable;<br>linux,cma-default</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">reserved-memory {</span><br><span class=\"line\"> #address-cells = <2>;</span><br><span class=\"line\"> #size-cells = <2>;</span><br><span class=\"line\"> ranges;</span><br><span class=\"line\"> </span><br><span class=\"line\"> reserved: buffer@0 {</span><br><span class=\"line\"> compatible = "shared-dma-pool";</span><br><span class=\"line\"> reusable;</span><br><span class=\"line\"> reg = <0x0 0x70000000 0x0 0x10000000>;</span><br><span class=\"line\"> linux,cma-default;</span><br><span class=\"line\"> };</span><br><span class=\"line\"> };</span><br></pre></td></tr></table></figure>\n<p>这样在设备启动的时候会显示:</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">[ 0.000000] Reserved memory: created CMA memory pool at 0x0000000070000000, size </span><br><span class=\"line\">256 MiB</span><br><span class=\"line\">[ 0.000000] Reserved memory: initialized node buffer@0, compatible id shared-dma-</span><br><span class=\"line\">pool</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"simple-bus关键字\"><a href=\"#simple-bus关键字\" class=\"headerlink\" title=\"simple-bus关键字\"></a>simple-bus关键字</h2>","cover":false,"excerpt":"","more":"<h2 id=\"编译与反编译命令\"><a href=\"#编译与反编译命令\" class=\"headerlink\" title=\"编译与反编译命令\"></a>编译与反编译命令</h2><ol>\n<li><p>编译命令<br>dtc -O dtb -o dest.dtb src.dts</p>\n</li>\n<li><p>反编译命令<br>dtc -I dtb -O dts src.dtb > des.dts</p>\n</li>\n</ol>\n<h2 id=\"预留内存\"><a href=\"#预留内存\" class=\"headerlink\" title=\"预留内存\"></a>预留内存</h2><h3 id=\"reserved-memory方式\"><a href=\"#reserved-memory方式\" class=\"headerlink\" title=\"reserved-memory方式\"></a>reserved-memory方式</h3><ol>\n<li>在reserve-memory区域添加要预留的内存。<br>下面就是在该区域添加了reserve:buffer@0区域。no-map表示该区域不要被映射进内核。预留后/proc/iomem也显示System RAM区域小于内存量。<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">reserved-memory {</span><br><span class=\"line\"> <span class=\"meta\">#address-cells = <span class=\"string\"><2></span>;</span></span><br><span class=\"line\"> <span class=\"meta\">#size-cells = <span class=\"string\"><2></span>;</span></span><br><span class=\"line\"> ranges;</span><br><span class=\"line\"> reserved: buffer@<span class=\"number\">0</span> {</span><br><span class=\"line\"> no-<span class=\"built_in\">map</span>;</span><br><span class=\"line\"> reg = <<span class=\"number\">0x0</span> <span class=\"number\">0x70000000</span> <span class=\"number\">0x0</span> <span class=\"number\">0x10000000</span>>;</span><br><span class=\"line\"> };</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure></li>\n<li>在驱动dts节点添加引用<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">reserved-driver@<span class=\"number\">0</span> {</span><br><span class=\"line\"> compatible = <span class=\"string\">"xlnx,reserved-memory"</span>;</span><br><span class=\"line\"> memory-region = <&reserved>;</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure></li>\n<li>在驱动代码中读驱动dts节点并使用<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* Get reserved memory region from Device-tree */</span></span><br><span class=\"line\">np = of_parse_phandle(dev->of_node, <span class=\"string\">"memory-region"</span>, <span class=\"number\">0</span>);</span><br><span class=\"line\"><span class=\"keyword\">if</span> (!np) {</span><br><span class=\"line\"> dev_err(dev, <span class=\"string\">"No %s specified\\n"</span>, <span class=\"string\">"memory-region"</span>);</span><br><span class=\"line\"> <span class=\"keyword\">goto</span> error1;</span><br><span class=\"line\">}</span><br><span class=\"line\"> </span><br><span class=\"line\">rc = of_address_to_resource(np, <span class=\"number\">0</span>, &r);</span><br><span class=\"line\"><span class=\"keyword\">if</span> (rc) {</span><br><span class=\"line\"> dev_err(dev, <span class=\"string\">"No memory address assigned to the region\\n"</span>);</span><br><span class=\"line\"> <span class=\"keyword\">goto</span> error1;</span><br><span class=\"line\">}</span><br><span class=\"line\"> </span><br><span class=\"line\">lp->paddr = r.start;</span><br><span class=\"line\">lp->vaddr = memremap(r.start, resource_size(&r), MEMREMAP_WB);</span><br><span class=\"line\">dev_info(dev, <span class=\"string\">"Allocated reserved memory, vaddr: 0x%0llX, paddr: 0x%0llX\\n"</span>, </span><br><span class=\"line\">(u64)lp->vaddr, lp->paddr);</span><br></pre></td></tr></table></figure></li>\n</ol>\n<h3 id=\"通过DMA-API预留\"><a href=\"#通过DMA-API预留\" class=\"headerlink\" title=\"通过DMA API预留\"></a>通过DMA API预留</h3><figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">reserved-memory {</span><br><span class=\"line\"> <span class=\"meta\">#address-cells = <span class=\"string\"><2></span>;</span></span><br><span class=\"line\"> <span class=\"meta\">#size-cells = <span class=\"string\"><2></span>;</span></span><br><span class=\"line\"> ranges;</span><br><span class=\"line\"> </span><br><span class=\"line\"> reserved: buffer@<span class=\"number\">0</span> {</span><br><span class=\"line\"> compatible = <span class=\"string\">"shared-dma-pool"</span>;</span><br><span class=\"line\"> no-<span class=\"built_in\">map</span>;</span><br><span class=\"line\"> reg = <<span class=\"number\">0x0</span> <span class=\"number\">0x70000000</span> <span class=\"number\">0x0</span> <span class=\"number\">0x10000000</span>>;</span><br><span class=\"line\"> };</span><br><span class=\"line\">};</span><br><span class=\"line\"> </span><br><span class=\"line\">reserved-driver@<span class=\"number\">0</span> {</span><br><span class=\"line\"> compatible = <span class=\"string\">"xlnx,reserved-memory"</span>;</span><br><span class=\"line\"> memory-region = <&reserved>;</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n<p>然后在驱动代码中使用dma接口申请。</p>\n<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* Initialize reserved memory resources */</span></span><br><span class=\"line\">rc = of_reserved_mem_device_init(dev);</span><br><span class=\"line\"><span class=\"keyword\">if</span>(rc) {</span><br><span class=\"line\"> dev_err(dev, <span class=\"string\">"Could not get reserved memory\\n"</span>);</span><br><span class=\"line\"> <span class=\"keyword\">goto</span> error1;</span><br><span class=\"line\">}</span><br><span class=\"line\"> </span><br><span class=\"line\"><span class=\"comment\">/* Allocate memory */</span></span><br><span class=\"line\">dma_set_coherent_mask(dev, <span class=\"number\">0xFFFFFFFF</span>);</span><br><span class=\"line\">lp->vaddr = dma_alloc_coherent(dev, ALLOC_SIZE, &lp->paddr, GFP_KERNEL);</span><br><span class=\"line\">dev_info(dev, <span class=\"string\">"Allocated coherent memory, vaddr: 0x%0llX, paddr: 0x%0llX\\n"</span>, </span><br><span class=\"line\">(u64)lp->vaddr, lp->paddr);</span><br><span class=\"line\"></span><br></pre></td></tr></table></figure>\n\n\n<h3 id=\"CMA内存预留\"><a href=\"#CMA内存预留\" class=\"headerlink\" title=\"CMA内存预留\"></a>CMA内存预留</h3><p>CMA跟上面DMA API预留方式一致,但多了两个属性。<br>需要的属性:<br>reusable;<br>linux,cma-default</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">reserved-memory {</span><br><span class=\"line\"> #address-cells = <2>;</span><br><span class=\"line\"> #size-cells = <2>;</span><br><span class=\"line\"> ranges;</span><br><span class=\"line\"> </span><br><span class=\"line\"> reserved: buffer@0 {</span><br><span class=\"line\"> compatible = "shared-dma-pool";</span><br><span class=\"line\"> reusable;</span><br><span class=\"line\"> reg = <0x0 0x70000000 0x0 0x10000000>;</span><br><span class=\"line\"> linux,cma-default;</span><br><span class=\"line\"> };</span><br><span class=\"line\"> };</span><br></pre></td></tr></table></figure>\n<p>这样在设备启动的时候会显示:</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">[ 0.000000] Reserved memory: created CMA memory pool at 0x0000000070000000, size </span><br><span class=\"line\">256 MiB</span><br><span class=\"line\">[ 0.000000] Reserved memory: initialized node buffer@0, compatible id shared-dma-</span><br><span class=\"line\">pool</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"simple-bus关键字\"><a href=\"#simple-bus关键字\" class=\"headerlink\" title=\"simple-bus关键字\"></a>simple-bus关键字</h2>"},{"title":"Ebuf","_content":"","source":"_posts/Ebuf.md","raw":"---\ntitle: Ebuf\ncategories: \n- Linux\ntags:\n- Linux Ebuf\n---\n","slug":"Ebuf","published":1,"date":"2024-08-16T12:53:51.254Z","updated":"2024-08-16T12:53:51.254Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv60007qwq2bt90allp","content":"","cover":false,"excerpt":"","more":""},{"title":"Ftrace","_content":"\n## Ftrace原理\ngcc编译时添加-pg编译选项。这个编译选项在函数开始处添加-bl指令\n\n## Ftrace跟踪函数\n```bash\ncd /sys/kernel/debug/tracing/\necho 0 > tracing_on\necho 5 > max_graph_depth\necho function_graph > current_tracer\necho 1 > options/func_stack_trace\necho xxx > set_graph_function ## set_ftrace_filter这个只能打印本函数没法打印子函数等,而set_graph_function是可以打印子函数,而且可以看到函数是不是在执行过程中被中断切出去了\necho 0 > trace \necho 1 > tracing_on\n\n./a.out 执行完程序\necho 0 > tracing_on\ncat trace\n```\n\n### set_graph_function\nIf you want to trace only one function and all of its children,\nyou just have to echo its name into set_graph_function:\n\n\n## Trace-cmd\nhttps://man7.org/linux/man-pages/man1/trace-cmd-record.1.html\n使用trace-cmd record -e workqueue:workqueue_queue_work查看workqueue在执行时cpu 100%的问题\nhttps://community.frame.work/t/tracking-kworker-stuck-at-near-100-cpu-usage-with-ubuntu-22-04/23053?page=2\n\n## Trace Event\n\n### Trace Event添加\n\n### 应用\n\n## 参考\nhttps://docs.kernel.org/trace/tracepoints.html\nhttps://www.kernel.org/doc/Documentation/trace/ftrace.txt\nhttps://www.cnblogs.com/arnoldlu/p/7211249.html\n","source":"_posts/Ftrace.md","raw":"---\ntitle: Ftrace\ncategories: \n- Linux\ntags:\n- Linux Trace\n---\n\n## Ftrace原理\ngcc编译时添加-pg编译选项。这个编译选项在函数开始处添加-bl指令\n\n## Ftrace跟踪函数\n```bash\ncd /sys/kernel/debug/tracing/\necho 0 > tracing_on\necho 5 > max_graph_depth\necho function_graph > current_tracer\necho 1 > options/func_stack_trace\necho xxx > set_graph_function ## set_ftrace_filter这个只能打印本函数没法打印子函数等,而set_graph_function是可以打印子函数,而且可以看到函数是不是在执行过程中被中断切出去了\necho 0 > trace \necho 1 > tracing_on\n\n./a.out 执行完程序\necho 0 > tracing_on\ncat trace\n```\n\n### set_graph_function\nIf you want to trace only one function and all of its children,\nyou just have to echo its name into set_graph_function:\n\n\n## Trace-cmd\nhttps://man7.org/linux/man-pages/man1/trace-cmd-record.1.html\n使用trace-cmd record -e workqueue:workqueue_queue_work查看workqueue在执行时cpu 100%的问题\nhttps://community.frame.work/t/tracking-kworker-stuck-at-near-100-cpu-usage-with-ubuntu-22-04/23053?page=2\n\n## Trace Event\n\n### Trace Event添加\n\n### 应用\n\n## 参考\nhttps://docs.kernel.org/trace/tracepoints.html\nhttps://www.kernel.org/doc/Documentation/trace/ftrace.txt\nhttps://www.cnblogs.com/arnoldlu/p/7211249.html\n","slug":"Ftrace","published":1,"date":"2024-08-14T10:01:22.766Z","updated":"2024-08-14T10:01:22.766Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv60008qwq2a7oj7ofb","content":"<h2 id=\"Ftrace原理\"><a href=\"#Ftrace原理\" class=\"headerlink\" title=\"Ftrace原理\"></a>Ftrace原理</h2><p>gcc编译时添加-pg编译选项。这个编译选项在函数开始处添加-bl指令</p>\n<h2 id=\"Ftrace跟踪函数\"><a href=\"#Ftrace跟踪函数\" class=\"headerlink\" title=\"Ftrace跟踪函数\"></a>Ftrace跟踪函数</h2><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">cd</span> /sys/kernel/debug/tracing/</span><br><span class=\"line\"><span class=\"built_in\">echo</span> 0 > tracing_on</span><br><span class=\"line\"><span class=\"built_in\">echo</span> 5 > max_graph_depth</span><br><span class=\"line\"><span class=\"built_in\">echo</span> function_graph > current_tracer</span><br><span class=\"line\"><span class=\"built_in\">echo</span> 1 > options/func_stack_trace</span><br><span class=\"line\"><span class=\"built_in\">echo</span> xxx > set_graph_function <span class=\"comment\">## set_ftrace_filter这个只能打印本函数没法打印子函数等,而set_graph_function是可以打印子函数,而且可以看到函数是不是在执行过程中被中断切出去了</span></span><br><span class=\"line\"><span class=\"built_in\">echo</span> 0 > trace </span><br><span class=\"line\"><span class=\"built_in\">echo</span> 1 > tracing_on</span><br><span class=\"line\"></span><br><span class=\"line\">./a.out 执行完程序</span><br><span class=\"line\"><span class=\"built_in\">echo</span> 0 > tracing_on</span><br><span class=\"line\"><span class=\"built_in\">cat</span> trace</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"set-graph-function\"><a href=\"#set-graph-function\" class=\"headerlink\" title=\"set_graph_function\"></a>set_graph_function</h3><p>If you want to trace only one function and all of its children,<br>you just have to echo its name into set_graph_function:</p>\n<h2 id=\"Trace-cmd\"><a href=\"#Trace-cmd\" class=\"headerlink\" title=\"Trace-cmd\"></a>Trace-cmd</h2><p><a href=\"https://man7.org/linux/man-pages/man1/trace-cmd-record.1.html\">https://man7.org/linux/man-pages/man1/trace-cmd-record.1.html</a><br>使用trace-cmd record -e workqueue:workqueue_queue_work查看workqueue在执行时cpu 100%的问题<br><a href=\"https://community.frame.work/t/tracking-kworker-stuck-at-near-100-cpu-usage-with-ubuntu-22-04/23053?page=2\">https://community.frame.work/t/tracking-kworker-stuck-at-near-100-cpu-usage-with-ubuntu-22-04/23053?page=2</a></p>\n<h2 id=\"Trace-Event\"><a href=\"#Trace-Event\" class=\"headerlink\" title=\"Trace Event\"></a>Trace Event</h2><h3 id=\"Trace-Event添加\"><a href=\"#Trace-Event添加\" class=\"headerlink\" title=\"Trace Event添加\"></a>Trace Event添加</h3><h3 id=\"应用\"><a href=\"#应用\" class=\"headerlink\" title=\"应用\"></a>应用</h3><h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://docs.kernel.org/trace/tracepoints.html\">https://docs.kernel.org/trace/tracepoints.html</a><br><a href=\"https://www.kernel.org/doc/Documentation/trace/ftrace.txt\">https://www.kernel.org/doc/Documentation/trace/ftrace.txt</a><br><a href=\"https://www.cnblogs.com/arnoldlu/p/7211249.html\">https://www.cnblogs.com/arnoldlu/p/7211249.html</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"Ftrace原理\"><a href=\"#Ftrace原理\" class=\"headerlink\" title=\"Ftrace原理\"></a>Ftrace原理</h2><p>gcc编译时添加-pg编译选项。这个编译选项在函数开始处添加-bl指令</p>\n<h2 id=\"Ftrace跟踪函数\"><a href=\"#Ftrace跟踪函数\" class=\"headerlink\" title=\"Ftrace跟踪函数\"></a>Ftrace跟踪函数</h2><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">cd</span> /sys/kernel/debug/tracing/</span><br><span class=\"line\"><span class=\"built_in\">echo</span> 0 > tracing_on</span><br><span class=\"line\"><span class=\"built_in\">echo</span> 5 > max_graph_depth</span><br><span class=\"line\"><span class=\"built_in\">echo</span> function_graph > current_tracer</span><br><span class=\"line\"><span class=\"built_in\">echo</span> 1 > options/func_stack_trace</span><br><span class=\"line\"><span class=\"built_in\">echo</span> xxx > set_graph_function <span class=\"comment\">## set_ftrace_filter这个只能打印本函数没法打印子函数等,而set_graph_function是可以打印子函数,而且可以看到函数是不是在执行过程中被中断切出去了</span></span><br><span class=\"line\"><span class=\"built_in\">echo</span> 0 > trace </span><br><span class=\"line\"><span class=\"built_in\">echo</span> 1 > tracing_on</span><br><span class=\"line\"></span><br><span class=\"line\">./a.out 执行完程序</span><br><span class=\"line\"><span class=\"built_in\">echo</span> 0 > tracing_on</span><br><span class=\"line\"><span class=\"built_in\">cat</span> trace</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"set-graph-function\"><a href=\"#set-graph-function\" class=\"headerlink\" title=\"set_graph_function\"></a>set_graph_function</h3><p>If you want to trace only one function and all of its children,<br>you just have to echo its name into set_graph_function:</p>\n<h2 id=\"Trace-cmd\"><a href=\"#Trace-cmd\" class=\"headerlink\" title=\"Trace-cmd\"></a>Trace-cmd</h2><p><a href=\"https://man7.org/linux/man-pages/man1/trace-cmd-record.1.html\">https://man7.org/linux/man-pages/man1/trace-cmd-record.1.html</a><br>使用trace-cmd record -e workqueue:workqueue_queue_work查看workqueue在执行时cpu 100%的问题<br><a href=\"https://community.frame.work/t/tracking-kworker-stuck-at-near-100-cpu-usage-with-ubuntu-22-04/23053?page=2\">https://community.frame.work/t/tracking-kworker-stuck-at-near-100-cpu-usage-with-ubuntu-22-04/23053?page=2</a></p>\n<h2 id=\"Trace-Event\"><a href=\"#Trace-Event\" class=\"headerlink\" title=\"Trace Event\"></a>Trace Event</h2><h3 id=\"Trace-Event添加\"><a href=\"#Trace-Event添加\" class=\"headerlink\" title=\"Trace Event添加\"></a>Trace Event添加</h3><h3 id=\"应用\"><a href=\"#应用\" class=\"headerlink\" title=\"应用\"></a>应用</h3><h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://docs.kernel.org/trace/tracepoints.html\">https://docs.kernel.org/trace/tracepoints.html</a><br><a href=\"https://www.kernel.org/doc/Documentation/trace/ftrace.txt\">https://www.kernel.org/doc/Documentation/trace/ftrace.txt</a><br><a href=\"https://www.cnblogs.com/arnoldlu/p/7211249.html\">https://www.cnblogs.com/arnoldlu/p/7211249.html</a></p>\n"},{"title":"Gcc Tool","_content":"## Summary\nar, nm, objdump, addr2line\n\n## ar\n库文件的操作指令\n经常用法:\n\n```bash\nar -t libname.a // 显示所有对象文件(.o文件)的列表.例: # ar t libtest.a\nlibtest1.o\nlibtest2.o\nar -rv libname.a objfile1.o objfile2.o ... objfilen.o // 把objfile1.o--objfilen.o打包成一个库文件\n```\n\nar -help打印:\n- d:从库中删除模块。按模块原来的文件名指定要删除的模块。如果使用了任选项v则列出被删除的每个模块。\n- m:该操作是在一个库中移动成员。当库中如果有若干模块有相同的符号定义(如函数定义),则成员的位置顺序很重要。如果没有指定任选项,任何指定的成员将移到库的最后。也可以使用'a','b',或'I'任选项移动到指定的位置。\n- p:显示库中指定的成员到标准输出。如果指定任选项v,则在输出成员的内容前,将显示成员的名字。如果没有指定成员的名字,所有库中的文件将显示出来。\n- q:快速追加。增加新模块到库的结尾处。并不检查是否需要替换。'a','b',或'I'任选项对此操作没有影响,模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。 这时,库的符号表没有更新,可以用'ar s'或ranlib来更新库的符号表索引。\n- r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。\n- t:显示库的模块表清单。一般只显示模块名。\n- x:从库中提取一个成员。如果不指定要提取的模块,则提取库中所有的模块。\n\n下面在看看可与操作选项结合使用的任选项:\n- a:在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a,则应该为命令行中membername参数指定一个已经存在的成员名。\n- b:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项b,则应该为命令行中membername参数指定一个已经存在的成员名。\n- c:创建一个库。不管库是否存在,都将创建。\n- f:在库中截短指定的名字。缺省情况下,文件名的长度是不受限制的,可以使用此参数将文件名截短,以保证与其它系统的兼容。\n- i:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项i,则应该为命令行中membername参数指定一个已经存在的成员名(类似任选项b)。\n- l:暂未使用\n- N:与count参数一起使用,在库中有多个相同的文件名时指定提取或输出的个数。\n- o:当提取成员时,保留成员的原始数据。如果不指定该任选项,则提取出的模块的时间将标为提取出的时间。\n- P:进行文件名匹配时使用全路径名。ar在创建库时不能使用全路径名(这样的库文件不符合POSIX标准),但是有些工具可以。\n- s:写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。甚至对于没有任何变化的库也作该动作。对一个库做ar s等同于对该库做ranlib。\n- S:不创建目标文件索引,这在创建较大的库时能加快时间。\n- u:一般说来,命令ar r...插入所有列出的文件到库中,如果你只想插入列出文件中那些比库中同名文件新的文件,就可以使用该任选项。该任选项只用于r操作选项。\n- v:该选项用来显示执行操作选项的附加信息。\n- V:显示ar的版本.\n\n## nm\n列出目标文件的符号清单\n```bash\nnm -s filename.a或者filename.o或者filename.out \n```\n\nnm -help打印\n\n- -a或--debug-syms:显示调试符号。\n- -B:等同于--format=bsd,用来兼容MIPS的nm。\n- -C或--demangle:将低级符号名解码(demangle)成用户级名字。这样可以使得C++函数名具有可读性。\n- -D或--dynamic:显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。\n- -f format:使用format格式输出。format可以选取bsd、sysv或posix,该选项在GNU的nm中有用。默认为bsd。\n- -g或--extern-only:仅显示外部符号。\n- -n、-v或--numeric-sort:按符号对应地址的顺序排序,而非按符号名的字符顺序。\n- -p或--no-sort:按目标文件中遇到的符号顺序显示,不排序。\n- -P或--portability:使用POSIX.2标准输出格式代替默认的输出格式。等同于使用任选项-f posix。\n- -s或--print-armap:当列出库中成员的符号时,包含索引。索引的内容包含:哪些模块包含哪些名字的映射。\n- -r或--reverse-sort:反转排序的顺序(例如,升序变为降序)。\n- --size-sort:按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。\n- -t radix或--radix=radix:使用radix进制显示符号值。radix只能为\"d\"表示十进制、\"o\"表示八进制或\"x\"表示十六进制。\n- --target=bfdname:指定一个目标代码的格式,而非使用系统的默认格式。\n- -u或--undefined-only:仅显示没有定义的符号(那些外部符号)。\n- -l或--line-numbers:对每个符号,使用调试信息来试图找到文件名和行号。对于已定义的符号,查找符号地址的行号。对于未定义符号,查找指向符号重定位入口的行号。如果可以找到行号信息,显示在符号信息之后。\n- -V或--version:显示nm的版本号。\n- --help:显示nm的任选项。\n\n## objdump\n常用命令:\n1. objdump -h file<.o,.a,.out> // 查看对象文件所有的节sections.例如\n #objdump -h libtest1.o\n```bash\n libtest1.o: file format elf32-i386\n Sections:\n Idx Name Size VMA LMA File off Algn\n 0 .text 00000014 00000000 00000000 00000034 2**2\n CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE\n 1 .data 00000000 00000000 00000000 00000048 2**2\n CONTENTS, ALLOC, LOAD, DATA\n 2 .bss 00000000 00000000 00000000 00000048 2**2\n ALLOC\n 3 .rodata 0000000e 00000000 00000000 00000048 2**0\n CONTENTS, ALLOC, LOAD, READONLY, DATA\n 4 .comment 0000001f 00000000 00000000 00000056 2**0\n CONTENTS, READONLY\n 5 .note.GNU-stack 00000000 00000000 00000000 00000075 2**0\n CONTENTS, READONLY\n```\n2. objdump -t 查看对象文件所有的符号列表,相当于 nm -s objfilename,如:\n#objdump -t libtest1.o\n```bash\n libtest1.o: file format elf32-i386\n \n SYMBOL TABLE:\n 00000000 l df *ABS* 00000000 libtest1.c\n 00000000 l d .text 00000000 .text\n 00000000 l d .data 00000000 .data\n 00000000 l d .bss 00000000 .bss\n 00000000 l d .rodata 00000000 .rodata\n 00000000 l d .note.GNU-stack 00000000 .note.GNU-stack\n 00000000 l d .comment 00000000 .comment\n 00000000 g F .text 00000014 print_test1\n 00000000 *UND* 00000000 puts\n```\n\n## addr2line\n将可执行文件反汇编并打印对应文件的行号。\n\n### 内核模块\n查看oops打印,看到挂死在xxx模块中,函数是func_xxx,偏移是0x100/0x200。\n我们可以按照如下方法打印具体的行号。\n1. 反汇编\n aarch64-linux-gnu-objdump -D xxx.o > out.txt\n 在out.txt中找到func_xxx的开始地址。假设开始地址是0x800。\n2. 计算挂死的地址\n 0x800 + 0x100 = 0x900。0x800是函数开始地址,0x100是偏移\n3. 打印\n aarch64-linux-gnu-addr2line -i -C -f -e xxx.o **900**\n### 内核\n跟上面一样,只需要将xxx.o文件替换成vmlinux就可以了。\n\n## 参考\n\nhttps://blog.csdn.net/longbei9029/article/details/76397089\n","source":"_posts/GccTool.md","raw":"---\ntitle: Gcc Tool\ncategories: \n- Gcc Tool\ntags:\n- Gcc Tool\n---\n## Summary\nar, nm, objdump, addr2line\n\n## ar\n库文件的操作指令\n经常用法:\n\n```bash\nar -t libname.a // 显示所有对象文件(.o文件)的列表.例: # ar t libtest.a\nlibtest1.o\nlibtest2.o\nar -rv libname.a objfile1.o objfile2.o ... objfilen.o // 把objfile1.o--objfilen.o打包成一个库文件\n```\n\nar -help打印:\n- d:从库中删除模块。按模块原来的文件名指定要删除的模块。如果使用了任选项v则列出被删除的每个模块。\n- m:该操作是在一个库中移动成员。当库中如果有若干模块有相同的符号定义(如函数定义),则成员的位置顺序很重要。如果没有指定任选项,任何指定的成员将移到库的最后。也可以使用'a','b',或'I'任选项移动到指定的位置。\n- p:显示库中指定的成员到标准输出。如果指定任选项v,则在输出成员的内容前,将显示成员的名字。如果没有指定成员的名字,所有库中的文件将显示出来。\n- q:快速追加。增加新模块到库的结尾处。并不检查是否需要替换。'a','b',或'I'任选项对此操作没有影响,模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。 这时,库的符号表没有更新,可以用'ar s'或ranlib来更新库的符号表索引。\n- r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。\n- t:显示库的模块表清单。一般只显示模块名。\n- x:从库中提取一个成员。如果不指定要提取的模块,则提取库中所有的模块。\n\n下面在看看可与操作选项结合使用的任选项:\n- a:在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a,则应该为命令行中membername参数指定一个已经存在的成员名。\n- b:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项b,则应该为命令行中membername参数指定一个已经存在的成员名。\n- c:创建一个库。不管库是否存在,都将创建。\n- f:在库中截短指定的名字。缺省情况下,文件名的长度是不受限制的,可以使用此参数将文件名截短,以保证与其它系统的兼容。\n- i:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项i,则应该为命令行中membername参数指定一个已经存在的成员名(类似任选项b)。\n- l:暂未使用\n- N:与count参数一起使用,在库中有多个相同的文件名时指定提取或输出的个数。\n- o:当提取成员时,保留成员的原始数据。如果不指定该任选项,则提取出的模块的时间将标为提取出的时间。\n- P:进行文件名匹配时使用全路径名。ar在创建库时不能使用全路径名(这样的库文件不符合POSIX标准),但是有些工具可以。\n- s:写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。甚至对于没有任何变化的库也作该动作。对一个库做ar s等同于对该库做ranlib。\n- S:不创建目标文件索引,这在创建较大的库时能加快时间。\n- u:一般说来,命令ar r...插入所有列出的文件到库中,如果你只想插入列出文件中那些比库中同名文件新的文件,就可以使用该任选项。该任选项只用于r操作选项。\n- v:该选项用来显示执行操作选项的附加信息。\n- V:显示ar的版本.\n\n## nm\n列出目标文件的符号清单\n```bash\nnm -s filename.a或者filename.o或者filename.out \n```\n\nnm -help打印\n\n- -a或--debug-syms:显示调试符号。\n- -B:等同于--format=bsd,用来兼容MIPS的nm。\n- -C或--demangle:将低级符号名解码(demangle)成用户级名字。这样可以使得C++函数名具有可读性。\n- -D或--dynamic:显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。\n- -f format:使用format格式输出。format可以选取bsd、sysv或posix,该选项在GNU的nm中有用。默认为bsd。\n- -g或--extern-only:仅显示外部符号。\n- -n、-v或--numeric-sort:按符号对应地址的顺序排序,而非按符号名的字符顺序。\n- -p或--no-sort:按目标文件中遇到的符号顺序显示,不排序。\n- -P或--portability:使用POSIX.2标准输出格式代替默认的输出格式。等同于使用任选项-f posix。\n- -s或--print-armap:当列出库中成员的符号时,包含索引。索引的内容包含:哪些模块包含哪些名字的映射。\n- -r或--reverse-sort:反转排序的顺序(例如,升序变为降序)。\n- --size-sort:按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。\n- -t radix或--radix=radix:使用radix进制显示符号值。radix只能为\"d\"表示十进制、\"o\"表示八进制或\"x\"表示十六进制。\n- --target=bfdname:指定一个目标代码的格式,而非使用系统的默认格式。\n- -u或--undefined-only:仅显示没有定义的符号(那些外部符号)。\n- -l或--line-numbers:对每个符号,使用调试信息来试图找到文件名和行号。对于已定义的符号,查找符号地址的行号。对于未定义符号,查找指向符号重定位入口的行号。如果可以找到行号信息,显示在符号信息之后。\n- -V或--version:显示nm的版本号。\n- --help:显示nm的任选项。\n\n## objdump\n常用命令:\n1. objdump -h file<.o,.a,.out> // 查看对象文件所有的节sections.例如\n #objdump -h libtest1.o\n```bash\n libtest1.o: file format elf32-i386\n Sections:\n Idx Name Size VMA LMA File off Algn\n 0 .text 00000014 00000000 00000000 00000034 2**2\n CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE\n 1 .data 00000000 00000000 00000000 00000048 2**2\n CONTENTS, ALLOC, LOAD, DATA\n 2 .bss 00000000 00000000 00000000 00000048 2**2\n ALLOC\n 3 .rodata 0000000e 00000000 00000000 00000048 2**0\n CONTENTS, ALLOC, LOAD, READONLY, DATA\n 4 .comment 0000001f 00000000 00000000 00000056 2**0\n CONTENTS, READONLY\n 5 .note.GNU-stack 00000000 00000000 00000000 00000075 2**0\n CONTENTS, READONLY\n```\n2. objdump -t 查看对象文件所有的符号列表,相当于 nm -s objfilename,如:\n#objdump -t libtest1.o\n```bash\n libtest1.o: file format elf32-i386\n \n SYMBOL TABLE:\n 00000000 l df *ABS* 00000000 libtest1.c\n 00000000 l d .text 00000000 .text\n 00000000 l d .data 00000000 .data\n 00000000 l d .bss 00000000 .bss\n 00000000 l d .rodata 00000000 .rodata\n 00000000 l d .note.GNU-stack 00000000 .note.GNU-stack\n 00000000 l d .comment 00000000 .comment\n 00000000 g F .text 00000014 print_test1\n 00000000 *UND* 00000000 puts\n```\n\n## addr2line\n将可执行文件反汇编并打印对应文件的行号。\n\n### 内核模块\n查看oops打印,看到挂死在xxx模块中,函数是func_xxx,偏移是0x100/0x200。\n我们可以按照如下方法打印具体的行号。\n1. 反汇编\n aarch64-linux-gnu-objdump -D xxx.o > out.txt\n 在out.txt中找到func_xxx的开始地址。假设开始地址是0x800。\n2. 计算挂死的地址\n 0x800 + 0x100 = 0x900。0x800是函数开始地址,0x100是偏移\n3. 打印\n aarch64-linux-gnu-addr2line -i -C -f -e xxx.o **900**\n### 内核\n跟上面一样,只需要将xxx.o文件替换成vmlinux就可以了。\n\n## 参考\n\nhttps://blog.csdn.net/longbei9029/article/details/76397089\n","slug":"GccTool","published":1,"date":"2024-08-13T13:15:23.309Z","updated":"2024-08-13T13:15:23.309Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv7000cqwq2626mbjkl","content":"<h2 id=\"Summary\"><a href=\"#Summary\" class=\"headerlink\" title=\"Summary\"></a>Summary</h2><p>ar, nm, objdump, addr2line</p>\n<h2 id=\"ar\"><a href=\"#ar\" class=\"headerlink\" title=\"ar\"></a>ar</h2><p>库文件的操作指令<br>经常用法:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">ar -t libname.a // 显示所有对象文件(.o文件)的列表.例: <span class=\"comment\"># ar t libtest.a</span></span><br><span class=\"line\">libtest1.o</span><br><span class=\"line\">libtest2.o</span><br><span class=\"line\">ar -rv libname.a objfile1.o objfile2.o ... objfilen.o // 把objfile1.o--objfilen.o打包成一个库文件</span><br></pre></td></tr></table></figure>\n\n<p>ar -help打印:</p>\n<ul>\n<li>d:从库中删除模块。按模块原来的文件名指定要删除的模块。如果使用了任选项v则列出被删除的每个模块。</li>\n<li>m:该操作是在一个库中移动成员。当库中如果有若干模块有相同的符号定义(如函数定义),则成员的位置顺序很重要。如果没有指定任选项,任何指定的成员将移到库的最后。也可以使用’a’,’b’,或’I’任选项移动到指定的位置。</li>\n<li>p:显示库中指定的成员到标准输出。如果指定任选项v,则在输出成员的内容前,将显示成员的名字。如果没有指定成员的名字,所有库中的文件将显示出来。</li>\n<li>q:快速追加。增加新模块到库的结尾处。并不检查是否需要替换。’a’,’b’,或’I’任选项对此操作没有影响,模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。 这时,库的符号表没有更新,可以用’ar s’或ranlib来更新库的符号表索引。</li>\n<li>r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。</li>\n<li>t:显示库的模块表清单。一般只显示模块名。</li>\n<li>x:从库中提取一个成员。如果不指定要提取的模块,则提取库中所有的模块。</li>\n</ul>\n<p>下面在看看可与操作选项结合使用的任选项:</p>\n<ul>\n<li>a:在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a,则应该为命令行中membername参数指定一个已经存在的成员名。</li>\n<li>b:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项b,则应该为命令行中membername参数指定一个已经存在的成员名。</li>\n<li>c:创建一个库。不管库是否存在,都将创建。</li>\n<li>f:在库中截短指定的名字。缺省情况下,文件名的长度是不受限制的,可以使用此参数将文件名截短,以保证与其它系统的兼容。</li>\n<li>i:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项i,则应该为命令行中membername参数指定一个已经存在的成员名(类似任选项b)。</li>\n<li>l:暂未使用</li>\n<li>N:与count参数一起使用,在库中有多个相同的文件名时指定提取或输出的个数。</li>\n<li>o:当提取成员时,保留成员的原始数据。如果不指定该任选项,则提取出的模块的时间将标为提取出的时间。</li>\n<li>P:进行文件名匹配时使用全路径名。ar在创建库时不能使用全路径名(这样的库文件不符合POSIX标准),但是有些工具可以。</li>\n<li>s:写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。甚至对于没有任何变化的库也作该动作。对一个库做ar s等同于对该库做ranlib。</li>\n<li>S:不创建目标文件索引,这在创建较大的库时能加快时间。</li>\n<li>u:一般说来,命令ar r…插入所有列出的文件到库中,如果你只想插入列出文件中那些比库中同名文件新的文件,就可以使用该任选项。该任选项只用于r操作选项。</li>\n<li>v:该选项用来显示执行操作选项的附加信息。</li>\n<li>V:显示ar的版本.</li>\n</ul>\n<h2 id=\"nm\"><a href=\"#nm\" class=\"headerlink\" title=\"nm\"></a>nm</h2><p>列出目标文件的符号清单</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">nm -s filename.a或者filename.o或者filename.out </span><br></pre></td></tr></table></figure>\n\n<p>nm -help打印</p>\n<ul>\n<li>-a或–debug-syms:显示调试符号。</li>\n<li>-B:等同于–format=bsd,用来兼容MIPS的nm。</li>\n<li>-C或–demangle:将低级符号名解码(demangle)成用户级名字。这样可以使得C++函数名具有可读性。</li>\n<li>-D或–dynamic:显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。</li>\n<li>-f format:使用format格式输出。format可以选取bsd、sysv或posix,该选项在GNU的nm中有用。默认为bsd。</li>\n<li>-g或–extern-only:仅显示外部符号。</li>\n<li>-n、-v或–numeric-sort:按符号对应地址的顺序排序,而非按符号名的字符顺序。</li>\n<li>-p或–no-sort:按目标文件中遇到的符号顺序显示,不排序。</li>\n<li>-P或–portability:使用POSIX.2标准输出格式代替默认的输出格式。等同于使用任选项-f posix。</li>\n<li>-s或–print-armap:当列出库中成员的符号时,包含索引。索引的内容包含:哪些模块包含哪些名字的映射。</li>\n<li>-r或–reverse-sort:反转排序的顺序(例如,升序变为降序)。</li>\n<li>–size-sort:按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。</li>\n<li>-t radix或–radix=radix:使用radix进制显示符号值。radix只能为”d”表示十进制、”o”表示八进制或”x”表示十六进制。</li>\n<li>–target=bfdname:指定一个目标代码的格式,而非使用系统的默认格式。</li>\n<li>-u或–undefined-only:仅显示没有定义的符号(那些外部符号)。</li>\n<li>-l或–line-numbers:对每个符号,使用调试信息来试图找到文件名和行号。对于已定义的符号,查找符号地址的行号。对于未定义符号,查找指向符号重定位入口的行号。如果可以找到行号信息,显示在符号信息之后。</li>\n<li>-V或–version:显示nm的版本号。</li>\n<li>–help:显示nm的任选项。</li>\n</ul>\n<h2 id=\"objdump\"><a href=\"#objdump\" class=\"headerlink\" title=\"objdump\"></a>objdump</h2><p>常用命令:</p>\n<ol>\n<li>objdump -h file<.o,.a,.out> // 查看对象文件所有的节sections.例如<br>#objdump -h libtest1.o</li>\n</ol>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">libtest1.o: file format elf32-i386</span><br><span class=\"line\">Sections:</span><br><span class=\"line\">Idx Name Size VMA LMA File off Algn</span><br><span class=\"line\"> 0 .text 00000014 00000000 00000000 00000034 2**2</span><br><span class=\"line\"> CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE</span><br><span class=\"line\"> 1 .data 00000000 00000000 00000000 00000048 2**2</span><br><span class=\"line\"> CONTENTS, ALLOC, LOAD, DATA</span><br><span class=\"line\"> 2 .bss 00000000 00000000 00000000 00000048 2**2</span><br><span class=\"line\"> ALLOC</span><br><span class=\"line\"> 3 .rodata 0000000e 00000000 00000000 00000048 2**0</span><br><span class=\"line\"> CONTENTS, ALLOC, LOAD, READONLY, DATA</span><br><span class=\"line\"> 4 .comment 0000001f 00000000 00000000 00000056 2**0</span><br><span class=\"line\"> CONTENTS, READONLY</span><br><span class=\"line\"> 5 .note.GNU-stack 00000000 00000000 00000000 00000075 2**0</span><br><span class=\"line\"> CONTENTS, READONLY</span><br></pre></td></tr></table></figure>\n<ol start=\"2\">\n<li>objdump -t 查看对象文件所有的符号列表,相当于 nm -s objfilename,如:</li>\n</ol>\n<p>#objdump -t libtest1.o</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">libtest1.o: file format elf32-i386</span><br><span class=\"line\"></span><br><span class=\"line\">SYMBOL TABLE:</span><br><span class=\"line\">00000000 l <span class=\"built_in\">df</span> *ABS* 00000000 libtest1.c</span><br><span class=\"line\">00000000 l d .text 00000000 .text</span><br><span class=\"line\">00000000 l d .data 00000000 .data</span><br><span class=\"line\">00000000 l d .bss 00000000 .bss</span><br><span class=\"line\">00000000 l d .rodata 00000000 .rodata</span><br><span class=\"line\">00000000 l d .note.GNU-stack 00000000 .note.GNU-stack</span><br><span class=\"line\">00000000 l d .comment 00000000 .comment</span><br><span class=\"line\">00000000 g F .text 00000014 print_test1</span><br><span class=\"line\">00000000 *UND* 00000000 puts</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"addr2line\"><a href=\"#addr2line\" class=\"headerlink\" title=\"addr2line\"></a>addr2line</h2><p>将可执行文件反汇编并打印对应文件的行号。</p>\n<h3 id=\"内核模块\"><a href=\"#内核模块\" class=\"headerlink\" title=\"内核模块\"></a>内核模块</h3><p>查看oops打印,看到挂死在xxx模块中,函数是func_xxx,偏移是0x100/0x200。<br>我们可以按照如下方法打印具体的行号。</p>\n<ol>\n<li>反汇编<br>aarch64-linux-gnu-objdump -D xxx.o > out.txt<br>在out.txt中找到func_xxx的开始地址。假设开始地址是0x800。</li>\n<li>计算挂死的地址<br>0x800 + 0x100 = 0x900。0x800是函数开始地址,0x100是偏移</li>\n<li>打印<br>aarch64-linux-gnu-addr2line -i -C -f -e xxx.o <strong>900</strong></li>\n</ol>\n<h3 id=\"内核\"><a href=\"#内核\" class=\"headerlink\" title=\"内核\"></a>内核</h3><p>跟上面一样,只需要将xxx.o文件替换成vmlinux就可以了。</p>\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://blog.csdn.net/longbei9029/article/details/76397089\">https://blog.csdn.net/longbei9029/article/details/76397089</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"Summary\"><a href=\"#Summary\" class=\"headerlink\" title=\"Summary\"></a>Summary</h2><p>ar, nm, objdump, addr2line</p>\n<h2 id=\"ar\"><a href=\"#ar\" class=\"headerlink\" title=\"ar\"></a>ar</h2><p>库文件的操作指令<br>经常用法:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">ar -t libname.a // 显示所有对象文件(.o文件)的列表.例: <span class=\"comment\"># ar t libtest.a</span></span><br><span class=\"line\">libtest1.o</span><br><span class=\"line\">libtest2.o</span><br><span class=\"line\">ar -rv libname.a objfile1.o objfile2.o ... objfilen.o // 把objfile1.o--objfilen.o打包成一个库文件</span><br></pre></td></tr></table></figure>\n\n<p>ar -help打印:</p>\n<ul>\n<li>d:从库中删除模块。按模块原来的文件名指定要删除的模块。如果使用了任选项v则列出被删除的每个模块。</li>\n<li>m:该操作是在一个库中移动成员。当库中如果有若干模块有相同的符号定义(如函数定义),则成员的位置顺序很重要。如果没有指定任选项,任何指定的成员将移到库的最后。也可以使用’a’,’b’,或’I’任选项移动到指定的位置。</li>\n<li>p:显示库中指定的成员到标准输出。如果指定任选项v,则在输出成员的内容前,将显示成员的名字。如果没有指定成员的名字,所有库中的文件将显示出来。</li>\n<li>q:快速追加。增加新模块到库的结尾处。并不检查是否需要替换。’a’,’b’,或’I’任选项对此操作没有影响,模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。 这时,库的符号表没有更新,可以用’ar s’或ranlib来更新库的符号表索引。</li>\n<li>r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。</li>\n<li>t:显示库的模块表清单。一般只显示模块名。</li>\n<li>x:从库中提取一个成员。如果不指定要提取的模块,则提取库中所有的模块。</li>\n</ul>\n<p>下面在看看可与操作选项结合使用的任选项:</p>\n<ul>\n<li>a:在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a,则应该为命令行中membername参数指定一个已经存在的成员名。</li>\n<li>b:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项b,则应该为命令行中membername参数指定一个已经存在的成员名。</li>\n<li>c:创建一个库。不管库是否存在,都将创建。</li>\n<li>f:在库中截短指定的名字。缺省情况下,文件名的长度是不受限制的,可以使用此参数将文件名截短,以保证与其它系统的兼容。</li>\n<li>i:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项i,则应该为命令行中membername参数指定一个已经存在的成员名(类似任选项b)。</li>\n<li>l:暂未使用</li>\n<li>N:与count参数一起使用,在库中有多个相同的文件名时指定提取或输出的个数。</li>\n<li>o:当提取成员时,保留成员的原始数据。如果不指定该任选项,则提取出的模块的时间将标为提取出的时间。</li>\n<li>P:进行文件名匹配时使用全路径名。ar在创建库时不能使用全路径名(这样的库文件不符合POSIX标准),但是有些工具可以。</li>\n<li>s:写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。甚至对于没有任何变化的库也作该动作。对一个库做ar s等同于对该库做ranlib。</li>\n<li>S:不创建目标文件索引,这在创建较大的库时能加快时间。</li>\n<li>u:一般说来,命令ar r…插入所有列出的文件到库中,如果你只想插入列出文件中那些比库中同名文件新的文件,就可以使用该任选项。该任选项只用于r操作选项。</li>\n<li>v:该选项用来显示执行操作选项的附加信息。</li>\n<li>V:显示ar的版本.</li>\n</ul>\n<h2 id=\"nm\"><a href=\"#nm\" class=\"headerlink\" title=\"nm\"></a>nm</h2><p>列出目标文件的符号清单</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">nm -s filename.a或者filename.o或者filename.out </span><br></pre></td></tr></table></figure>\n\n<p>nm -help打印</p>\n<ul>\n<li>-a或–debug-syms:显示调试符号。</li>\n<li>-B:等同于–format=bsd,用来兼容MIPS的nm。</li>\n<li>-C或–demangle:将低级符号名解码(demangle)成用户级名字。这样可以使得C++函数名具有可读性。</li>\n<li>-D或–dynamic:显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。</li>\n<li>-f format:使用format格式输出。format可以选取bsd、sysv或posix,该选项在GNU的nm中有用。默认为bsd。</li>\n<li>-g或–extern-only:仅显示外部符号。</li>\n<li>-n、-v或–numeric-sort:按符号对应地址的顺序排序,而非按符号名的字符顺序。</li>\n<li>-p或–no-sort:按目标文件中遇到的符号顺序显示,不排序。</li>\n<li>-P或–portability:使用POSIX.2标准输出格式代替默认的输出格式。等同于使用任选项-f posix。</li>\n<li>-s或–print-armap:当列出库中成员的符号时,包含索引。索引的内容包含:哪些模块包含哪些名字的映射。</li>\n<li>-r或–reverse-sort:反转排序的顺序(例如,升序变为降序)。</li>\n<li>–size-sort:按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。</li>\n<li>-t radix或–radix=radix:使用radix进制显示符号值。radix只能为”d”表示十进制、”o”表示八进制或”x”表示十六进制。</li>\n<li>–target=bfdname:指定一个目标代码的格式,而非使用系统的默认格式。</li>\n<li>-u或–undefined-only:仅显示没有定义的符号(那些外部符号)。</li>\n<li>-l或–line-numbers:对每个符号,使用调试信息来试图找到文件名和行号。对于已定义的符号,查找符号地址的行号。对于未定义符号,查找指向符号重定位入口的行号。如果可以找到行号信息,显示在符号信息之后。</li>\n<li>-V或–version:显示nm的版本号。</li>\n<li>–help:显示nm的任选项。</li>\n</ul>\n<h2 id=\"objdump\"><a href=\"#objdump\" class=\"headerlink\" title=\"objdump\"></a>objdump</h2><p>常用命令:</p>\n<ol>\n<li>objdump -h file<.o,.a,.out> // 查看对象文件所有的节sections.例如<br>#objdump -h libtest1.o</li>\n</ol>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">libtest1.o: file format elf32-i386</span><br><span class=\"line\">Sections:</span><br><span class=\"line\">Idx Name Size VMA LMA File off Algn</span><br><span class=\"line\"> 0 .text 00000014 00000000 00000000 00000034 2**2</span><br><span class=\"line\"> CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE</span><br><span class=\"line\"> 1 .data 00000000 00000000 00000000 00000048 2**2</span><br><span class=\"line\"> CONTENTS, ALLOC, LOAD, DATA</span><br><span class=\"line\"> 2 .bss 00000000 00000000 00000000 00000048 2**2</span><br><span class=\"line\"> ALLOC</span><br><span class=\"line\"> 3 .rodata 0000000e 00000000 00000000 00000048 2**0</span><br><span class=\"line\"> CONTENTS, ALLOC, LOAD, READONLY, DATA</span><br><span class=\"line\"> 4 .comment 0000001f 00000000 00000000 00000056 2**0</span><br><span class=\"line\"> CONTENTS, READONLY</span><br><span class=\"line\"> 5 .note.GNU-stack 00000000 00000000 00000000 00000075 2**0</span><br><span class=\"line\"> CONTENTS, READONLY</span><br></pre></td></tr></table></figure>\n<ol start=\"2\">\n<li>objdump -t 查看对象文件所有的符号列表,相当于 nm -s objfilename,如:</li>\n</ol>\n<p>#objdump -t libtest1.o</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">libtest1.o: file format elf32-i386</span><br><span class=\"line\"></span><br><span class=\"line\">SYMBOL TABLE:</span><br><span class=\"line\">00000000 l <span class=\"built_in\">df</span> *ABS* 00000000 libtest1.c</span><br><span class=\"line\">00000000 l d .text 00000000 .text</span><br><span class=\"line\">00000000 l d .data 00000000 .data</span><br><span class=\"line\">00000000 l d .bss 00000000 .bss</span><br><span class=\"line\">00000000 l d .rodata 00000000 .rodata</span><br><span class=\"line\">00000000 l d .note.GNU-stack 00000000 .note.GNU-stack</span><br><span class=\"line\">00000000 l d .comment 00000000 .comment</span><br><span class=\"line\">00000000 g F .text 00000014 print_test1</span><br><span class=\"line\">00000000 *UND* 00000000 puts</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"addr2line\"><a href=\"#addr2line\" class=\"headerlink\" title=\"addr2line\"></a>addr2line</h2><p>将可执行文件反汇编并打印对应文件的行号。</p>\n<h3 id=\"内核模块\"><a href=\"#内核模块\" class=\"headerlink\" title=\"内核模块\"></a>内核模块</h3><p>查看oops打印,看到挂死在xxx模块中,函数是func_xxx,偏移是0x100/0x200。<br>我们可以按照如下方法打印具体的行号。</p>\n<ol>\n<li>反汇编<br>aarch64-linux-gnu-objdump -D xxx.o > out.txt<br>在out.txt中找到func_xxx的开始地址。假设开始地址是0x800。</li>\n<li>计算挂死的地址<br>0x800 + 0x100 = 0x900。0x800是函数开始地址,0x100是偏移</li>\n<li>打印<br>aarch64-linux-gnu-addr2line -i -C -f -e xxx.o <strong>900</strong></li>\n</ol>\n<h3 id=\"内核\"><a href=\"#内核\" class=\"headerlink\" title=\"内核\"></a>内核</h3><p>跟上面一样,只需要将xxx.o文件替换成vmlinux就可以了。</p>\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://blog.csdn.net/longbei9029/article/details/76397089\">https://blog.csdn.net/longbei9029/article/details/76397089</a></p>\n"},{"title":"Gic","_content":"\n## 寄存器\nGICC_AHPPIR\n","source":"_posts/Gic.md","raw":"---\ntitle: Gic\ncategories: \n- Aarch64\ntags:\n- Gic\n---\n\n## 寄存器\nGICC_AHPPIR\n","slug":"Gic","published":1,"date":"2024-08-16T12:53:51.255Z","updated":"2024-08-16T12:53:51.255Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv7000dqwq2790t9qxu","content":"<h2 id=\"寄存器\"><a href=\"#寄存器\" class=\"headerlink\" title=\"寄存器\"></a>寄存器</h2><p>GICC_AHPPIR</p>\n","cover":false,"excerpt":"","more":"<h2 id=\"寄存器\"><a href=\"#寄存器\" class=\"headerlink\" title=\"寄存器\"></a>寄存器</h2><p>GICC_AHPPIR</p>\n"},{"title":"CpuTopology","_content":"\n## 参考\n\nDocumentation\\cputopology.txt\n","source":"_posts/CpuTopology.md","raw":"---\ntitle: CpuTopology\ncategories: \n- Aarch64\ntags:\n- Aarch64\n---\n\n## 参考\n\nDocumentation\\cputopology.txt\n","slug":"CpuTopology","published":1,"date":"2024-08-14T10:01:22.766Z","updated":"2024-08-14T10:01:22.766Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv8000hqwq22xw145j1","content":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p>Documentation\\cputopology.txt</p>\n","cover":false,"excerpt":"","more":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p>Documentation\\cputopology.txt</p>\n"},{"title":"FileSystem","_content":"\n","source":"_posts/FileSystem.md","raw":"---\ntitle: FileSystem\ncategories: \n- Linux\ntags:\n- Linux File System\n---\n\n","slug":"FileSystem","published":1,"date":"2024-08-09T10:53:15.489Z","updated":"2024-08-10T16:13:28.241Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv8000kqwq29vtja4vn","content":"","cover":false,"excerpt":"","more":""},{"title":"HugeTLB","_content":"\n## 参考\nhttps://blog.csdn.net/wangquan1992/article/details/103963108\nhttps://blog.csdn.net/hbuxiaofei/article/details/128402495\nhttps://blog.csdn.net/tony_vip/article/details/113791585\n\nhttps://students.mimuw.edu.pl/ZSO/Wyklady/11_extXfs/TransparentHugePages.pdf\n\n## 为什么使用大页 \n#### 大页提高性能\n大页能提高性能的原理:MMU翻译页表,按照2MB翻译,到PMD这层就可以了,不用翻译到PTE阶段。\n\n## 大页类型\n### HugeTLB机制: \n hstate管理大页,从伙伴系统申请,由order值决定大小。小于order的由伙伴系统申请,大于order的由memblock预留内存中申请或者调用alloc_cont_range申请。\n HugeTLB机制:hugetlbfs文件系统\n (1) HugeTLB就是透过hugetlbfs方式向文件系统提供使用HugeTLB大页机制\n (2) hugetlbfs创建的文件可以被读系统调用操作,但不允许写系统调用操作,可以mmap映射\n\n### 复合大页(Compound pages):多个page组合起来管理连续内存空间\n### 透明大页(Transparent Huge Pages):伙伴系统直接动态分配\n 透明大页机制介绍:khugepaged线程\n 1) Hash表是为了便于通过mm_struct指针地址,来找到对应的mm_slot结构\n 2) Khugepaged_scan管理的链表是透明大页遍历扫描的链表,透明大页遍历每个mm_slot 的mm_struct\n 3) 通过mm_struct,遍历每个vma数据结构,扫描vma的地址空间,每次按2M大小扫描对应的pte内容\n\n透明大页由于性能抖动以及挂死等问题,被禁用:\nhttps://www.pingcap.com/blog/transparent-huge-pages-why-we-disable-it-for-databases/\n\n## 如何使用大页\n### 用户态使用大页\n 用户态使用大页有以下几种方法:\n - mount一个特殊的hugetlbfs文件系统,在上面创建文件,然后用mmap()进行访问, 但文件是只读的。也可以使用libhugetlbfs。\n - shmget/shmat,调用shmget申请共享内存加上SHM_HUGETLB标志。\n - mmap()时指定MAAP_HUGETLB标志。\n - memfd的memfd_create传MFD_HUGETLB标记\n \n#### mmap方式使用示例\n1) cat /proc/meminfo | grep -i huge查看大页预留情况\n AnonHugePages: 2048 kB\n HugePages_Total: 200\n HugePages_Free: 200\n HugePages_Rsvd: 0\n HugePages_Surp: 0\n Hugepagesize: 2048 kB\n2) 预留大页(200个大页)\n echo 200 > /proc/sys/vm/nr_huagepages\n 或者\n sysctl vm.nr_hugepages=200\n3) mmap + memset的时候,在mmap参数中添加MAP_HUGETLB申请使用大页\n 例如:\n (1) 申请使用大页\n size = 2 * 1024 * 1024;\n addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | 0x40000 /*MAP_HUGETLB*/, -1, 0);\n memset(addr, 0, size);\n (2) 重新查看大页使用情况\n AnonHugePages: 2048 kB\n HugePages_Total: 200\n HugePages_Free: 199\n HugePages_Rsvd: 0\n HugePages_Surp: 0\n Hugepagesize: 2048 kB\n#### mount hugetlbfs方式示例\n libhugetlbfs:使用大页,将用户态程序的text/data/BSS保存到大页功能,提高性能\n\n#### shmemget方式示例\n shmem大页:https://stackoverflow.com/questions/40777684/create-huge-page-shared-memory-for-ipc-in-linux\n\n### 内核态申请大页\n\n\n","source":"_posts/HugeTLB.md","raw":"---\ntitle: HugeTLB\ncategories: \n- Linux\ntags:\n- Linux MM\n---\n\n## 参考\nhttps://blog.csdn.net/wangquan1992/article/details/103963108\nhttps://blog.csdn.net/hbuxiaofei/article/details/128402495\nhttps://blog.csdn.net/tony_vip/article/details/113791585\n\nhttps://students.mimuw.edu.pl/ZSO/Wyklady/11_extXfs/TransparentHugePages.pdf\n\n## 为什么使用大页 \n#### 大页提高性能\n大页能提高性能的原理:MMU翻译页表,按照2MB翻译,到PMD这层就可以了,不用翻译到PTE阶段。\n\n## 大页类型\n### HugeTLB机制: \n hstate管理大页,从伙伴系统申请,由order值决定大小。小于order的由伙伴系统申请,大于order的由memblock预留内存中申请或者调用alloc_cont_range申请。\n HugeTLB机制:hugetlbfs文件系统\n (1) HugeTLB就是透过hugetlbfs方式向文件系统提供使用HugeTLB大页机制\n (2) hugetlbfs创建的文件可以被读系统调用操作,但不允许写系统调用操作,可以mmap映射\n\n### 复合大页(Compound pages):多个page组合起来管理连续内存空间\n### 透明大页(Transparent Huge Pages):伙伴系统直接动态分配\n 透明大页机制介绍:khugepaged线程\n 1) Hash表是为了便于通过mm_struct指针地址,来找到对应的mm_slot结构\n 2) Khugepaged_scan管理的链表是透明大页遍历扫描的链表,透明大页遍历每个mm_slot 的mm_struct\n 3) 通过mm_struct,遍历每个vma数据结构,扫描vma的地址空间,每次按2M大小扫描对应的pte内容\n\n透明大页由于性能抖动以及挂死等问题,被禁用:\nhttps://www.pingcap.com/blog/transparent-huge-pages-why-we-disable-it-for-databases/\n\n## 如何使用大页\n### 用户态使用大页\n 用户态使用大页有以下几种方法:\n - mount一个特殊的hugetlbfs文件系统,在上面创建文件,然后用mmap()进行访问, 但文件是只读的。也可以使用libhugetlbfs。\n - shmget/shmat,调用shmget申请共享内存加上SHM_HUGETLB标志。\n - mmap()时指定MAAP_HUGETLB标志。\n - memfd的memfd_create传MFD_HUGETLB标记\n \n#### mmap方式使用示例\n1) cat /proc/meminfo | grep -i huge查看大页预留情况\n AnonHugePages: 2048 kB\n HugePages_Total: 200\n HugePages_Free: 200\n HugePages_Rsvd: 0\n HugePages_Surp: 0\n Hugepagesize: 2048 kB\n2) 预留大页(200个大页)\n echo 200 > /proc/sys/vm/nr_huagepages\n 或者\n sysctl vm.nr_hugepages=200\n3) mmap + memset的时候,在mmap参数中添加MAP_HUGETLB申请使用大页\n 例如:\n (1) 申请使用大页\n size = 2 * 1024 * 1024;\n addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | 0x40000 /*MAP_HUGETLB*/, -1, 0);\n memset(addr, 0, size);\n (2) 重新查看大页使用情况\n AnonHugePages: 2048 kB\n HugePages_Total: 200\n HugePages_Free: 199\n HugePages_Rsvd: 0\n HugePages_Surp: 0\n Hugepagesize: 2048 kB\n#### mount hugetlbfs方式示例\n libhugetlbfs:使用大页,将用户态程序的text/data/BSS保存到大页功能,提高性能\n\n#### shmemget方式示例\n shmem大页:https://stackoverflow.com/questions/40777684/create-huge-page-shared-memory-for-ipc-in-linux\n\n### 内核态申请大页\n\n\n","slug":"HugeTLB","published":1,"date":"2024-08-10T10:31:17.357Z","updated":"2024-08-10T16:13:37.995Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv8000oqwq27co9cmc6","content":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://blog.csdn.net/wangquan1992/article/details/103963108\">https://blog.csdn.net/wangquan1992/article/details/103963108</a><br><a href=\"https://blog.csdn.net/hbuxiaofei/article/details/128402495\">https://blog.csdn.net/hbuxiaofei/article/details/128402495</a><br><a href=\"https://blog.csdn.net/tony_vip/article/details/113791585\">https://blog.csdn.net/tony_vip/article/details/113791585</a></p>\n<p><a href=\"https://students.mimuw.edu.pl/ZSO/Wyklady/11_extXfs/TransparentHugePages.pdf\">https://students.mimuw.edu.pl/ZSO/Wyklady/11_extXfs/TransparentHugePages.pdf</a></p>\n<h2 id=\"为什么使用大页\"><a href=\"#为什么使用大页\" class=\"headerlink\" title=\"为什么使用大页\"></a>为什么使用大页</h2><h4 id=\"大页提高性能\"><a href=\"#大页提高性能\" class=\"headerlink\" title=\"大页提高性能\"></a>大页提高性能</h4><p>大页能提高性能的原理:MMU翻译页表,按照2MB翻译,到PMD这层就可以了,不用翻译到PTE阶段。</p>\n<h2 id=\"大页类型\"><a href=\"#大页类型\" class=\"headerlink\" title=\"大页类型\"></a>大页类型</h2><h3 id=\"HugeTLB机制:\"><a href=\"#HugeTLB机制:\" class=\"headerlink\" title=\"HugeTLB机制:\"></a>HugeTLB机制:</h3><p> hstate管理大页,从伙伴系统申请,由order值决定大小。小于order的由伙伴系统申请,大于order的由memblock预留内存中申请或者调用alloc_cont_range申请。<br> HugeTLB机制:hugetlbfs文件系统<br> (1) HugeTLB就是透过hugetlbfs方式向文件系统提供使用HugeTLB大页机制<br> (2) hugetlbfs创建的文件可以被读系统调用操作,但不允许写系统调用操作,可以mmap映射</p>\n<h3 id=\"复合大页(Compound-pages):多个page组合起来管理连续内存空间\"><a href=\"#复合大页(Compound-pages):多个page组合起来管理连续内存空间\" class=\"headerlink\" title=\"复合大页(Compound pages):多个page组合起来管理连续内存空间\"></a>复合大页(Compound pages):多个page组合起来管理连续内存空间</h3><h3 id=\"透明大页(Transparent-Huge-Pages):伙伴系统直接动态分配\"><a href=\"#透明大页(Transparent-Huge-Pages):伙伴系统直接动态分配\" class=\"headerlink\" title=\"透明大页(Transparent Huge Pages):伙伴系统直接动态分配\"></a>透明大页(Transparent Huge Pages):伙伴系统直接动态分配</h3><p> 透明大页机制介绍:khugepaged线程</p>\n<ol>\n<li>Hash表是为了便于通过mm_struct指针地址,来找到对应的mm_slot结构</li>\n<li>Khugepaged_scan管理的链表是透明大页遍历扫描的链表,透明大页遍历每个mm_slot 的mm_struct</li>\n<li>通过mm_struct,遍历每个vma数据结构,扫描vma的地址空间,每次按2M大小扫描对应的pte内容</li>\n</ol>\n<p>透明大页由于性能抖动以及挂死等问题,被禁用:<br><a href=\"https://www.pingcap.com/blog/transparent-huge-pages-why-we-disable-it-for-databases/\">https://www.pingcap.com/blog/transparent-huge-pages-why-we-disable-it-for-databases/</a></p>\n<h2 id=\"如何使用大页\"><a href=\"#如何使用大页\" class=\"headerlink\" title=\"如何使用大页\"></a>如何使用大页</h2><h3 id=\"用户态使用大页\"><a href=\"#用户态使用大页\" class=\"headerlink\" title=\"用户态使用大页\"></a>用户态使用大页</h3><p> 用户态使用大页有以下几种方法:</p>\n<ul>\n<li>mount一个特殊的hugetlbfs文件系统,在上面创建文件,然后用mmap()进行访问, 但文件是只读的。也可以使用libhugetlbfs。</li>\n<li>shmget/shmat,调用shmget申请共享内存加上SHM_HUGETLB标志。</li>\n<li>mmap()时指定MAAP_HUGETLB标志。</li>\n<li>memfd的memfd_create传MFD_HUGETLB标记</li>\n</ul>\n<h4 id=\"mmap方式使用示例\"><a href=\"#mmap方式使用示例\" class=\"headerlink\" title=\"mmap方式使用示例\"></a>mmap方式使用示例</h4><ol>\n<li>cat /proc/meminfo | grep -i huge查看大页预留情况<br>AnonHugePages: 2048 kB<br>HugePages_Total: 200<br>HugePages_Free: 200<br>HugePages_Rsvd: 0<br>HugePages_Surp: 0<br>Hugepagesize: 2048 kB</li>\n<li>预留大页(200个大页)<br>echo 200 > /proc/sys/vm/nr_huagepages<br>或者<br>sysctl vm.nr_hugepages=200</li>\n<li>mmap + memset的时候,在mmap参数中添加MAP_HUGETLB申请使用大页<br>例如:<br>(1) 申请使用大页<br> size = 2 * 1024 * 1024;<br> addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | 0x40000 /<em>MAP_HUGETLB</em>/, -1, 0);<br> memset(addr, 0, size);<br>(2) 重新查看大页使用情况<br> AnonHugePages: 2048 kB<br> HugePages_Total: 200<br> HugePages_Free: 199<br> HugePages_Rsvd: 0<br> HugePages_Surp: 0<br> Hugepagesize: 2048 kB</li>\n</ol>\n<h4 id=\"mount-hugetlbfs方式示例\"><a href=\"#mount-hugetlbfs方式示例\" class=\"headerlink\" title=\"mount hugetlbfs方式示例\"></a>mount hugetlbfs方式示例</h4><p> libhugetlbfs:使用大页,将用户态程序的text/data/BSS保存到大页功能,提高性能</p>\n<h4 id=\"shmemget方式示例\"><a href=\"#shmemget方式示例\" class=\"headerlink\" title=\"shmemget方式示例\"></a>shmemget方式示例</h4><p> shmem大页:<a href=\"https://stackoverflow.com/questions/40777684/create-huge-page-shared-memory-for-ipc-in-linux\">https://stackoverflow.com/questions/40777684/create-huge-page-shared-memory-for-ipc-in-linux</a></p>\n<h3 id=\"内核态申请大页\"><a href=\"#内核态申请大页\" class=\"headerlink\" title=\"内核态申请大页\"></a>内核态申请大页</h3>","cover":false,"excerpt":"","more":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://blog.csdn.net/wangquan1992/article/details/103963108\">https://blog.csdn.net/wangquan1992/article/details/103963108</a><br><a href=\"https://blog.csdn.net/hbuxiaofei/article/details/128402495\">https://blog.csdn.net/hbuxiaofei/article/details/128402495</a><br><a href=\"https://blog.csdn.net/tony_vip/article/details/113791585\">https://blog.csdn.net/tony_vip/article/details/113791585</a></p>\n<p><a href=\"https://students.mimuw.edu.pl/ZSO/Wyklady/11_extXfs/TransparentHugePages.pdf\">https://students.mimuw.edu.pl/ZSO/Wyklady/11_extXfs/TransparentHugePages.pdf</a></p>\n<h2 id=\"为什么使用大页\"><a href=\"#为什么使用大页\" class=\"headerlink\" title=\"为什么使用大页\"></a>为什么使用大页</h2><h4 id=\"大页提高性能\"><a href=\"#大页提高性能\" class=\"headerlink\" title=\"大页提高性能\"></a>大页提高性能</h4><p>大页能提高性能的原理:MMU翻译页表,按照2MB翻译,到PMD这层就可以了,不用翻译到PTE阶段。</p>\n<h2 id=\"大页类型\"><a href=\"#大页类型\" class=\"headerlink\" title=\"大页类型\"></a>大页类型</h2><h3 id=\"HugeTLB机制:\"><a href=\"#HugeTLB机制:\" class=\"headerlink\" title=\"HugeTLB机制:\"></a>HugeTLB机制:</h3><p> hstate管理大页,从伙伴系统申请,由order值决定大小。小于order的由伙伴系统申请,大于order的由memblock预留内存中申请或者调用alloc_cont_range申请。<br> HugeTLB机制:hugetlbfs文件系统<br> (1) HugeTLB就是透过hugetlbfs方式向文件系统提供使用HugeTLB大页机制<br> (2) hugetlbfs创建的文件可以被读系统调用操作,但不允许写系统调用操作,可以mmap映射</p>\n<h3 id=\"复合大页(Compound-pages):多个page组合起来管理连续内存空间\"><a href=\"#复合大页(Compound-pages):多个page组合起来管理连续内存空间\" class=\"headerlink\" title=\"复合大页(Compound pages):多个page组合起来管理连续内存空间\"></a>复合大页(Compound pages):多个page组合起来管理连续内存空间</h3><h3 id=\"透明大页(Transparent-Huge-Pages):伙伴系统直接动态分配\"><a href=\"#透明大页(Transparent-Huge-Pages):伙伴系统直接动态分配\" class=\"headerlink\" title=\"透明大页(Transparent Huge Pages):伙伴系统直接动态分配\"></a>透明大页(Transparent Huge Pages):伙伴系统直接动态分配</h3><p> 透明大页机制介绍:khugepaged线程</p>\n<ol>\n<li>Hash表是为了便于通过mm_struct指针地址,来找到对应的mm_slot结构</li>\n<li>Khugepaged_scan管理的链表是透明大页遍历扫描的链表,透明大页遍历每个mm_slot 的mm_struct</li>\n<li>通过mm_struct,遍历每个vma数据结构,扫描vma的地址空间,每次按2M大小扫描对应的pte内容</li>\n</ol>\n<p>透明大页由于性能抖动以及挂死等问题,被禁用:<br><a href=\"https://www.pingcap.com/blog/transparent-huge-pages-why-we-disable-it-for-databases/\">https://www.pingcap.com/blog/transparent-huge-pages-why-we-disable-it-for-databases/</a></p>\n<h2 id=\"如何使用大页\"><a href=\"#如何使用大页\" class=\"headerlink\" title=\"如何使用大页\"></a>如何使用大页</h2><h3 id=\"用户态使用大页\"><a href=\"#用户态使用大页\" class=\"headerlink\" title=\"用户态使用大页\"></a>用户态使用大页</h3><p> 用户态使用大页有以下几种方法:</p>\n<ul>\n<li>mount一个特殊的hugetlbfs文件系统,在上面创建文件,然后用mmap()进行访问, 但文件是只读的。也可以使用libhugetlbfs。</li>\n<li>shmget/shmat,调用shmget申请共享内存加上SHM_HUGETLB标志。</li>\n<li>mmap()时指定MAAP_HUGETLB标志。</li>\n<li>memfd的memfd_create传MFD_HUGETLB标记</li>\n</ul>\n<h4 id=\"mmap方式使用示例\"><a href=\"#mmap方式使用示例\" class=\"headerlink\" title=\"mmap方式使用示例\"></a>mmap方式使用示例</h4><ol>\n<li>cat /proc/meminfo | grep -i huge查看大页预留情况<br>AnonHugePages: 2048 kB<br>HugePages_Total: 200<br>HugePages_Free: 200<br>HugePages_Rsvd: 0<br>HugePages_Surp: 0<br>Hugepagesize: 2048 kB</li>\n<li>预留大页(200个大页)<br>echo 200 > /proc/sys/vm/nr_huagepages<br>或者<br>sysctl vm.nr_hugepages=200</li>\n<li>mmap + memset的时候,在mmap参数中添加MAP_HUGETLB申请使用大页<br>例如:<br>(1) 申请使用大页<br> size = 2 * 1024 * 1024;<br> addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | 0x40000 /<em>MAP_HUGETLB</em>/, -1, 0);<br> memset(addr, 0, size);<br>(2) 重新查看大页使用情况<br> AnonHugePages: 2048 kB<br> HugePages_Total: 200<br> HugePages_Free: 199<br> HugePages_Rsvd: 0<br> HugePages_Surp: 0<br> Hugepagesize: 2048 kB</li>\n</ol>\n<h4 id=\"mount-hugetlbfs方式示例\"><a href=\"#mount-hugetlbfs方式示例\" class=\"headerlink\" title=\"mount hugetlbfs方式示例\"></a>mount hugetlbfs方式示例</h4><p> libhugetlbfs:使用大页,将用户态程序的text/data/BSS保存到大页功能,提高性能</p>\n<h4 id=\"shmemget方式示例\"><a href=\"#shmemget方式示例\" class=\"headerlink\" title=\"shmemget方式示例\"></a>shmemget方式示例</h4><p> shmem大页:<a href=\"https://stackoverflow.com/questions/40777684/create-huge-page-shared-memory-for-ipc-in-linux\">https://stackoverflow.com/questions/40777684/create-huge-page-shared-memory-for-ipc-in-linux</a></p>\n<h3 id=\"内核态申请大页\"><a href=\"#内核态申请大页\" class=\"headerlink\" title=\"内核态申请大页\"></a>内核态申请大页</h3>"},{"title":"I2c Protocol","_content":"\n## I2C协议综述\nI2C总线包含两条线,SDA(串行数据线)/SDL(串行时钟线). 原理是通过SDA/SDL的电平高低的时序控制来进行数据的传递。\n在空闲状态时,这两个线一般被上面所接的上拉电阻拉高,保持高电平。\nI2C是半双工通信方式,同一时间只能单向通信。通信速度根据通信模式如下:\n(1) 标准模式:100Kbit/s\n(2) 快速模式:400Kbit/s\n(3) 高速模式:3.4Mbit/s。\n\n## I2C主设备/从设备\nI2C的是分主设备与从设备的。\n1. I2C通信时,通信设备之间的地位是平等的,分为主设备和从设备,其中主设备一个、从设备多个。主设备要主导整个通信过程,从设备根据I2C协议被动的响应主设备;\n2. 在I2C通信中,没有规定谁做主设备、谁做从设备,是通信双方自己协商的。一个设备在同一时间只能做主设备或者从设备,但是有的设备可以通过软件配置来决定在此次通信时做主设备还是从设备。\n\n## I2C总线\n### I2C总线状态:I2C数据传输单位是一个字节(8bit),数据前后要有一个开始信号和结束信号。根据SDA/SDL电平高低,I2C总线状态可以分为如下几种:\n1. SDA/SDL高电平:空闲\n2. SDA由高变低,SDL高电平:开始信号\n3. SDL由低变高:SDL高电平:结束信号\n\n### I2C总线状态转移:\n在开始条件产生后,总线出于忙状态,总线由数据传输的主从设备独占,其他I2C期间无法访问总线。\n在停止条件产生后,本次数据传输的主从设备将释放总线,总线再次出于空闲状态。\n\n### I2C数据传输:\nI2C发送完开始信号之后,==主设备== 在SCL线上产生每个时钟脉冲的过程中将在SDA线上传输一个数据位,当一个字节按数据位从高位到低位的顺序传输完后,紧接着==从设备==将拉低SDA线,回传给主设备一个应答位, 此时才认为一个字节真正的被传输完成。当然,并不是所有的字节传输都必须有一个应答位,比如:当从设备不能再接收主设备发送的数据时,从设备将回传一个否定应答位。ACK信号就是从设备在拉低SDA之后,再给一个SDL脉冲?\n","source":"_posts/I2c Protocol.md","raw":"---\ntitle: I2c Protocol\ncategories: \n- I2C\ntags:\n- I2c Protocol\n---\n\n## I2C协议综述\nI2C总线包含两条线,SDA(串行数据线)/SDL(串行时钟线). 原理是通过SDA/SDL的电平高低的时序控制来进行数据的传递。\n在空闲状态时,这两个线一般被上面所接的上拉电阻拉高,保持高电平。\nI2C是半双工通信方式,同一时间只能单向通信。通信速度根据通信模式如下:\n(1) 标准模式:100Kbit/s\n(2) 快速模式:400Kbit/s\n(3) 高速模式:3.4Mbit/s。\n\n## I2C主设备/从设备\nI2C的是分主设备与从设备的。\n1. I2C通信时,通信设备之间的地位是平等的,分为主设备和从设备,其中主设备一个、从设备多个。主设备要主导整个通信过程,从设备根据I2C协议被动的响应主设备;\n2. 在I2C通信中,没有规定谁做主设备、谁做从设备,是通信双方自己协商的。一个设备在同一时间只能做主设备或者从设备,但是有的设备可以通过软件配置来决定在此次通信时做主设备还是从设备。\n\n## I2C总线\n### I2C总线状态:I2C数据传输单位是一个字节(8bit),数据前后要有一个开始信号和结束信号。根据SDA/SDL电平高低,I2C总线状态可以分为如下几种:\n1. SDA/SDL高电平:空闲\n2. SDA由高变低,SDL高电平:开始信号\n3. SDL由低变高:SDL高电平:结束信号\n\n### I2C总线状态转移:\n在开始条件产生后,总线出于忙状态,总线由数据传输的主从设备独占,其他I2C期间无法访问总线。\n在停止条件产生后,本次数据传输的主从设备将释放总线,总线再次出于空闲状态。\n\n### I2C数据传输:\nI2C发送完开始信号之后,==主设备== 在SCL线上产生每个时钟脉冲的过程中将在SDA线上传输一个数据位,当一个字节按数据位从高位到低位的顺序传输完后,紧接着==从设备==将拉低SDA线,回传给主设备一个应答位, 此时才认为一个字节真正的被传输完成。当然,并不是所有的字节传输都必须有一个应答位,比如:当从设备不能再接收主设备发送的数据时,从设备将回传一个否定应答位。ACK信号就是从设备在拉低SDA之后,再给一个SDL脉冲?\n","slug":"I2c Protocol","published":1,"date":"2024-08-12T10:22:51.119Z","updated":"2024-08-12T10:22:51.119Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv9000rqwq26vqd8xan","content":"<h2 id=\"I2C协议综述\"><a href=\"#I2C协议综述\" class=\"headerlink\" title=\"I2C协议综述\"></a>I2C协议综述</h2><p>I2C总线包含两条线,SDA(串行数据线)/SDL(串行时钟线). 原理是通过SDA/SDL的电平高低的时序控制来进行数据的传递。<br>在空闲状态时,这两个线一般被上面所接的上拉电阻拉高,保持高电平。<br>I2C是半双工通信方式,同一时间只能单向通信。通信速度根据通信模式如下:<br>(1) 标准模式:100Kbit/s<br>(2) 快速模式:400Kbit/s<br>(3) 高速模式:3.4Mbit/s。</p>\n<h2 id=\"I2C主设备-从设备\"><a href=\"#I2C主设备-从设备\" class=\"headerlink\" title=\"I2C主设备/从设备\"></a>I2C主设备/从设备</h2><p>I2C的是分主设备与从设备的。</p>\n<ol>\n<li>I2C通信时,通信设备之间的地位是平等的,分为主设备和从设备,其中主设备一个、从设备多个。主设备要主导整个通信过程,从设备根据I2C协议被动的响应主设备;</li>\n<li>在I2C通信中,没有规定谁做主设备、谁做从设备,是通信双方自己协商的。一个设备在同一时间只能做主设备或者从设备,但是有的设备可以通过软件配置来决定在此次通信时做主设备还是从设备。</li>\n</ol>\n<h2 id=\"I2C总线\"><a href=\"#I2C总线\" class=\"headerlink\" title=\"I2C总线\"></a>I2C总线</h2><h3 id=\"I2C总线状态:I2C数据传输单位是一个字节-8bit-,数据前后要有一个开始信号和结束信号。根据SDA-SDL电平高低,I2C总线状态可以分为如下几种:\"><a href=\"#I2C总线状态:I2C数据传输单位是一个字节-8bit-,数据前后要有一个开始信号和结束信号。根据SDA-SDL电平高低,I2C总线状态可以分为如下几种:\" class=\"headerlink\" title=\"I2C总线状态:I2C数据传输单位是一个字节(8bit),数据前后要有一个开始信号和结束信号。根据SDA/SDL电平高低,I2C总线状态可以分为如下几种:\"></a>I2C总线状态:I2C数据传输单位是一个字节(8bit),数据前后要有一个开始信号和结束信号。根据SDA/SDL电平高低,I2C总线状态可以分为如下几种:</h3><ol>\n<li>SDA/SDL高电平:空闲</li>\n<li>SDA由高变低,SDL高电平:开始信号</li>\n<li>SDL由低变高:SDL高电平:结束信号</li>\n</ol>\n<h3 id=\"I2C总线状态转移:\"><a href=\"#I2C总线状态转移:\" class=\"headerlink\" title=\"I2C总线状态转移:\"></a>I2C总线状态转移:</h3><p>在开始条件产生后,总线出于忙状态,总线由数据传输的主从设备独占,其他I2C期间无法访问总线。<br>在停止条件产生后,本次数据传输的主从设备将释放总线,总线再次出于空闲状态。</p>\n<h3 id=\"I2C数据传输:\"><a href=\"#I2C数据传输:\" class=\"headerlink\" title=\"I2C数据传输:\"></a>I2C数据传输:</h3><p>I2C发送完开始信号之后,==主设备== 在SCL线上产生每个时钟脉冲的过程中将在SDA线上传输一个数据位,当一个字节按数据位从高位到低位的顺序传输完后,紧接着==从设备==将拉低SDA线,回传给主设备一个应答位, 此时才认为一个字节真正的被传输完成。当然,并不是所有的字节传输都必须有一个应答位,比如:当从设备不能再接收主设备发送的数据时,从设备将回传一个否定应答位。ACK信号就是从设备在拉低SDA之后,再给一个SDL脉冲?</p>\n","cover":false,"excerpt":"","more":"<h2 id=\"I2C协议综述\"><a href=\"#I2C协议综述\" class=\"headerlink\" title=\"I2C协议综述\"></a>I2C协议综述</h2><p>I2C总线包含两条线,SDA(串行数据线)/SDL(串行时钟线). 原理是通过SDA/SDL的电平高低的时序控制来进行数据的传递。<br>在空闲状态时,这两个线一般被上面所接的上拉电阻拉高,保持高电平。<br>I2C是半双工通信方式,同一时间只能单向通信。通信速度根据通信模式如下:<br>(1) 标准模式:100Kbit/s<br>(2) 快速模式:400Kbit/s<br>(3) 高速模式:3.4Mbit/s。</p>\n<h2 id=\"I2C主设备-从设备\"><a href=\"#I2C主设备-从设备\" class=\"headerlink\" title=\"I2C主设备/从设备\"></a>I2C主设备/从设备</h2><p>I2C的是分主设备与从设备的。</p>\n<ol>\n<li>I2C通信时,通信设备之间的地位是平等的,分为主设备和从设备,其中主设备一个、从设备多个。主设备要主导整个通信过程,从设备根据I2C协议被动的响应主设备;</li>\n<li>在I2C通信中,没有规定谁做主设备、谁做从设备,是通信双方自己协商的。一个设备在同一时间只能做主设备或者从设备,但是有的设备可以通过软件配置来决定在此次通信时做主设备还是从设备。</li>\n</ol>\n<h2 id=\"I2C总线\"><a href=\"#I2C总线\" class=\"headerlink\" title=\"I2C总线\"></a>I2C总线</h2><h3 id=\"I2C总线状态:I2C数据传输单位是一个字节-8bit-,数据前后要有一个开始信号和结束信号。根据SDA-SDL电平高低,I2C总线状态可以分为如下几种:\"><a href=\"#I2C总线状态:I2C数据传输单位是一个字节-8bit-,数据前后要有一个开始信号和结束信号。根据SDA-SDL电平高低,I2C总线状态可以分为如下几种:\" class=\"headerlink\" title=\"I2C总线状态:I2C数据传输单位是一个字节(8bit),数据前后要有一个开始信号和结束信号。根据SDA/SDL电平高低,I2C总线状态可以分为如下几种:\"></a>I2C总线状态:I2C数据传输单位是一个字节(8bit),数据前后要有一个开始信号和结束信号。根据SDA/SDL电平高低,I2C总线状态可以分为如下几种:</h3><ol>\n<li>SDA/SDL高电平:空闲</li>\n<li>SDA由高变低,SDL高电平:开始信号</li>\n<li>SDL由低变高:SDL高电平:结束信号</li>\n</ol>\n<h3 id=\"I2C总线状态转移:\"><a href=\"#I2C总线状态转移:\" class=\"headerlink\" title=\"I2C总线状态转移:\"></a>I2C总线状态转移:</h3><p>在开始条件产生后,总线出于忙状态,总线由数据传输的主从设备独占,其他I2C期间无法访问总线。<br>在停止条件产生后,本次数据传输的主从设备将释放总线,总线再次出于空闲状态。</p>\n<h3 id=\"I2C数据传输:\"><a href=\"#I2C数据传输:\" class=\"headerlink\" title=\"I2C数据传输:\"></a>I2C数据传输:</h3><p>I2C发送完开始信号之后,==主设备== 在SCL线上产生每个时钟脉冲的过程中将在SDA线上传输一个数据位,当一个字节按数据位从高位到低位的顺序传输完后,紧接着==从设备==将拉低SDA线,回传给主设备一个应答位, 此时才认为一个字节真正的被传输完成。当然,并不是所有的字节传输都必须有一个应答位,比如:当从设备不能再接收主设备发送的数据时,从设备将回传一个否定应答位。ACK信号就是从设备在拉低SDA之后,再给一个SDL脉冲?</p>\n"},{"title":"Kvm","_content":"","source":"_posts/Kvm.md","raw":"---\ntitle: Kvm\ncategories: \n- Linux\ntags:\n- Linux Virt\n---\n","slug":"Kvm","published":1,"date":"2024-08-10T10:31:17.358Z","updated":"2024-08-10T16:14:38.666Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv9000vqwq2awaxh58w","content":"","cover":false,"excerpt":"","more":""},{"title":"Memblock","_content":"\n","source":"_posts/Memblock.md","raw":"---\ntitle: Memblock\ncategories: \n- Linux\ntags:\n- Linux Memblock\n---\n\n","slug":"Memblock","published":1,"date":"2024-08-16T12:53:51.255Z","updated":"2024-08-16T12:53:51.255Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv9000yqwq273651wqs","content":"","cover":false,"excerpt":"","more":""},{"title":"Prctl","_content":"\n## 打开Kasan选项\n\n## 打开page alloc/free相关宏\n```c\nCONFIG_PAGE_EXTENSION=y\nCONFIG_DEBUG_PAGEALLOC=y\nCONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y\n# CONFIG_PAGE_OWNER is not set\nCONFIG_PAGE_POISONING=y\nCONFIG_PAGE_POISONING_NO_SANITY=y\n原理:内核空间通过线性映射可以访问所有的内存(页表提前被创建),上述debug版本在内存释放后会释放线性映射,这样free的内存就不能在访问了\n```\n","source":"_posts/Linux踩内存问题定位.md","raw":"---\ntitle: Prctl\ncategories: \n- Linux\ntags:\n- Linux Debug\n---\n\n## 打开Kasan选项\n\n## 打开page alloc/free相关宏\n```c\nCONFIG_PAGE_EXTENSION=y\nCONFIG_DEBUG_PAGEALLOC=y\nCONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y\n# CONFIG_PAGE_OWNER is not set\nCONFIG_PAGE_POISONING=y\nCONFIG_PAGE_POISONING_NO_SANITY=y\n原理:内核空间通过线性映射可以访问所有的内存(页表提前被创建),上述debug版本在内存释放后会释放线性映射,这样free的内存就不能在访问了\n```\n","slug":"Linux踩内存问题定位","published":1,"date":"2024-08-16T12:53:51.255Z","updated":"2024-08-16T12:53:51.255Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfv90011qwq26vpcevfn","content":"<h2 id=\"打开Kasan选项\"><a href=\"#打开Kasan选项\" class=\"headerlink\" title=\"打开Kasan选项\"></a>打开Kasan选项</h2><h2 id=\"打开page-alloc-free相关宏\"><a href=\"#打开page-alloc-free相关宏\" class=\"headerlink\" title=\"打开page alloc/free相关宏\"></a>打开page alloc/free相关宏</h2><figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">CONFIG_PAGE_EXTENSION=y</span><br><span class=\"line\">CONFIG_DEBUG_PAGEALLOC=y</span><br><span class=\"line\">CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y</span><br><span class=\"line\"># CONFIG_PAGE_OWNER is not <span class=\"built_in\">set</span></span><br><span class=\"line\">CONFIG_PAGE_POISONING=y</span><br><span class=\"line\">CONFIG_PAGE_POISONING_NO_SANITY=y</span><br><span class=\"line\">原理:内核空间通过线性映射可以访问所有的内存(页表提前被创建),上述debug版本在内存释放后会释放线性映射,这样<span class=\"built_in\">free</span>的内存就不能在访问了</span><br></pre></td></tr></table></figure>\n","cover":false,"excerpt":"","more":"<h2 id=\"打开Kasan选项\"><a href=\"#打开Kasan选项\" class=\"headerlink\" title=\"打开Kasan选项\"></a>打开Kasan选项</h2><h2 id=\"打开page-alloc-free相关宏\"><a href=\"#打开page-alloc-free相关宏\" class=\"headerlink\" title=\"打开page alloc/free相关宏\"></a>打开page alloc/free相关宏</h2><figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">CONFIG_PAGE_EXTENSION=y</span><br><span class=\"line\">CONFIG_DEBUG_PAGEALLOC=y</span><br><span class=\"line\">CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y</span><br><span class=\"line\"># CONFIG_PAGE_OWNER is not <span class=\"built_in\">set</span></span><br><span class=\"line\">CONFIG_PAGE_POISONING=y</span><br><span class=\"line\">CONFIG_PAGE_POISONING_NO_SANITY=y</span><br><span class=\"line\">原理:内核空间通过线性映射可以访问所有的内存(页表提前被创建),上述debug版本在内存释放后会释放线性映射,这样<span class=\"built_in\">free</span>的内存就不能在访问了</span><br></pre></td></tr></table></figure>\n"},{"title":"Mte","_content":"\n## 参考\nhttps://blog.csdn.net/feelabclihu/article/details/121571741\n\nhttps://www.kernel.org/doc/html/v5.12/arm64/memory-tagging-extension.html\n","source":"_posts/Mte.md","raw":"---\ntitle: Mte\ncategories: \n- Aarch64\ntags:\n- Mte\n---\n\n## 参考\nhttps://blog.csdn.net/feelabclihu/article/details/121571741\n\nhttps://www.kernel.org/doc/html/v5.12/arm64/memory-tagging-extension.html\n","slug":"Mte","published":1,"date":"2024-08-13T13:15:23.309Z","updated":"2024-08-13T13:15:23.309Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfva0015qwq26vaoband","content":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://blog.csdn.net/feelabclihu/article/details/121571741\">https://blog.csdn.net/feelabclihu/article/details/121571741</a></p>\n<p><a href=\"https://www.kernel.org/doc/html/v5.12/arm64/memory-tagging-extension.html\">https://www.kernel.org/doc/html/v5.12/arm64/memory-tagging-extension.html</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://blog.csdn.net/feelabclihu/article/details/121571741\">https://blog.csdn.net/feelabclihu/article/details/121571741</a></p>\n<p><a href=\"https://www.kernel.org/doc/html/v5.12/arm64/memory-tagging-extension.html\">https://www.kernel.org/doc/html/v5.12/arm64/memory-tagging-extension.html</a></p>\n"},{"title":"Kprobe","_content":"\n## 内核态注册\nhttps://docs.kernel.org/trace/kprobes.html\n\n## 用户态使用Kprobe探测内核函数\n### 开启关闭Kprobe\n1. 开启:echo 1 > /sys/kernel/debug/tracing/events/kprobes/enable\n2. 关闭:echo 0 > /sys/kernel/debug/tracing/events/kprobes/enable\n\n### 设置Kprobe探测点\n1. 返回值打印:\n```bash\necho 'r 函数名 ret=$retval' > /sys/kernel/debug/tracing/kprobe_events\n```\n2. 入参打印:\n\nx86平台使用%ax, %bx, %cx, %dx表示第0-3个参数。\narm平台使用x0, x1, x2, x3来表示第0-3个参数。\nLinux4.x版本之后,应该都可以使用arg0, arg1等方式表示。\n\n2.1 函数的参数直接打印值:\n\nX86打印第一个第二个参数:\n```bash\necho 'p function_name a=%ax:s32 b=%bx:u64' > /sys/kernel/debug/tracing/kprobe_events\n```\nARM打印第一个和第二个参数:\n```bash\necho 'p function_name a=%x0:x64 b=%x1' > /sys/kernel/debug/tracing/kprobe_events\n```\n这里参数:后面s32, u64, x64等都表示的是需要打印的类型。x64表示按照16禁止打印,数据位宽就是64bit(8字节)\n\n2.2 函数参数是指针,打印指针里边的内容:\n```bash\necho 'p function_name +0(%x1):x64 +8(%x1):x64 +16(%x1):x64' > /sys/kernel/debug/tracing/kprobe_events\n```\n+0(指针)表示解引用指针。按照上面的打印,第二个参数就是指针,+0(%x1):x64就是表示第二个参数指针偏移0并按照x64方式打印。\n\n### 查看结果\n```bash\ncat /sys/kernel/debug/tracing/trace\n```\n\n### 清空结果\n```bash\necho > /sys/kernel/debug/tracing/trace\n```\n\n### 查看调用栈\n```bash\necho 1 > /sys/kernel/debug/tracing/options/stacktrace\n```\n\n### 过滤入参\n```bash\necho 'arg2==期望的值' > /sys/kernel/debug/tracing/events/kprobes/p_函数名_0/filter\n```\n\n### 挂死打印\n当内核panic的时候ftrace_dump函数会将trace缓冲区里边的内容打印到内核日志中。\n```bash\necho 1 > /proc/sys/kernel/ftrace_dump_on_oops\n```\n\n例如:调用栈显示某个函数有挂死现象,则可以按照上述方式打开并跟踪参数情况,可以追踪哪些参数传到函数中导致的异常\n\n\n","source":"_posts/Kprobe.md","raw":"---\ntitle: Kprobe\ncategories: \n- Linux\ntags:\n- Linux Trace\n---\n\n## 内核态注册\nhttps://docs.kernel.org/trace/kprobes.html\n\n## 用户态使用Kprobe探测内核函数\n### 开启关闭Kprobe\n1. 开启:echo 1 > /sys/kernel/debug/tracing/events/kprobes/enable\n2. 关闭:echo 0 > /sys/kernel/debug/tracing/events/kprobes/enable\n\n### 设置Kprobe探测点\n1. 返回值打印:\n```bash\necho 'r 函数名 ret=$retval' > /sys/kernel/debug/tracing/kprobe_events\n```\n2. 入参打印:\n\nx86平台使用%ax, %bx, %cx, %dx表示第0-3个参数。\narm平台使用x0, x1, x2, x3来表示第0-3个参数。\nLinux4.x版本之后,应该都可以使用arg0, arg1等方式表示。\n\n2.1 函数的参数直接打印值:\n\nX86打印第一个第二个参数:\n```bash\necho 'p function_name a=%ax:s32 b=%bx:u64' > /sys/kernel/debug/tracing/kprobe_events\n```\nARM打印第一个和第二个参数:\n```bash\necho 'p function_name a=%x0:x64 b=%x1' > /sys/kernel/debug/tracing/kprobe_events\n```\n这里参数:后面s32, u64, x64等都表示的是需要打印的类型。x64表示按照16禁止打印,数据位宽就是64bit(8字节)\n\n2.2 函数参数是指针,打印指针里边的内容:\n```bash\necho 'p function_name +0(%x1):x64 +8(%x1):x64 +16(%x1):x64' > /sys/kernel/debug/tracing/kprobe_events\n```\n+0(指针)表示解引用指针。按照上面的打印,第二个参数就是指针,+0(%x1):x64就是表示第二个参数指针偏移0并按照x64方式打印。\n\n### 查看结果\n```bash\ncat /sys/kernel/debug/tracing/trace\n```\n\n### 清空结果\n```bash\necho > /sys/kernel/debug/tracing/trace\n```\n\n### 查看调用栈\n```bash\necho 1 > /sys/kernel/debug/tracing/options/stacktrace\n```\n\n### 过滤入参\n```bash\necho 'arg2==期望的值' > /sys/kernel/debug/tracing/events/kprobes/p_函数名_0/filter\n```\n\n### 挂死打印\n当内核panic的时候ftrace_dump函数会将trace缓冲区里边的内容打印到内核日志中。\n```bash\necho 1 > /proc/sys/kernel/ftrace_dump_on_oops\n```\n\n例如:调用栈显示某个函数有挂死现象,则可以按照上述方式打开并跟踪参数情况,可以追踪哪些参数传到函数中导致的异常\n\n\n","slug":"Kprobe","published":1,"date":"2024-08-13T13:15:23.309Z","updated":"2024-08-13T13:15:23.309Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfva0018qwq29u71ht4v","content":"<h2 id=\"内核态注册\"><a href=\"#内核态注册\" class=\"headerlink\" title=\"内核态注册\"></a>内核态注册</h2><p><a href=\"https://docs.kernel.org/trace/kprobes.html\">https://docs.kernel.org/trace/kprobes.html</a></p>\n<h2 id=\"用户态使用Kprobe探测内核函数\"><a href=\"#用户态使用Kprobe探测内核函数\" class=\"headerlink\" title=\"用户态使用Kprobe探测内核函数\"></a>用户态使用Kprobe探测内核函数</h2><h3 id=\"开启关闭Kprobe\"><a href=\"#开启关闭Kprobe\" class=\"headerlink\" title=\"开启关闭Kprobe\"></a>开启关闭Kprobe</h3><ol>\n<li>开启:echo 1 > /sys/kernel/debug/tracing/events/kprobes/enable</li>\n<li>关闭:echo 0 > /sys/kernel/debug/tracing/events/kprobes/enable</li>\n</ol>\n<h3 id=\"设置Kprobe探测点\"><a href=\"#设置Kprobe探测点\" class=\"headerlink\" title=\"设置Kprobe探测点\"></a>设置Kprobe探测点</h3><ol>\n<li>返回值打印:<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">'r 函数名 ret=$retval'</span> > /sys/kernel/debug/tracing/kprobe_events</span><br></pre></td></tr></table></figure></li>\n<li>入参打印:</li>\n</ol>\n<p>x86平台使用%ax, %bx, %cx, %dx表示第0-3个参数。<br>arm平台使用x0, x1, x2, x3来表示第0-3个参数。<br>Linux4.x版本之后,应该都可以使用arg0, arg1等方式表示。</p>\n<p>2.1 函数的参数直接打印值:</p>\n<p>X86打印第一个第二个参数:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">'p function_name a=%ax:s32 b=%bx:u64'</span> > /sys/kernel/debug/tracing/kprobe_events</span><br></pre></td></tr></table></figure>\n<p>ARM打印第一个和第二个参数:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">'p function_name a=%x0:x64 b=%x1'</span> > /sys/kernel/debug/tracing/kprobe_events</span><br></pre></td></tr></table></figure>\n<p>这里参数:后面s32, u64, x64等都表示的是需要打印的类型。x64表示按照16禁止打印,数据位宽就是64bit(8字节)</p>\n<p>2.2 函数参数是指针,打印指针里边的内容:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">'p function_name +0(%x1):x64 +8(%x1):x64 +16(%x1):x64'</span> > /sys/kernel/debug/tracing/kprobe_events</span><br></pre></td></tr></table></figure>\n<p>+0(指针)表示解引用指针。按照上面的打印,第二个参数就是指针,+0(%x1):x64就是表示第二个参数指针偏移0并按照x64方式打印。</p>\n<h3 id=\"查看结果\"><a href=\"#查看结果\" class=\"headerlink\" title=\"查看结果\"></a>查看结果</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">cat</span> /sys/kernel/debug/tracing/trace</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"清空结果\"><a href=\"#清空结果\" class=\"headerlink\" title=\"清空结果\"></a>清空结果</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> > /sys/kernel/debug/tracing/trace</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"查看调用栈\"><a href=\"#查看调用栈\" class=\"headerlink\" title=\"查看调用栈\"></a>查看调用栈</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> 1 > /sys/kernel/debug/tracing/options/stacktrace</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"过滤入参\"><a href=\"#过滤入参\" class=\"headerlink\" title=\"过滤入参\"></a>过滤入参</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">'arg2==期望的值'</span> > /sys/kernel/debug/tracing/events/kprobes/p_函数名_0/filter</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"挂死打印\"><a href=\"#挂死打印\" class=\"headerlink\" title=\"挂死打印\"></a>挂死打印</h3><p>当内核panic的时候ftrace_dump函数会将trace缓冲区里边的内容打印到内核日志中。</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> 1 > /proc/sys/kernel/ftrace_dump_on_oops</span><br></pre></td></tr></table></figure>\n\n<p>例如:调用栈显示某个函数有挂死现象,则可以按照上述方式打开并跟踪参数情况,可以追踪哪些参数传到函数中导致的异常</p>\n","cover":false,"excerpt":"","more":"<h2 id=\"内核态注册\"><a href=\"#内核态注册\" class=\"headerlink\" title=\"内核态注册\"></a>内核态注册</h2><p><a href=\"https://docs.kernel.org/trace/kprobes.html\">https://docs.kernel.org/trace/kprobes.html</a></p>\n<h2 id=\"用户态使用Kprobe探测内核函数\"><a href=\"#用户态使用Kprobe探测内核函数\" class=\"headerlink\" title=\"用户态使用Kprobe探测内核函数\"></a>用户态使用Kprobe探测内核函数</h2><h3 id=\"开启关闭Kprobe\"><a href=\"#开启关闭Kprobe\" class=\"headerlink\" title=\"开启关闭Kprobe\"></a>开启关闭Kprobe</h3><ol>\n<li>开启:echo 1 > /sys/kernel/debug/tracing/events/kprobes/enable</li>\n<li>关闭:echo 0 > /sys/kernel/debug/tracing/events/kprobes/enable</li>\n</ol>\n<h3 id=\"设置Kprobe探测点\"><a href=\"#设置Kprobe探测点\" class=\"headerlink\" title=\"设置Kprobe探测点\"></a>设置Kprobe探测点</h3><ol>\n<li>返回值打印:<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">'r 函数名 ret=$retval'</span> > /sys/kernel/debug/tracing/kprobe_events</span><br></pre></td></tr></table></figure></li>\n<li>入参打印:</li>\n</ol>\n<p>x86平台使用%ax, %bx, %cx, %dx表示第0-3个参数。<br>arm平台使用x0, x1, x2, x3来表示第0-3个参数。<br>Linux4.x版本之后,应该都可以使用arg0, arg1等方式表示。</p>\n<p>2.1 函数的参数直接打印值:</p>\n<p>X86打印第一个第二个参数:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">'p function_name a=%ax:s32 b=%bx:u64'</span> > /sys/kernel/debug/tracing/kprobe_events</span><br></pre></td></tr></table></figure>\n<p>ARM打印第一个和第二个参数:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">'p function_name a=%x0:x64 b=%x1'</span> > /sys/kernel/debug/tracing/kprobe_events</span><br></pre></td></tr></table></figure>\n<p>这里参数:后面s32, u64, x64等都表示的是需要打印的类型。x64表示按照16禁止打印,数据位宽就是64bit(8字节)</p>\n<p>2.2 函数参数是指针,打印指针里边的内容:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">'p function_name +0(%x1):x64 +8(%x1):x64 +16(%x1):x64'</span> > /sys/kernel/debug/tracing/kprobe_events</span><br></pre></td></tr></table></figure>\n<p>+0(指针)表示解引用指针。按照上面的打印,第二个参数就是指针,+0(%x1):x64就是表示第二个参数指针偏移0并按照x64方式打印。</p>\n<h3 id=\"查看结果\"><a href=\"#查看结果\" class=\"headerlink\" title=\"查看结果\"></a>查看结果</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">cat</span> /sys/kernel/debug/tracing/trace</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"清空结果\"><a href=\"#清空结果\" class=\"headerlink\" title=\"清空结果\"></a>清空结果</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> > /sys/kernel/debug/tracing/trace</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"查看调用栈\"><a href=\"#查看调用栈\" class=\"headerlink\" title=\"查看调用栈\"></a>查看调用栈</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> 1 > /sys/kernel/debug/tracing/options/stacktrace</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"过滤入参\"><a href=\"#过滤入参\" class=\"headerlink\" title=\"过滤入参\"></a>过滤入参</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">'arg2==期望的值'</span> > /sys/kernel/debug/tracing/events/kprobes/p_函数名_0/filter</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"挂死打印\"><a href=\"#挂死打印\" class=\"headerlink\" title=\"挂死打印\"></a>挂死打印</h3><p>当内核panic的时候ftrace_dump函数会将trace缓冲区里边的内容打印到内核日志中。</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> 1 > /proc/sys/kernel/ftrace_dump_on_oops</span><br></pre></td></tr></table></figure>\n\n<p>例如:调用栈显示某个函数有挂死现象,则可以按照上述方式打开并跟踪参数情况,可以追踪哪些参数传到函数中导致的异常</p>\n"},{"title":"Mmu","_content":"\n## TTBR(Translation Table Base Register)寄存器\n### TTBR寄存器介绍\nStage1页表翻译时的页表基地址。\nTTBR0_EL1指定用户态页表基地址,TTBR1_EL1指定内核态的页表基地址。\nEL2和EL3有TTBR0但没有TTBR1(就是说EL2有TTBR0_EL2, EL3有TTBR_EL3,但没有TTBR1_EL2和TTRB1_EL3)。\n- 所以EL2/EL3模式下,只能使用0x0-0x0000FFFF_FFFFFFFF范围的地址\n\n用户态不能直接访问MMU,当然也没有所谓的TTBR0_EL0,TTBR1_EL0之类的寄存器了。\n\n### TTBR地址范围确定\n\n在Linux系统中,0x0000_0000_0000_0000到0x0000_FFFF_FFFF_FFFF范围是被指定为用户态内存,0xFFFF_0000_0000_0000到0xFFFF_FFFF_FFFF_FFFF被指定为内核态地址。\n具体前面几个0表示走TTBR0_EL1或者几个F走TTBR1_EL1则是由TCR.TxSZ指定。\n\n### 如何选择(D5-1736)\n在TCR.T0SZ, TCR.T1SZ都为16的场景下:\n- 0x0000_开头的地址选择TTBR0_EL1为基地址开始页表翻译\n- 0xFFFF_开头的地址选择TTBR1_EL1为基地址开始页表翻译\n\n### TTBR位分配\n1) ASID是做什么?\n\n### VTTBR_EL2\n\n## TCR(Translation Control Register)寄存器\n包含TCR_EL1/TCR_EL2/TCR_EL3这几种。\n决定EL0/EL1在做地址翻译的时候选择哪个TTBR寄存器。\n例如:0x0000开始的地址,比如0x0000_ABCD_ABCD_ABCD这样的地址就是通过TTBR0_EL1开始地址翻译,而0xFFFF开始的地址,比如0xFFFF_ABCD_ABCD_ABCD这个地址就是通过TTBR1_EL1开始地址翻译。\n\n### TCR寄存器位分配\n\n以下是对TCR寄存器中的各位进行解释\n\n### TB (Top Byte ignored)(D8-2038)(MTE)\n表示top addr是ignore,还是用于MTE的计算\n看代码应该是kasa在用这个。\n```c [arch/arm64/mm/proc.S]\n#ifdef CONFIG_KASAN_SW_TAGS\n#define TCR_KASAN_FLAGS TCR_TBI1\n#else\n#define TCR_KASAN_FLAGS 0\n#endif\n```\n\n参考文件:Linux目录下tools/testing/selftests/arm64/tags/tags_test.c 可以查看TB是否使能。\nTB ignore使能的情况下,可以将高位用来做计数,实际地址访问的时候是会把高位给忽略掉的\n\n./Documentation/arm64/memory-tagging-extension.rst\nprctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)\n\nTB的使用可以具体参考MTE使用篇。\n\n### A1\nASID的选择,是使用TTBR_EL1中的,还是使用TTBR_EL0中的。\n\n### AS\nASID是使用8bit,还是使用16bit。\n\nTTBRx_EL1中使用ASID的原因:https://blog.csdn.net/WANGYONGZIXUE/article/details/132996049\n\n### EPD\n包含EPD1、EPD0,表示TTBR_EL1/TTBR_EL0是使能还是去使能。\n\n### T1SZ/T0SZ\nT0SZ: 表示TTBR0_EL1能表示的地址范围,地址范围的计算公式就是2^(64-T1SZ) Bytest:\n例如:如果用户态地址范围是48位虚拟地址,那这里应该配置T0SZ=64-48=16, 虚拟地址的范围是 2^(64-16) = 0 ~ 0x0000_FFFF_FFFF_FFFF\nT1SZ: 和T0SZ一样,就是表示的是TTBR1_EL1的\n这样设置之后,0x0000_开头的地址都走TTBR0_EL1进行地址翻译,0xFFFFF_开头的地址就都走TTBR1_EL1进行地址翻译。\nAarch64的tcr相关的定义都在arch/arm64/include/asm/pgtable-hwdef.h\n虚拟地址的位宽在linux用CONFIG_ARM64_VA_BITS定义\n\n### IPS(Intermediate Physical Address Size)\n中间级物理地址大小\n表示物理地址的范围:\n- 000 32 bits, 4 GB.\n- 001 36 bits, 64 GB.\n- 010 40 bits, 1 TB.\n- 011 42 bits, 4 TB.\n- 100 44 bits, 16 TB.\n- 101 48 bits, 256 TB.\n\n### TG(Granule size)\n寻址的地址粒度(在Linux场景下,就是page_size对应的大小)\n01 16KByte\n10 4KByte\n11 64KByte\n\n## MAIR (Memory Attribute Indirection Register)\n表示内存的属性。\n\nMAIR_ELx可以定义8种不同的属性。每种属性占8bit。8个bit分为前4个bit和后4个bit分别定义了不同的属性。\n\n\n\n上面显示的RW分别别是读写属性。如果读写属性都有,就填1就可以了。\n\n在Linux中,占了5种类型。MAIR_ELx属性在启动阶段就会设置好。设置的代码在\narch/arm64/mm/proc.S的__cpu_setup函数中。\n```s\nmov_q mair, MAIR_EL1_SET\n```\n\nMAIR_EL1_SET定义如下:\n```c \n#define MAIR_ATTRIDX(attr, idx) ((attr) << ((idx) * 8))\n\n#define MAIR_ATTR_DEVICE_nGnRnE UL(0x00)\n#define MAIR_ATTR_DEVICE_nGnRE UL(0x04)\n#define MAIR_ATTR_NORMAL_NC UL(0x44)\n#define MAIR_ATTR_NORMAL_TAGGED UL(0xf0)\n#define MAIR_ATTR_NORMAL UL(0xff)\n#define MAIR_ATTR_MASK UL(0xff)\n\n#define MT_NORMAL 0 \n#define MT_NORMAL_TAGGED 1 \n#define MT_NORMAL_NC 2 \n#define MT_DEVICE_nGnRnE 3\n#define MT_DEVICE_nGnRE 4 \n\n#define MAIR_EL1_SET \\\n (MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) | \\ \n MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) | \\ \n MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) | \\ \n MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \\ \n MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL_TAGGED)) \n```\n\nMAIR_ELx设置完成之后,在寻址的时候,就只需要通过lower attribute中的Attrindex中的index就可以知道这段页的内存是哪种属性了。例如如果Attrindex的值是0就是MT_NORMAL,如果是3就是MT_DEVICE_nGnRnE这种类型的。\n\n\n\n## 参考\n\nTTBR寄存器中asid的作用\nhttps://blog.csdn.net/weixin_42135087/article/details/123369119\n","source":"_posts/Mmu.md","raw":"---\ntitle: Mmu\ncategories: \n- Aarch64\ntags:\n- Mmu\n---\n\n## TTBR(Translation Table Base Register)寄存器\n### TTBR寄存器介绍\nStage1页表翻译时的页表基地址。\nTTBR0_EL1指定用户态页表基地址,TTBR1_EL1指定内核态的页表基地址。\nEL2和EL3有TTBR0但没有TTBR1(就是说EL2有TTBR0_EL2, EL3有TTBR_EL3,但没有TTBR1_EL2和TTRB1_EL3)。\n- 所以EL2/EL3模式下,只能使用0x0-0x0000FFFF_FFFFFFFF范围的地址\n\n用户态不能直接访问MMU,当然也没有所谓的TTBR0_EL0,TTBR1_EL0之类的寄存器了。\n\n### TTBR地址范围确定\n\n在Linux系统中,0x0000_0000_0000_0000到0x0000_FFFF_FFFF_FFFF范围是被指定为用户态内存,0xFFFF_0000_0000_0000到0xFFFF_FFFF_FFFF_FFFF被指定为内核态地址。\n具体前面几个0表示走TTBR0_EL1或者几个F走TTBR1_EL1则是由TCR.TxSZ指定。\n\n### 如何选择(D5-1736)\n在TCR.T0SZ, TCR.T1SZ都为16的场景下:\n- 0x0000_开头的地址选择TTBR0_EL1为基地址开始页表翻译\n- 0xFFFF_开头的地址选择TTBR1_EL1为基地址开始页表翻译\n\n### TTBR位分配\n1) ASID是做什么?\n\n### VTTBR_EL2\n\n## TCR(Translation Control Register)寄存器\n包含TCR_EL1/TCR_EL2/TCR_EL3这几种。\n决定EL0/EL1在做地址翻译的时候选择哪个TTBR寄存器。\n例如:0x0000开始的地址,比如0x0000_ABCD_ABCD_ABCD这样的地址就是通过TTBR0_EL1开始地址翻译,而0xFFFF开始的地址,比如0xFFFF_ABCD_ABCD_ABCD这个地址就是通过TTBR1_EL1开始地址翻译。\n\n### TCR寄存器位分配\n\n以下是对TCR寄存器中的各位进行解释\n\n### TB (Top Byte ignored)(D8-2038)(MTE)\n表示top addr是ignore,还是用于MTE的计算\n看代码应该是kasa在用这个。\n```c [arch/arm64/mm/proc.S]\n#ifdef CONFIG_KASAN_SW_TAGS\n#define TCR_KASAN_FLAGS TCR_TBI1\n#else\n#define TCR_KASAN_FLAGS 0\n#endif\n```\n\n参考文件:Linux目录下tools/testing/selftests/arm64/tags/tags_test.c 可以查看TB是否使能。\nTB ignore使能的情况下,可以将高位用来做计数,实际地址访问的时候是会把高位给忽略掉的\n\n./Documentation/arm64/memory-tagging-extension.rst\nprctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)\n\nTB的使用可以具体参考MTE使用篇。\n\n### A1\nASID的选择,是使用TTBR_EL1中的,还是使用TTBR_EL0中的。\n\n### AS\nASID是使用8bit,还是使用16bit。\n\nTTBRx_EL1中使用ASID的原因:https://blog.csdn.net/WANGYONGZIXUE/article/details/132996049\n\n### EPD\n包含EPD1、EPD0,表示TTBR_EL1/TTBR_EL0是使能还是去使能。\n\n### T1SZ/T0SZ\nT0SZ: 表示TTBR0_EL1能表示的地址范围,地址范围的计算公式就是2^(64-T1SZ) Bytest:\n例如:如果用户态地址范围是48位虚拟地址,那这里应该配置T0SZ=64-48=16, 虚拟地址的范围是 2^(64-16) = 0 ~ 0x0000_FFFF_FFFF_FFFF\nT1SZ: 和T0SZ一样,就是表示的是TTBR1_EL1的\n这样设置之后,0x0000_开头的地址都走TTBR0_EL1进行地址翻译,0xFFFFF_开头的地址就都走TTBR1_EL1进行地址翻译。\nAarch64的tcr相关的定义都在arch/arm64/include/asm/pgtable-hwdef.h\n虚拟地址的位宽在linux用CONFIG_ARM64_VA_BITS定义\n\n### IPS(Intermediate Physical Address Size)\n中间级物理地址大小\n表示物理地址的范围:\n- 000 32 bits, 4 GB.\n- 001 36 bits, 64 GB.\n- 010 40 bits, 1 TB.\n- 011 42 bits, 4 TB.\n- 100 44 bits, 16 TB.\n- 101 48 bits, 256 TB.\n\n### TG(Granule size)\n寻址的地址粒度(在Linux场景下,就是page_size对应的大小)\n01 16KByte\n10 4KByte\n11 64KByte\n\n## MAIR (Memory Attribute Indirection Register)\n表示内存的属性。\n\nMAIR_ELx可以定义8种不同的属性。每种属性占8bit。8个bit分为前4个bit和后4个bit分别定义了不同的属性。\n\n\n\n上面显示的RW分别别是读写属性。如果读写属性都有,就填1就可以了。\n\n在Linux中,占了5种类型。MAIR_ELx属性在启动阶段就会设置好。设置的代码在\narch/arm64/mm/proc.S的__cpu_setup函数中。\n```s\nmov_q mair, MAIR_EL1_SET\n```\n\nMAIR_EL1_SET定义如下:\n```c \n#define MAIR_ATTRIDX(attr, idx) ((attr) << ((idx) * 8))\n\n#define MAIR_ATTR_DEVICE_nGnRnE UL(0x00)\n#define MAIR_ATTR_DEVICE_nGnRE UL(0x04)\n#define MAIR_ATTR_NORMAL_NC UL(0x44)\n#define MAIR_ATTR_NORMAL_TAGGED UL(0xf0)\n#define MAIR_ATTR_NORMAL UL(0xff)\n#define MAIR_ATTR_MASK UL(0xff)\n\n#define MT_NORMAL 0 \n#define MT_NORMAL_TAGGED 1 \n#define MT_NORMAL_NC 2 \n#define MT_DEVICE_nGnRnE 3\n#define MT_DEVICE_nGnRE 4 \n\n#define MAIR_EL1_SET \\\n (MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) | \\ \n MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) | \\ \n MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) | \\ \n MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \\ \n MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL_TAGGED)) \n```\n\nMAIR_ELx设置完成之后,在寻址的时候,就只需要通过lower attribute中的Attrindex中的index就可以知道这段页的内存是哪种属性了。例如如果Attrindex的值是0就是MT_NORMAL,如果是3就是MT_DEVICE_nGnRnE这种类型的。\n\n\n\n## 参考\n\nTTBR寄存器中asid的作用\nhttps://blog.csdn.net/weixin_42135087/article/details/123369119\n","slug":"Mmu","published":1,"date":"2024-08-16T12:53:51.256Z","updated":"2024-08-16T12:53:51.256Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfva001bqwq28r3ygwqa","content":"<h2 id=\"TTBR-Translation-Table-Base-Register-寄存器\"><a href=\"#TTBR-Translation-Table-Base-Register-寄存器\" class=\"headerlink\" title=\"TTBR(Translation Table Base Register)寄存器\"></a>TTBR(Translation Table Base Register)寄存器</h2><h3 id=\"TTBR寄存器介绍\"><a href=\"#TTBR寄存器介绍\" class=\"headerlink\" title=\"TTBR寄存器介绍\"></a>TTBR寄存器介绍</h3><p>Stage1页表翻译时的页表基地址。<br>TTBR0_EL1指定用户态页表基地址,TTBR1_EL1指定内核态的页表基地址。<br>EL2和EL3有TTBR0但没有TTBR1(就是说EL2有TTBR0_EL2, EL3有TTBR_EL3,但没有TTBR1_EL2和TTRB1_EL3)。</p>\n<ul>\n<li>所以EL2/EL3模式下,只能使用0x0-0x0000FFFF_FFFFFFFF范围的地址</li>\n</ul>\n<p>用户态不能直接访问MMU,当然也没有所谓的TTBR0_EL0,TTBR1_EL0之类的寄存器了。</p>\n<h3 id=\"TTBR地址范围确定\"><a href=\"#TTBR地址范围确定\" class=\"headerlink\" title=\"TTBR地址范围确定\"></a>TTBR地址范围确定</h3><p><img src=\"/images/MMU/TTBR%E8%A1%A8%E7%A4%BA%E7%9A%84%E5%9C%B0%E5%9D%80%E8%8C%83%E5%9B%B4.drawio.svg\" alt=\"TTBR地址范围\"><br>在Linux系统中,0x0000_0000_0000_0000到0x0000_FFFF_FFFF_FFFF范围是被指定为用户态内存,0xFFFF_0000_0000_0000到0xFFFF_FFFF_FFFF_FFFF被指定为内核态地址。<br>具体前面几个0表示走TTBR0_EL1或者几个F走TTBR1_EL1则是由TCR.TxSZ指定。</p>\n<h3 id=\"如何选择(D5-1736)\"><a href=\"#如何选择(D5-1736)\" class=\"headerlink\" title=\"如何选择(D5-1736)\"></a>如何选择(D5-1736)</h3><p>在TCR.T0SZ, TCR.T1SZ都为16的场景下:</p>\n<ul>\n<li>0x0000_开头的地址选择TTBR0_EL1为基地址开始页表翻译</li>\n<li>0xFFFF_开头的地址选择TTBR1_EL1为基地址开始页表翻译</li>\n</ul>\n<h3 id=\"TTBR位分配\"><a href=\"#TTBR位分配\" class=\"headerlink\" title=\"TTBR位分配\"></a>TTBR位分配</h3><ol>\n<li>ASID是做什么?</li>\n</ol>\n<h3 id=\"VTTBR-EL2\"><a href=\"#VTTBR-EL2\" class=\"headerlink\" title=\"VTTBR_EL2\"></a>VTTBR_EL2</h3><h2 id=\"TCR-Translation-Control-Register-寄存器\"><a href=\"#TCR-Translation-Control-Register-寄存器\" class=\"headerlink\" title=\"TCR(Translation Control Register)寄存器\"></a>TCR(Translation Control Register)寄存器</h2><p>包含TCR_EL1/TCR_EL2/TCR_EL3这几种。<br>决定EL0/EL1在做地址翻译的时候选择哪个TTBR寄存器。<br>例如:0x0000开始的地址,比如0x0000_ABCD_ABCD_ABCD这样的地址就是通过TTBR0_EL1开始地址翻译,而0xFFFF开始的地址,比如0xFFFF_ABCD_ABCD_ABCD这个地址就是通过TTBR1_EL1开始地址翻译。</p>\n<h3 id=\"TCR寄存器位分配\"><a href=\"#TCR寄存器位分配\" class=\"headerlink\" title=\"TCR寄存器位分配\"></a>TCR寄存器位分配</h3><p><img src=\"/images/MMU/TCR%E5%AF%84%E5%AD%98%E5%99%A8%E4%BD%8D%E5%9B%BE.png\" alt=\"TCR寄存器\"><br>以下是对TCR寄存器中的各位进行解释</p>\n<h3 id=\"TB-(Top-Byte-ignored)(D8-2038)-MTE\"><a href=\"#TB-(Top-Byte-ignored)(D8-2038)-MTE\" class=\"headerlink\" title=\"TB (Top Byte ignored)(D8-2038)(MTE)\"></a>TB (Top Byte ignored)(D8-2038)(MTE)</h3><p>表示top addr是ignore,还是用于MTE的计算<br>看代码应该是kasa在用这个。</p>\n<figure class=\"highlight c\"><figcaption><span>[arch/arm64/mm/proc.S]</span></figcaption><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">ifdef</span> CONFIG_KASAN_SW_TAGS</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> TCR_KASAN_FLAGS TCR_TBI1</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">else</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> TCR_KASAN_FLAGS 0</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">endif</span></span></span><br></pre></td></tr></table></figure>\n\n<p>参考文件:Linux目录下tools/testing/selftests/arm64/tags/tags_test.c 可以查看TB是否使能。<br>TB ignore使能的情况下,可以将高位用来做计数,实际地址访问的时候是会把高位给忽略掉的</p>\n<p>./Documentation/arm64/memory-tagging-extension.rst<br>prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)</p>\n<p>TB的使用可以具体参考MTE使用篇。</p>\n<h3 id=\"A1\"><a href=\"#A1\" class=\"headerlink\" title=\"A1\"></a>A1</h3><p>ASID的选择,是使用TTBR_EL1中的,还是使用TTBR_EL0中的。</p>\n<h3 id=\"AS\"><a href=\"#AS\" class=\"headerlink\" title=\"AS\"></a>AS</h3><p>ASID是使用8bit,还是使用16bit。</p>\n<p>TTBRx_EL1中使用ASID的原因:<a href=\"https://blog.csdn.net/WANGYONGZIXUE/article/details/132996049\">https://blog.csdn.net/WANGYONGZIXUE/article/details/132996049</a></p>\n<h3 id=\"EPD\"><a href=\"#EPD\" class=\"headerlink\" title=\"EPD\"></a>EPD</h3><p>包含EPD1、EPD0,表示TTBR_EL1/TTBR_EL0是使能还是去使能。</p>\n<h3 id=\"T1SZ-T0SZ\"><a href=\"#T1SZ-T0SZ\" class=\"headerlink\" title=\"T1SZ/T0SZ\"></a>T1SZ/T0SZ</h3><p>T0SZ: 表示TTBR0_EL1能表示的地址范围,地址范围的计算公式就是2^(64-T1SZ) Bytest:<br>例如:如果用户态地址范围是48位虚拟地址,那这里应该配置T0SZ=64-48=16, 虚拟地址的范围是 2^(64-16) = 0 ~ 0x0000_FFFF_FFFF_FFFF<br>T1SZ: 和T0SZ一样,就是表示的是TTBR1_EL1的<br>这样设置之后,0x0000_开头的地址都走TTBR0_EL1进行地址翻译,0xFFFFF_开头的地址就都走TTBR1_EL1进行地址翻译。<br>Aarch64的tcr相关的定义都在arch/arm64/include/asm/pgtable-hwdef.h<br>虚拟地址的位宽在linux用CONFIG_ARM64_VA_BITS定义</p>\n<h3 id=\"IPS(Intermediate-Physical-Address-Size)\"><a href=\"#IPS(Intermediate-Physical-Address-Size)\" class=\"headerlink\" title=\"IPS(Intermediate Physical Address Size)\"></a>IPS(Intermediate Physical Address Size)</h3><p>中间级物理地址大小<br>表示物理地址的范围:</p>\n<ul>\n<li>000 32 bits, 4 GB.</li>\n<li>001 36 bits, 64 GB.</li>\n<li>010 40 bits, 1 TB.</li>\n<li>011 42 bits, 4 TB.</li>\n<li>100 44 bits, 16 TB.</li>\n<li>101 48 bits, 256 TB.</li>\n</ul>\n<h3 id=\"TG(Granule-size)\"><a href=\"#TG(Granule-size)\" class=\"headerlink\" title=\"TG(Granule size)\"></a>TG(Granule size)</h3><p>寻址的地址粒度(在Linux场景下,就是page_size对应的大小)<br>01 16KByte<br>10 4KByte<br>11 64KByte</p>\n<h2 id=\"MAIR-Memory-Attribute-Indirection-Register\"><a href=\"#MAIR-Memory-Attribute-Indirection-Register\" class=\"headerlink\" title=\"MAIR (Memory Attribute Indirection Register)\"></a>MAIR (Memory Attribute Indirection Register)</h2><p>表示内存的属性。<br><img src=\"/images/MMU/MAIR_EL1-1.png\" alt=\"TCR寄存器\"><br>MAIR_ELx可以定义8种不同的属性。每种属性占8bit。8个bit分为前4个bit和后4个bit分别定义了不同的属性。<br><img src=\"/images/MMU/MAIR_EL1-2.png\" alt=\"TCR寄存器\"><br><img src=\"/images/MMU/MAIR_EL1-3.png\" alt=\"TCR寄存器\"></p>\n<p>上面显示的RW分别别是读写属性。如果读写属性都有,就填1就可以了。</p>\n<p>在Linux中,占了5种类型。MAIR_ELx属性在启动阶段就会设置好。设置的代码在<br>arch/arm64/mm/proc.S的__cpu_setup函数中。</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">mov_q mair, MAIR_EL1_SET</span><br></pre></td></tr></table></figure>\n\n<p>MAIR_EL1_SET定义如下:</p>\n<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTRIDX(attr, idx) ((attr) << ((idx) * 8))</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_DEVICE_nGnRnE UL(0x00)</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_DEVICE_nGnRE UL(0x04)</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_NORMAL_NC UL(0x44)</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_NORMAL_TAGGED UL(0xf0)</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_NORMAL UL(0xff)</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_MASK UL(0xff)</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MT_NORMAL 0 </span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MT_NORMAL_TAGGED 1 </span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MT_NORMAL_NC 2 </span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MT_DEVICE_nGnRnE 3</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MT_DEVICE_nGnRE 4 </span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_EL1_SET \\</span></span><br><span class=\"line\"><span class=\"meta\"> (MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) | \\ </span></span><br><span class=\"line\"> MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) | \\ </span><br><span class=\"line\"> MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) | \\ </span><br><span class=\"line\"> MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \\ </span><br><span class=\"line\"> MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL_TAGGED)) </span><br></pre></td></tr></table></figure>\n\n<p>MAIR_ELx设置完成之后,在寻址的时候,就只需要通过lower attribute中的Attrindex中的index就可以知道这段页的内存是哪种属性了。例如如果Attrindex的值是0就是MT_NORMAL,如果是3就是MT_DEVICE_nGnRnE这种类型的。<br><img src=\"/images/MMU/PTE-1.png\" alt=\"TCR寄存器\"><br><img src=\"/images/MMU/PTE-2.png\" alt=\"TCR寄存器\"></p>\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p>TTBR寄存器中asid的作用<br><a href=\"https://blog.csdn.net/weixin_42135087/article/details/123369119\">https://blog.csdn.net/weixin_42135087/article/details/123369119</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"TTBR-Translation-Table-Base-Register-寄存器\"><a href=\"#TTBR-Translation-Table-Base-Register-寄存器\" class=\"headerlink\" title=\"TTBR(Translation Table Base Register)寄存器\"></a>TTBR(Translation Table Base Register)寄存器</h2><h3 id=\"TTBR寄存器介绍\"><a href=\"#TTBR寄存器介绍\" class=\"headerlink\" title=\"TTBR寄存器介绍\"></a>TTBR寄存器介绍</h3><p>Stage1页表翻译时的页表基地址。<br>TTBR0_EL1指定用户态页表基地址,TTBR1_EL1指定内核态的页表基地址。<br>EL2和EL3有TTBR0但没有TTBR1(就是说EL2有TTBR0_EL2, EL3有TTBR_EL3,但没有TTBR1_EL2和TTRB1_EL3)。</p>\n<ul>\n<li>所以EL2/EL3模式下,只能使用0x0-0x0000FFFF_FFFFFFFF范围的地址</li>\n</ul>\n<p>用户态不能直接访问MMU,当然也没有所谓的TTBR0_EL0,TTBR1_EL0之类的寄存器了。</p>\n<h3 id=\"TTBR地址范围确定\"><a href=\"#TTBR地址范围确定\" class=\"headerlink\" title=\"TTBR地址范围确定\"></a>TTBR地址范围确定</h3><p><img src=\"/images/MMU/TTBR%E8%A1%A8%E7%A4%BA%E7%9A%84%E5%9C%B0%E5%9D%80%E8%8C%83%E5%9B%B4.drawio.svg\" alt=\"TTBR地址范围\"><br>在Linux系统中,0x0000_0000_0000_0000到0x0000_FFFF_FFFF_FFFF范围是被指定为用户态内存,0xFFFF_0000_0000_0000到0xFFFF_FFFF_FFFF_FFFF被指定为内核态地址。<br>具体前面几个0表示走TTBR0_EL1或者几个F走TTBR1_EL1则是由TCR.TxSZ指定。</p>\n<h3 id=\"如何选择(D5-1736)\"><a href=\"#如何选择(D5-1736)\" class=\"headerlink\" title=\"如何选择(D5-1736)\"></a>如何选择(D5-1736)</h3><p>在TCR.T0SZ, TCR.T1SZ都为16的场景下:</p>\n<ul>\n<li>0x0000_开头的地址选择TTBR0_EL1为基地址开始页表翻译</li>\n<li>0xFFFF_开头的地址选择TTBR1_EL1为基地址开始页表翻译</li>\n</ul>\n<h3 id=\"TTBR位分配\"><a href=\"#TTBR位分配\" class=\"headerlink\" title=\"TTBR位分配\"></a>TTBR位分配</h3><ol>\n<li>ASID是做什么?</li>\n</ol>\n<h3 id=\"VTTBR-EL2\"><a href=\"#VTTBR-EL2\" class=\"headerlink\" title=\"VTTBR_EL2\"></a>VTTBR_EL2</h3><h2 id=\"TCR-Translation-Control-Register-寄存器\"><a href=\"#TCR-Translation-Control-Register-寄存器\" class=\"headerlink\" title=\"TCR(Translation Control Register)寄存器\"></a>TCR(Translation Control Register)寄存器</h2><p>包含TCR_EL1/TCR_EL2/TCR_EL3这几种。<br>决定EL0/EL1在做地址翻译的时候选择哪个TTBR寄存器。<br>例如:0x0000开始的地址,比如0x0000_ABCD_ABCD_ABCD这样的地址就是通过TTBR0_EL1开始地址翻译,而0xFFFF开始的地址,比如0xFFFF_ABCD_ABCD_ABCD这个地址就是通过TTBR1_EL1开始地址翻译。</p>\n<h3 id=\"TCR寄存器位分配\"><a href=\"#TCR寄存器位分配\" class=\"headerlink\" title=\"TCR寄存器位分配\"></a>TCR寄存器位分配</h3><p><img src=\"/images/MMU/TCR%E5%AF%84%E5%AD%98%E5%99%A8%E4%BD%8D%E5%9B%BE.png\" alt=\"TCR寄存器\"><br>以下是对TCR寄存器中的各位进行解释</p>\n<h3 id=\"TB-(Top-Byte-ignored)(D8-2038)-MTE\"><a href=\"#TB-(Top-Byte-ignored)(D8-2038)-MTE\" class=\"headerlink\" title=\"TB (Top Byte ignored)(D8-2038)(MTE)\"></a>TB (Top Byte ignored)(D8-2038)(MTE)</h3><p>表示top addr是ignore,还是用于MTE的计算<br>看代码应该是kasa在用这个。</p>\n<figure class=\"highlight c\"><figcaption><span>[arch/arm64/mm/proc.S]</span></figcaption><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">ifdef</span> CONFIG_KASAN_SW_TAGS</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> TCR_KASAN_FLAGS TCR_TBI1</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">else</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> TCR_KASAN_FLAGS 0</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">endif</span></span></span><br></pre></td></tr></table></figure>\n\n<p>参考文件:Linux目录下tools/testing/selftests/arm64/tags/tags_test.c 可以查看TB是否使能。<br>TB ignore使能的情况下,可以将高位用来做计数,实际地址访问的时候是会把高位给忽略掉的</p>\n<p>./Documentation/arm64/memory-tagging-extension.rst<br>prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)</p>\n<p>TB的使用可以具体参考MTE使用篇。</p>\n<h3 id=\"A1\"><a href=\"#A1\" class=\"headerlink\" title=\"A1\"></a>A1</h3><p>ASID的选择,是使用TTBR_EL1中的,还是使用TTBR_EL0中的。</p>\n<h3 id=\"AS\"><a href=\"#AS\" class=\"headerlink\" title=\"AS\"></a>AS</h3><p>ASID是使用8bit,还是使用16bit。</p>\n<p>TTBRx_EL1中使用ASID的原因:<a href=\"https://blog.csdn.net/WANGYONGZIXUE/article/details/132996049\">https://blog.csdn.net/WANGYONGZIXUE/article/details/132996049</a></p>\n<h3 id=\"EPD\"><a href=\"#EPD\" class=\"headerlink\" title=\"EPD\"></a>EPD</h3><p>包含EPD1、EPD0,表示TTBR_EL1/TTBR_EL0是使能还是去使能。</p>\n<h3 id=\"T1SZ-T0SZ\"><a href=\"#T1SZ-T0SZ\" class=\"headerlink\" title=\"T1SZ/T0SZ\"></a>T1SZ/T0SZ</h3><p>T0SZ: 表示TTBR0_EL1能表示的地址范围,地址范围的计算公式就是2^(64-T1SZ) Bytest:<br>例如:如果用户态地址范围是48位虚拟地址,那这里应该配置T0SZ=64-48=16, 虚拟地址的范围是 2^(64-16) = 0 ~ 0x0000_FFFF_FFFF_FFFF<br>T1SZ: 和T0SZ一样,就是表示的是TTBR1_EL1的<br>这样设置之后,0x0000_开头的地址都走TTBR0_EL1进行地址翻译,0xFFFFF_开头的地址就都走TTBR1_EL1进行地址翻译。<br>Aarch64的tcr相关的定义都在arch/arm64/include/asm/pgtable-hwdef.h<br>虚拟地址的位宽在linux用CONFIG_ARM64_VA_BITS定义</p>\n<h3 id=\"IPS(Intermediate-Physical-Address-Size)\"><a href=\"#IPS(Intermediate-Physical-Address-Size)\" class=\"headerlink\" title=\"IPS(Intermediate Physical Address Size)\"></a>IPS(Intermediate Physical Address Size)</h3><p>中间级物理地址大小<br>表示物理地址的范围:</p>\n<ul>\n<li>000 32 bits, 4 GB.</li>\n<li>001 36 bits, 64 GB.</li>\n<li>010 40 bits, 1 TB.</li>\n<li>011 42 bits, 4 TB.</li>\n<li>100 44 bits, 16 TB.</li>\n<li>101 48 bits, 256 TB.</li>\n</ul>\n<h3 id=\"TG(Granule-size)\"><a href=\"#TG(Granule-size)\" class=\"headerlink\" title=\"TG(Granule size)\"></a>TG(Granule size)</h3><p>寻址的地址粒度(在Linux场景下,就是page_size对应的大小)<br>01 16KByte<br>10 4KByte<br>11 64KByte</p>\n<h2 id=\"MAIR-Memory-Attribute-Indirection-Register\"><a href=\"#MAIR-Memory-Attribute-Indirection-Register\" class=\"headerlink\" title=\"MAIR (Memory Attribute Indirection Register)\"></a>MAIR (Memory Attribute Indirection Register)</h2><p>表示内存的属性。<br><img src=\"/images/MMU/MAIR_EL1-1.png\" alt=\"TCR寄存器\"><br>MAIR_ELx可以定义8种不同的属性。每种属性占8bit。8个bit分为前4个bit和后4个bit分别定义了不同的属性。<br><img src=\"/images/MMU/MAIR_EL1-2.png\" alt=\"TCR寄存器\"><br><img src=\"/images/MMU/MAIR_EL1-3.png\" alt=\"TCR寄存器\"></p>\n<p>上面显示的RW分别别是读写属性。如果读写属性都有,就填1就可以了。</p>\n<p>在Linux中,占了5种类型。MAIR_ELx属性在启动阶段就会设置好。设置的代码在<br>arch/arm64/mm/proc.S的__cpu_setup函数中。</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">mov_q mair, MAIR_EL1_SET</span><br></pre></td></tr></table></figure>\n\n<p>MAIR_EL1_SET定义如下:</p>\n<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTRIDX(attr, idx) ((attr) << ((idx) * 8))</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_DEVICE_nGnRnE UL(0x00)</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_DEVICE_nGnRE UL(0x04)</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_NORMAL_NC UL(0x44)</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_NORMAL_TAGGED UL(0xf0)</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_NORMAL UL(0xff)</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_ATTR_MASK UL(0xff)</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MT_NORMAL 0 </span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MT_NORMAL_TAGGED 1 </span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MT_NORMAL_NC 2 </span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MT_DEVICE_nGnRnE 3</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MT_DEVICE_nGnRE 4 </span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MAIR_EL1_SET \\</span></span><br><span class=\"line\"><span class=\"meta\"> (MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) | \\ </span></span><br><span class=\"line\"> MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) | \\ </span><br><span class=\"line\"> MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) | \\ </span><br><span class=\"line\"> MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \\ </span><br><span class=\"line\"> MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL_TAGGED)) </span><br></pre></td></tr></table></figure>\n\n<p>MAIR_ELx设置完成之后,在寻址的时候,就只需要通过lower attribute中的Attrindex中的index就可以知道这段页的内存是哪种属性了。例如如果Attrindex的值是0就是MT_NORMAL,如果是3就是MT_DEVICE_nGnRnE这种类型的。<br><img src=\"/images/MMU/PTE-1.png\" alt=\"TCR寄存器\"><br><img src=\"/images/MMU/PTE-2.png\" alt=\"TCR寄存器\"></p>\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p>TTBR寄存器中asid的作用<br><a href=\"https://blog.csdn.net/weixin_42135087/article/details/123369119\">https://blog.csdn.net/weixin_42135087/article/details/123369119</a></p>\n"},{"title":"Net","_content":"","source":"_posts/Net.md","raw":"---\ntitle: Net\ncategories: \n- Linux\ntags:\n- Linux Net \n---\n","slug":"Net","published":1,"date":"2024-08-16T12:53:51.256Z","updated":"2024-08-16T12:53:51.256Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfva001eqwq22fj0ctl7","content":"","cover":false,"excerpt":"","more":""},{"title":"Numa","_content":"","source":"_posts/Numa.md","raw":"---\ntitle: Numa\ncategories: \n- Linux\ntags:\n- Linux Numa\n---\n","slug":"Numa","published":1,"date":"2024-08-16T12:53:51.256Z","updated":"2024-08-16T12:53:51.256Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvb001iqwq24r3e0lvy","content":"","cover":false,"excerpt":"","more":""},{"_content":"```c\n#include <stdio.h>\n#include <stdbool.h>\n#include <errno.h>\n#include <string.h>\n#include <sys/ioctl.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <sys/mman.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <sys/syscall.h>\n\nstatic int nr_numa;\n\nstatic int open_device(const char *file)\n{\n\tint fd = open(file, O_RDWR);\n\tif (fd < 0) {\n\t\tprintf(\"open file /dev/sdma failed, err: %s\\n\", strerror(errno));\n\t\texit(1);\n\t}\n\n\treturn fd;\n}\n\nstatic bool huge_page = false;\nenum {\n MPOL_DEFAULT,\n MPOL_PREFERRED,\n MPOL_BIND,\n MPOL_INTERLEAVE,\n MPOL_LOCAL,\n MPOL_MAX, /* always last member of enum */\n};\n#define MPOL_MF_MOVE (1 << 1)\n\n#define SIZE_1M 0x100000UL\n#define SIZE_2M 0x200000UL\n\nstatic int testcase(size_t size, int fd, int src_nid, int dst_nid)\n{\n\tint ret;\n\tlong memcpy_dur;\n\tchar *src, *dst;\n\tstruct timeval start, end;\n\tsize_t alloc_size = (size + SIZE_2M - 1UL) & ~(SIZE_2M - 1UL); // align up to 2M\n\n\tint flags = MAP_PRIVATE | MAP_ANONYMOUS;\n\tif (huge_page)\n\t\tflags |= MAP_HUGETLB;\n\n\tsrc = mmap(NULL, alloc_size, PROT_WRITE | PROT_READ, flags, -1, 0);\n\tif (src == MAP_FAILED) {\n\t\tprintf(\"alloc src memory failed, %d\\n\", errno);\n\t\treturn -1;\n\t}\n\n\tdst = mmap(NULL, alloc_size, PROT_WRITE | PROT_READ, flags, -1, 0);\n\tif (dst == MAP_FAILED) {\n\t\tprintf(\"alloc dst memory failed, %d\\n\", errno);\n\t\treturn -1;\n\t}\n\n\tunsigned long nodemask = 1UL << src_nid;\n\tret = syscall(__NR_mbind, src, alloc_size, MPOL_BIND, &nodemask, nr_numa, MPOL_MF_MOVE);\n\tif (ret < 0) {\n\t\tprintf(\"mbind for src failed\\n\");\n\t\treturn -1;\n\t}\n\n\tnodemask = 1UL << dst_nid;\n\tret = syscall(__NR_mbind, dst, alloc_size, MPOL_BIND, &nodemask, nr_numa, MPOL_MF_MOVE);\n\tif (ret < 0) {\n\t\tprintf(\"mbind for dst failed\\n\");\n\t\treturn -1;\n\t}\n\n\tmemset(src, 'a', size);\n\tmemset(dst, 'b', size);\n\n\tgettimeofday(&start, NULL);\n\tmemcpy(dst, src, size);\n\tgettimeofday(&end, NULL);\n\n\tmemcpy_dur = 1000000 * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;\n \n\tprintf(\"src: %3d, dst: %3d, size: %8zd, memcpy: %12ld, %s\\n\",\n\t\tsrc_nid, dst_nid, size, memcpy_dur, huge_page ? \"huge_page\" : \"normal_page\");\n\n\treturn 0;\n}\n\nint main(int argc, char **argv)\n{\n\tint ret, pasid;\n\tint src_nid, dst_nid;\n\n\tif (argc < 6) {\n\t\tprintf(\"invalid input!\\n\"\n\t\t\t\"Usage:\\n\\t%s <dev_file> <size> <src_nid> <dst_nid> <nr_numa> [huge_page]\\n\",\n\t\t\targv[0]);\n\t\treturn -1;\n\t}\n\n\tif (argc == 7)\n\t\thuge_page = true;\n\n\tint fd = open_device(argv[1]);\n\tif (fd < 0) {\n\t\tperror(argv[1]);\n\t\texit(1);\n\t}\n\tsize_t size = atoi(argv[2]);\n\tsrc_nid = atoi(argv[3]);\n\tdst_nid = atoi(argv[4]);\n\tnr_numa = atoi(argv[5]);\n\n\ttestcase(size, fd, src_nid, dst_nid);\n\n\tclose(fd);\n\n\treturn 0;\n}\n\n```\n","source":"_posts/NumaPerf.md","raw":"```c\n#include <stdio.h>\n#include <stdbool.h>\n#include <errno.h>\n#include <string.h>\n#include <sys/ioctl.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <sys/mman.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <sys/syscall.h>\n\nstatic int nr_numa;\n\nstatic int open_device(const char *file)\n{\n\tint fd = open(file, O_RDWR);\n\tif (fd < 0) {\n\t\tprintf(\"open file /dev/sdma failed, err: %s\\n\", strerror(errno));\n\t\texit(1);\n\t}\n\n\treturn fd;\n}\n\nstatic bool huge_page = false;\nenum {\n MPOL_DEFAULT,\n MPOL_PREFERRED,\n MPOL_BIND,\n MPOL_INTERLEAVE,\n MPOL_LOCAL,\n MPOL_MAX, /* always last member of enum */\n};\n#define MPOL_MF_MOVE (1 << 1)\n\n#define SIZE_1M 0x100000UL\n#define SIZE_2M 0x200000UL\n\nstatic int testcase(size_t size, int fd, int src_nid, int dst_nid)\n{\n\tint ret;\n\tlong memcpy_dur;\n\tchar *src, *dst;\n\tstruct timeval start, end;\n\tsize_t alloc_size = (size + SIZE_2M - 1UL) & ~(SIZE_2M - 1UL); // align up to 2M\n\n\tint flags = MAP_PRIVATE | MAP_ANONYMOUS;\n\tif (huge_page)\n\t\tflags |= MAP_HUGETLB;\n\n\tsrc = mmap(NULL, alloc_size, PROT_WRITE | PROT_READ, flags, -1, 0);\n\tif (src == MAP_FAILED) {\n\t\tprintf(\"alloc src memory failed, %d\\n\", errno);\n\t\treturn -1;\n\t}\n\n\tdst = mmap(NULL, alloc_size, PROT_WRITE | PROT_READ, flags, -1, 0);\n\tif (dst == MAP_FAILED) {\n\t\tprintf(\"alloc dst memory failed, %d\\n\", errno);\n\t\treturn -1;\n\t}\n\n\tunsigned long nodemask = 1UL << src_nid;\n\tret = syscall(__NR_mbind, src, alloc_size, MPOL_BIND, &nodemask, nr_numa, MPOL_MF_MOVE);\n\tif (ret < 0) {\n\t\tprintf(\"mbind for src failed\\n\");\n\t\treturn -1;\n\t}\n\n\tnodemask = 1UL << dst_nid;\n\tret = syscall(__NR_mbind, dst, alloc_size, MPOL_BIND, &nodemask, nr_numa, MPOL_MF_MOVE);\n\tif (ret < 0) {\n\t\tprintf(\"mbind for dst failed\\n\");\n\t\treturn -1;\n\t}\n\n\tmemset(src, 'a', size);\n\tmemset(dst, 'b', size);\n\n\tgettimeofday(&start, NULL);\n\tmemcpy(dst, src, size);\n\tgettimeofday(&end, NULL);\n\n\tmemcpy_dur = 1000000 * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;\n \n\tprintf(\"src: %3d, dst: %3d, size: %8zd, memcpy: %12ld, %s\\n\",\n\t\tsrc_nid, dst_nid, size, memcpy_dur, huge_page ? \"huge_page\" : \"normal_page\");\n\n\treturn 0;\n}\n\nint main(int argc, char **argv)\n{\n\tint ret, pasid;\n\tint src_nid, dst_nid;\n\n\tif (argc < 6) {\n\t\tprintf(\"invalid input!\\n\"\n\t\t\t\"Usage:\\n\\t%s <dev_file> <size> <src_nid> <dst_nid> <nr_numa> [huge_page]\\n\",\n\t\t\targv[0]);\n\t\treturn -1;\n\t}\n\n\tif (argc == 7)\n\t\thuge_page = true;\n\n\tint fd = open_device(argv[1]);\n\tif (fd < 0) {\n\t\tperror(argv[1]);\n\t\texit(1);\n\t}\n\tsize_t size = atoi(argv[2]);\n\tsrc_nid = atoi(argv[3]);\n\tdst_nid = atoi(argv[4]);\n\tnr_numa = atoi(argv[5]);\n\n\ttestcase(size, fd, src_nid, dst_nid);\n\n\tclose(fd);\n\n\treturn 0;\n}\n\n```\n","slug":"NumaPerf","published":1,"date":"2024-08-14T10:01:22.766Z","updated":"2024-08-14T10:01:22.766Z","title":"","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvb001lqwq265p4g8uu","content":"<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br><span class=\"line\">60</span><br><span class=\"line\">61</span><br><span class=\"line\">62</span><br><span class=\"line\">63</span><br><span class=\"line\">64</span><br><span class=\"line\">65</span><br><span class=\"line\">66</span><br><span class=\"line\">67</span><br><span class=\"line\">68</span><br><span class=\"line\">69</span><br><span class=\"line\">70</span><br><span class=\"line\">71</span><br><span class=\"line\">72</span><br><span class=\"line\">73</span><br><span class=\"line\">74</span><br><span class=\"line\">75</span><br><span class=\"line\">76</span><br><span class=\"line\">77</span><br><span class=\"line\">78</span><br><span class=\"line\">79</span><br><span class=\"line\">80</span><br><span class=\"line\">81</span><br><span class=\"line\">82</span><br><span class=\"line\">83</span><br><span class=\"line\">84</span><br><span class=\"line\">85</span><br><span class=\"line\">86</span><br><span class=\"line\">87</span><br><span class=\"line\">88</span><br><span class=\"line\">89</span><br><span class=\"line\">90</span><br><span class=\"line\">91</span><br><span class=\"line\">92</span><br><span class=\"line\">93</span><br><span class=\"line\">94</span><br><span class=\"line\">95</span><br><span class=\"line\">96</span><br><span class=\"line\">97</span><br><span class=\"line\">98</span><br><span class=\"line\">99</span><br><span class=\"line\">100</span><br><span class=\"line\">101</span><br><span class=\"line\">102</span><br><span class=\"line\">103</span><br><span class=\"line\">104</span><br><span class=\"line\">105</span><br><span class=\"line\">106</span><br><span class=\"line\">107</span><br><span class=\"line\">108</span><br><span class=\"line\">109</span><br><span class=\"line\">110</span><br><span class=\"line\">111</span><br><span class=\"line\">112</span><br><span class=\"line\">113</span><br><span class=\"line\">114</span><br><span class=\"line\">115</span><br><span class=\"line\">116</span><br><span class=\"line\">117</span><br><span class=\"line\">118</span><br><span class=\"line\">119</span><br><span class=\"line\">120</span><br><span class=\"line\">121</span><br><span class=\"line\">122</span><br><span class=\"line\">123</span><br><span class=\"line\">124</span><br><span class=\"line\">125</span><br><span class=\"line\">126</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><stdio.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><stdbool.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><errno.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><string.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/ioctl.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/types.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/stat.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/time.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/mman.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><fcntl.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><unistd.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><stdlib.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/syscall.h></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"type\">int</span> nr_numa;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"type\">int</span> <span class=\"title function_\">open_device</span><span class=\"params\">(<span class=\"type\">const</span> <span class=\"type\">char</span> *file)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\t<span class=\"type\">int</span> fd = open(file, O_RDWR);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (fd < <span class=\"number\">0</span>) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"open file /dev/sdma failed, err: %s\\n"</span>, strerror(errno));</span><br><span class=\"line\">\t\t<span class=\"built_in\">exit</span>(<span class=\"number\">1</span>);</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">return</span> fd;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"type\">bool</span> huge_page = <span class=\"literal\">false</span>;</span><br><span class=\"line\"><span class=\"class\"><span class=\"keyword\">enum</span> {</span></span><br><span class=\"line\"> MPOL_DEFAULT,</span><br><span class=\"line\"> MPOL_PREFERRED,</span><br><span class=\"line\"> MPOL_BIND,</span><br><span class=\"line\"> MPOL_INTERLEAVE,</span><br><span class=\"line\"> MPOL_LOCAL,</span><br><span class=\"line\"> MPOL_MAX, <span class=\"comment\">/* always last member of enum */</span></span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MPOL_MF_MOVE (1 << 1)</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> SIZE_1M 0x100000UL</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> SIZE_2M 0x200000UL</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"type\">int</span> <span class=\"title function_\">testcase</span><span class=\"params\">(<span class=\"type\">size_t</span> size, <span class=\"type\">int</span> fd, <span class=\"type\">int</span> src_nid, <span class=\"type\">int</span> dst_nid)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\t<span class=\"type\">int</span> ret;</span><br><span class=\"line\">\t<span class=\"type\">long</span> memcpy_dur;</span><br><span class=\"line\">\t<span class=\"type\">char</span> *src, *dst;</span><br><span class=\"line\">\t<span class=\"class\"><span class=\"keyword\">struct</span> <span class=\"title\">timeval</span> <span class=\"title\">start</span>, <span class=\"title\">end</span>;</span></span><br><span class=\"line\">\t<span class=\"type\">size_t</span> alloc_size = (size + SIZE_2M - <span class=\"number\">1UL</span>) & ~(SIZE_2M - <span class=\"number\">1UL</span>); <span class=\"comment\">// align up to 2M</span></span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"type\">int</span> flags = MAP_PRIVATE | MAP_ANONYMOUS;</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (huge_page)</span><br><span class=\"line\">\t\tflags |= MAP_HUGETLB;</span><br><span class=\"line\"></span><br><span class=\"line\">\tsrc = mmap(<span class=\"literal\">NULL</span>, alloc_size, PROT_WRITE | PROT_READ, flags, <span class=\"number\">-1</span>, <span class=\"number\">0</span>);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (src == MAP_FAILED) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"alloc src memory failed, %d\\n"</span>, errno);</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> <span class=\"number\">-1</span>;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\tdst = mmap(<span class=\"literal\">NULL</span>, alloc_size, PROT_WRITE | PROT_READ, flags, <span class=\"number\">-1</span>, <span class=\"number\">0</span>);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (dst == MAP_FAILED) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"alloc dst memory failed, %d\\n"</span>, errno);</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> <span class=\"number\">-1</span>;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"type\">unsigned</span> <span class=\"type\">long</span> nodemask = <span class=\"number\">1UL</span> << src_nid;</span><br><span class=\"line\">\tret = syscall(__NR_mbind, src, alloc_size, MPOL_BIND, &nodemask, nr_numa, MPOL_MF_MOVE);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (ret < <span class=\"number\">0</span>) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"mbind for src failed\\n"</span>);</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> <span class=\"number\">-1</span>;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\tnodemask = <span class=\"number\">1UL</span> << dst_nid;</span><br><span class=\"line\">\tret = syscall(__NR_mbind, dst, alloc_size, MPOL_BIND, &nodemask, nr_numa, MPOL_MF_MOVE);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (ret < <span class=\"number\">0</span>) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"mbind for dst failed\\n"</span>);</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> <span class=\"number\">-1</span>;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"built_in\">memset</span>(src, <span class=\"string\">'a'</span>, size);</span><br><span class=\"line\">\t<span class=\"built_in\">memset</span>(dst, <span class=\"string\">'b'</span>, size);</span><br><span class=\"line\"></span><br><span class=\"line\">\tgettimeofday(&start, <span class=\"literal\">NULL</span>);</span><br><span class=\"line\">\t<span class=\"built_in\">memcpy</span>(dst, src, size);</span><br><span class=\"line\">\tgettimeofday(&end, <span class=\"literal\">NULL</span>);</span><br><span class=\"line\"></span><br><span class=\"line\">\tmemcpy_dur = <span class=\"number\">1000000</span> * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;</span><br><span class=\"line\"> </span><br><span class=\"line\">\t<span class=\"built_in\">printf</span>(<span class=\"string\">"src: %3d, dst: %3d, size: %8zd, memcpy: %12ld, %s\\n"</span>,</span><br><span class=\"line\">\t\tsrc_nid, dst_nid, size, memcpy_dur, huge_page ? <span class=\"string\">"huge_page"</span> : <span class=\"string\">"normal_page"</span>);</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">int</span> <span class=\"title function_\">main</span><span class=\"params\">(<span class=\"type\">int</span> argc, <span class=\"type\">char</span> **argv)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\t<span class=\"type\">int</span> ret, pasid;</span><br><span class=\"line\">\t<span class=\"type\">int</span> src_nid, dst_nid;</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (argc < <span class=\"number\">6</span>) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"invalid input!\\n"</span></span><br><span class=\"line\">\t\t\t<span class=\"string\">"Usage:\\n\\t%s <dev_file> <size> <src_nid> <dst_nid> <nr_numa> [huge_page]\\n"</span>,</span><br><span class=\"line\">\t\t\targv[<span class=\"number\">0</span>]);</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> <span class=\"number\">-1</span>;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (argc == <span class=\"number\">7</span>)</span><br><span class=\"line\">\t\thuge_page = <span class=\"literal\">true</span>;</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"type\">int</span> fd = open_device(argv[<span class=\"number\">1</span>]);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (fd < <span class=\"number\">0</span>) {</span><br><span class=\"line\">\t\tperror(argv[<span class=\"number\">1</span>]);</span><br><span class=\"line\">\t\t<span class=\"built_in\">exit</span>(<span class=\"number\">1</span>);</span><br><span class=\"line\">\t}</span><br><span class=\"line\">\t<span class=\"type\">size_t</span> size = atoi(argv[<span class=\"number\">2</span>]);</span><br><span class=\"line\">\tsrc_nid = atoi(argv[<span class=\"number\">3</span>]);</span><br><span class=\"line\">\tdst_nid = atoi(argv[<span class=\"number\">4</span>]);</span><br><span class=\"line\">\tnr_numa = atoi(argv[<span class=\"number\">5</span>]);</span><br><span class=\"line\"></span><br><span class=\"line\">\ttestcase(size, fd, src_nid, dst_nid);</span><br><span class=\"line\"></span><br><span class=\"line\">\tclose(fd);</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br></pre></td></tr></table></figure>\n","cover":false,"excerpt":"","more":"<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br><span class=\"line\">60</span><br><span class=\"line\">61</span><br><span class=\"line\">62</span><br><span class=\"line\">63</span><br><span class=\"line\">64</span><br><span class=\"line\">65</span><br><span class=\"line\">66</span><br><span class=\"line\">67</span><br><span class=\"line\">68</span><br><span class=\"line\">69</span><br><span class=\"line\">70</span><br><span class=\"line\">71</span><br><span class=\"line\">72</span><br><span class=\"line\">73</span><br><span class=\"line\">74</span><br><span class=\"line\">75</span><br><span class=\"line\">76</span><br><span class=\"line\">77</span><br><span class=\"line\">78</span><br><span class=\"line\">79</span><br><span class=\"line\">80</span><br><span class=\"line\">81</span><br><span class=\"line\">82</span><br><span class=\"line\">83</span><br><span class=\"line\">84</span><br><span class=\"line\">85</span><br><span class=\"line\">86</span><br><span class=\"line\">87</span><br><span class=\"line\">88</span><br><span class=\"line\">89</span><br><span class=\"line\">90</span><br><span class=\"line\">91</span><br><span class=\"line\">92</span><br><span class=\"line\">93</span><br><span class=\"line\">94</span><br><span class=\"line\">95</span><br><span class=\"line\">96</span><br><span class=\"line\">97</span><br><span class=\"line\">98</span><br><span class=\"line\">99</span><br><span class=\"line\">100</span><br><span class=\"line\">101</span><br><span class=\"line\">102</span><br><span class=\"line\">103</span><br><span class=\"line\">104</span><br><span class=\"line\">105</span><br><span class=\"line\">106</span><br><span class=\"line\">107</span><br><span class=\"line\">108</span><br><span class=\"line\">109</span><br><span class=\"line\">110</span><br><span class=\"line\">111</span><br><span class=\"line\">112</span><br><span class=\"line\">113</span><br><span class=\"line\">114</span><br><span class=\"line\">115</span><br><span class=\"line\">116</span><br><span class=\"line\">117</span><br><span class=\"line\">118</span><br><span class=\"line\">119</span><br><span class=\"line\">120</span><br><span class=\"line\">121</span><br><span class=\"line\">122</span><br><span class=\"line\">123</span><br><span class=\"line\">124</span><br><span class=\"line\">125</span><br><span class=\"line\">126</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><stdio.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><stdbool.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><errno.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><string.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/ioctl.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/types.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/stat.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/time.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/mman.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><fcntl.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><unistd.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><stdlib.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><sys/syscall.h></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"type\">int</span> nr_numa;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"type\">int</span> <span class=\"title function_\">open_device</span><span class=\"params\">(<span class=\"type\">const</span> <span class=\"type\">char</span> *file)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\t<span class=\"type\">int</span> fd = open(file, O_RDWR);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (fd < <span class=\"number\">0</span>) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"open file /dev/sdma failed, err: %s\\n"</span>, strerror(errno));</span><br><span class=\"line\">\t\t<span class=\"built_in\">exit</span>(<span class=\"number\">1</span>);</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">return</span> fd;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"type\">bool</span> huge_page = <span class=\"literal\">false</span>;</span><br><span class=\"line\"><span class=\"class\"><span class=\"keyword\">enum</span> {</span></span><br><span class=\"line\"> MPOL_DEFAULT,</span><br><span class=\"line\"> MPOL_PREFERRED,</span><br><span class=\"line\"> MPOL_BIND,</span><br><span class=\"line\"> MPOL_INTERLEAVE,</span><br><span class=\"line\"> MPOL_LOCAL,</span><br><span class=\"line\"> MPOL_MAX, <span class=\"comment\">/* always last member of enum */</span></span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> MPOL_MF_MOVE (1 << 1)</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> SIZE_1M 0x100000UL</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> SIZE_2M 0x200000UL</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"type\">int</span> <span class=\"title function_\">testcase</span><span class=\"params\">(<span class=\"type\">size_t</span> size, <span class=\"type\">int</span> fd, <span class=\"type\">int</span> src_nid, <span class=\"type\">int</span> dst_nid)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\t<span class=\"type\">int</span> ret;</span><br><span class=\"line\">\t<span class=\"type\">long</span> memcpy_dur;</span><br><span class=\"line\">\t<span class=\"type\">char</span> *src, *dst;</span><br><span class=\"line\">\t<span class=\"class\"><span class=\"keyword\">struct</span> <span class=\"title\">timeval</span> <span class=\"title\">start</span>, <span class=\"title\">end</span>;</span></span><br><span class=\"line\">\t<span class=\"type\">size_t</span> alloc_size = (size + SIZE_2M - <span class=\"number\">1UL</span>) & ~(SIZE_2M - <span class=\"number\">1UL</span>); <span class=\"comment\">// align up to 2M</span></span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"type\">int</span> flags = MAP_PRIVATE | MAP_ANONYMOUS;</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (huge_page)</span><br><span class=\"line\">\t\tflags |= MAP_HUGETLB;</span><br><span class=\"line\"></span><br><span class=\"line\">\tsrc = mmap(<span class=\"literal\">NULL</span>, alloc_size, PROT_WRITE | PROT_READ, flags, <span class=\"number\">-1</span>, <span class=\"number\">0</span>);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (src == MAP_FAILED) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"alloc src memory failed, %d\\n"</span>, errno);</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> <span class=\"number\">-1</span>;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\tdst = mmap(<span class=\"literal\">NULL</span>, alloc_size, PROT_WRITE | PROT_READ, flags, <span class=\"number\">-1</span>, <span class=\"number\">0</span>);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (dst == MAP_FAILED) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"alloc dst memory failed, %d\\n"</span>, errno);</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> <span class=\"number\">-1</span>;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"type\">unsigned</span> <span class=\"type\">long</span> nodemask = <span class=\"number\">1UL</span> << src_nid;</span><br><span class=\"line\">\tret = syscall(__NR_mbind, src, alloc_size, MPOL_BIND, &nodemask, nr_numa, MPOL_MF_MOVE);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (ret < <span class=\"number\">0</span>) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"mbind for src failed\\n"</span>);</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> <span class=\"number\">-1</span>;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\tnodemask = <span class=\"number\">1UL</span> << dst_nid;</span><br><span class=\"line\">\tret = syscall(__NR_mbind, dst, alloc_size, MPOL_BIND, &nodemask, nr_numa, MPOL_MF_MOVE);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (ret < <span class=\"number\">0</span>) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"mbind for dst failed\\n"</span>);</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> <span class=\"number\">-1</span>;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"built_in\">memset</span>(src, <span class=\"string\">'a'</span>, size);</span><br><span class=\"line\">\t<span class=\"built_in\">memset</span>(dst, <span class=\"string\">'b'</span>, size);</span><br><span class=\"line\"></span><br><span class=\"line\">\tgettimeofday(&start, <span class=\"literal\">NULL</span>);</span><br><span class=\"line\">\t<span class=\"built_in\">memcpy</span>(dst, src, size);</span><br><span class=\"line\">\tgettimeofday(&end, <span class=\"literal\">NULL</span>);</span><br><span class=\"line\"></span><br><span class=\"line\">\tmemcpy_dur = <span class=\"number\">1000000</span> * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;</span><br><span class=\"line\"> </span><br><span class=\"line\">\t<span class=\"built_in\">printf</span>(<span class=\"string\">"src: %3d, dst: %3d, size: %8zd, memcpy: %12ld, %s\\n"</span>,</span><br><span class=\"line\">\t\tsrc_nid, dst_nid, size, memcpy_dur, huge_page ? <span class=\"string\">"huge_page"</span> : <span class=\"string\">"normal_page"</span>);</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">int</span> <span class=\"title function_\">main</span><span class=\"params\">(<span class=\"type\">int</span> argc, <span class=\"type\">char</span> **argv)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\t<span class=\"type\">int</span> ret, pasid;</span><br><span class=\"line\">\t<span class=\"type\">int</span> src_nid, dst_nid;</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (argc < <span class=\"number\">6</span>) {</span><br><span class=\"line\">\t\t<span class=\"built_in\">printf</span>(<span class=\"string\">"invalid input!\\n"</span></span><br><span class=\"line\">\t\t\t<span class=\"string\">"Usage:\\n\\t%s <dev_file> <size> <src_nid> <dst_nid> <nr_numa> [huge_page]\\n"</span>,</span><br><span class=\"line\">\t\t\targv[<span class=\"number\">0</span>]);</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> <span class=\"number\">-1</span>;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (argc == <span class=\"number\">7</span>)</span><br><span class=\"line\">\t\thuge_page = <span class=\"literal\">true</span>;</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"type\">int</span> fd = open_device(argv[<span class=\"number\">1</span>]);</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (fd < <span class=\"number\">0</span>) {</span><br><span class=\"line\">\t\tperror(argv[<span class=\"number\">1</span>]);</span><br><span class=\"line\">\t\t<span class=\"built_in\">exit</span>(<span class=\"number\">1</span>);</span><br><span class=\"line\">\t}</span><br><span class=\"line\">\t<span class=\"type\">size_t</span> size = atoi(argv[<span class=\"number\">2</span>]);</span><br><span class=\"line\">\tsrc_nid = atoi(argv[<span class=\"number\">3</span>]);</span><br><span class=\"line\">\tdst_nid = atoi(argv[<span class=\"number\">4</span>]);</span><br><span class=\"line\">\tnr_numa = atoi(argv[<span class=\"number\">5</span>]);</span><br><span class=\"line\"></span><br><span class=\"line\">\ttestcase(size, fd, src_nid, dst_nid);</span><br><span class=\"line\"></span><br><span class=\"line\">\tclose(fd);</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br></pre></td></tr></table></figure>\n"},{"title":"Perf","_content":"## perf命令\n### stat\n记录给定条件下事件的发生次数\n参数:\n- -p 指定待分析进程的 pid(可以是多个,用,分隔列表)\n- -t 指定待分析线程的 tid(可以是多个,用,分隔列表)\n- -a 从所有 CPU 收集系统数据\n- -d -d:打印更详细的信息,可重复 3 次;\n追加显示L1 和 LLC data cache\n- -d -d 追加显示dTLB 和 iTLB events\n- -d -d -d 追加 prefetch events\n- -r 重复运行命令 n 次,打印平均值。n 设为 0 时无限循环打印\n- -c 只统计指定 CPU 列表的数据,如:0,1,3或1-2\n- -A 与-a选项联用,不要将 CPU 计数聚合\n\n输出结果分析:\n- Task-clock-msecs:CPU 利用率,该值高,说明程序的多数时间花费在 CPU 计算上而非 IO。\n- Context-switches:进程切换次数,记录了程序运行过程中发生了多少次进程切换,一般来说,频繁的进程切换有可能只是CPU正常调度下一个任务,也有可能是一些性能问题的外在表现,导致的原因可能是锁竞争,IO阻塞,硬件中断等。如果可能,频繁的进程切换是应该避免的。\n- Cache-misses:程序运行过程中总体的 cache 利用情况,对于性能敏感的程序来说,需要避免出现cache miss的情况。解决方法是对于程序频繁访问的热数据可以集中紧凑存储、程序不去大跨度离散的访问内存等等。\n- CPU-migrations:表示进程 t1 运行过程中发生了多少次 CPU 迁移,即被调度器从一个 CPU 转移到另外一个 CPU 上运行。\n- Cycles:处理器时钟,一条机器指令可能需要多个 cycles。\n- Instructions: 机器指令数目。\n- branches:为分支数量。\n- branch-misses:为分支预测时失败的数量。\n\n### record\n#### lock\n内核锁性能\n需要编译选项的支持:CONFIG_LOCKDEP、CONFIG_LOCK_STAT。\nCONFIG_LOCKDEP :defines acquired and release events.\nCONFIG_LOCK_STAT :defines contended and acquired lock events.\n-i 输入文件\n-k sorting key,默认为acquired,还可以按contended、wait_total、wait_max和wait_min来\n\n执行命令:\n1. perf lock record ./xxx\n2. perf lock report\n\n结果分析:\n- Name 内核锁的名字\n- aquired 该锁被直接获得的次数,因为没有其它内核路径占用该锁,此时不用等待。\n- contended 该锁等待后获得的次数,此时被其它内核路径占用,需要等待\n- total wait 为了获得该锁,总共的等待时间。\n- max wait 为了获得该锁,最大的等待时间\n- min wait 为了获得该锁,最小的等待时间。\n\n#### kmem\nslab分配器性能分析\n执行命令:\n1. perf kmem record ./xxx\n2. perf kmem stat --caller --alloc -l 20\n结果分析:\n- Callsite 内核代码中调用kmalloc和kfree的地方\n- Total_alloc/Per 总共分配的内存大小,平均每次分配的内存大小\n- Total_req/Per 总共请求的内存大小,平均每次请求的内存大小\n- Hit 调用的次数\n- Ping-pong kmalloc和kfree不被同一个CPU执行时的次数,这会导致cache效率降低。\n- Frag 碎片所占的百分比,碎片 = 分配的内存 - 请求的内存,这部分是浪费的。\n- Alloc Ptr 有使用--alloc选项,还会看到此列,即所分配内存的地址(案例未使用)\n\n#### sched\n执行命令记录1秒钟的调度事件:\n```bash\nperf sched record -- sleep 1\n```\n执行以下命令可以对生成的recored进行分析:\n1. perf sched map\n2. perf sched timehist\n3. \n### top\n主要用于实时剖析各个函数在某个性能事件上的热度。利用perf top,能够直观地观察到当前的热点函数,并利用工具中内置的annotate功能,进一步查找热点指令\n\n### diff\n\n### timechart\n\n由于perf timechart只记录线程粒度的信息,无法替代火焰图在函数级别上分析,需要结合火焰图一\n起使用\n\n### probe\n可以在程序中添加或者删除动态追踪点,即自定义事件。\n例如给malloc/free等添加事件来追踪内存泄露情况:\n```bash\nperf probe --exec=/lib64/libc-2.17.so --add malloc\n或者\n# perf stat -e probe_libc:free -e probe_libc:malloc -ag -p $(pgrep $process_name$) sleep 4\n```\n\nprobe也可以在(内核)函数的某一行添加事件进行追踪:\n例如在schedule函数的12行处增加一个探测点\n```bash\nperf probe -a schedule:12\n```\n\n若需要对自定义函数进行跟踪,和上文相似,假设我们定义了一个名为loop的函数\n```bash\n#perf probe -x /root/code/test-perf-probe.o \"--add=loop\"\n```\n执行之后会显示:\n```bash\nAdded new event: probe_test_perf_probe:loop (on loop in /root/code/test_perf_probe.o)\n```\n然后就可以执行perf工具记录:\n```bash\nperf record -e probe_test_perf_probe:loop -aR sleep 1\n```\n\n## 火焰图\n\n## 参考\n\nhttps://www.brendangregg.com/perf.html\n\nhttps://www.brendangregg.com/perf.html\n","source":"_posts/Perf.md","raw":"---\ntitle: Perf\ncategories: \n- Linux\ntags:\n- Linux Perf\n---\n## perf命令\n### stat\n记录给定条件下事件的发生次数\n参数:\n- -p 指定待分析进程的 pid(可以是多个,用,分隔列表)\n- -t 指定待分析线程的 tid(可以是多个,用,分隔列表)\n- -a 从所有 CPU 收集系统数据\n- -d -d:打印更详细的信息,可重复 3 次;\n追加显示L1 和 LLC data cache\n- -d -d 追加显示dTLB 和 iTLB events\n- -d -d -d 追加 prefetch events\n- -r 重复运行命令 n 次,打印平均值。n 设为 0 时无限循环打印\n- -c 只统计指定 CPU 列表的数据,如:0,1,3或1-2\n- -A 与-a选项联用,不要将 CPU 计数聚合\n\n输出结果分析:\n- Task-clock-msecs:CPU 利用率,该值高,说明程序的多数时间花费在 CPU 计算上而非 IO。\n- Context-switches:进程切换次数,记录了程序运行过程中发生了多少次进程切换,一般来说,频繁的进程切换有可能只是CPU正常调度下一个任务,也有可能是一些性能问题的外在表现,导致的原因可能是锁竞争,IO阻塞,硬件中断等。如果可能,频繁的进程切换是应该避免的。\n- Cache-misses:程序运行过程中总体的 cache 利用情况,对于性能敏感的程序来说,需要避免出现cache miss的情况。解决方法是对于程序频繁访问的热数据可以集中紧凑存储、程序不去大跨度离散的访问内存等等。\n- CPU-migrations:表示进程 t1 运行过程中发生了多少次 CPU 迁移,即被调度器从一个 CPU 转移到另外一个 CPU 上运行。\n- Cycles:处理器时钟,一条机器指令可能需要多个 cycles。\n- Instructions: 机器指令数目。\n- branches:为分支数量。\n- branch-misses:为分支预测时失败的数量。\n\n### record\n#### lock\n内核锁性能\n需要编译选项的支持:CONFIG_LOCKDEP、CONFIG_LOCK_STAT。\nCONFIG_LOCKDEP :defines acquired and release events.\nCONFIG_LOCK_STAT :defines contended and acquired lock events.\n-i 输入文件\n-k sorting key,默认为acquired,还可以按contended、wait_total、wait_max和wait_min来\n\n执行命令:\n1. perf lock record ./xxx\n2. perf lock report\n\n结果分析:\n- Name 内核锁的名字\n- aquired 该锁被直接获得的次数,因为没有其它内核路径占用该锁,此时不用等待。\n- contended 该锁等待后获得的次数,此时被其它内核路径占用,需要等待\n- total wait 为了获得该锁,总共的等待时间。\n- max wait 为了获得该锁,最大的等待时间\n- min wait 为了获得该锁,最小的等待时间。\n\n#### kmem\nslab分配器性能分析\n执行命令:\n1. perf kmem record ./xxx\n2. perf kmem stat --caller --alloc -l 20\n结果分析:\n- Callsite 内核代码中调用kmalloc和kfree的地方\n- Total_alloc/Per 总共分配的内存大小,平均每次分配的内存大小\n- Total_req/Per 总共请求的内存大小,平均每次请求的内存大小\n- Hit 调用的次数\n- Ping-pong kmalloc和kfree不被同一个CPU执行时的次数,这会导致cache效率降低。\n- Frag 碎片所占的百分比,碎片 = 分配的内存 - 请求的内存,这部分是浪费的。\n- Alloc Ptr 有使用--alloc选项,还会看到此列,即所分配内存的地址(案例未使用)\n\n#### sched\n执行命令记录1秒钟的调度事件:\n```bash\nperf sched record -- sleep 1\n```\n执行以下命令可以对生成的recored进行分析:\n1. perf sched map\n2. perf sched timehist\n3. \n### top\n主要用于实时剖析各个函数在某个性能事件上的热度。利用perf top,能够直观地观察到当前的热点函数,并利用工具中内置的annotate功能,进一步查找热点指令\n\n### diff\n\n### timechart\n\n由于perf timechart只记录线程粒度的信息,无法替代火焰图在函数级别上分析,需要结合火焰图一\n起使用\n\n### probe\n可以在程序中添加或者删除动态追踪点,即自定义事件。\n例如给malloc/free等添加事件来追踪内存泄露情况:\n```bash\nperf probe --exec=/lib64/libc-2.17.so --add malloc\n或者\n# perf stat -e probe_libc:free -e probe_libc:malloc -ag -p $(pgrep $process_name$) sleep 4\n```\n\nprobe也可以在(内核)函数的某一行添加事件进行追踪:\n例如在schedule函数的12行处增加一个探测点\n```bash\nperf probe -a schedule:12\n```\n\n若需要对自定义函数进行跟踪,和上文相似,假设我们定义了一个名为loop的函数\n```bash\n#perf probe -x /root/code/test-perf-probe.o \"--add=loop\"\n```\n执行之后会显示:\n```bash\nAdded new event: probe_test_perf_probe:loop (on loop in /root/code/test_perf_probe.o)\n```\n然后就可以执行perf工具记录:\n```bash\nperf record -e probe_test_perf_probe:loop -aR sleep 1\n```\n\n## 火焰图\n\n## 参考\n\nhttps://www.brendangregg.com/perf.html\n\nhttps://www.brendangregg.com/perf.html\n","slug":"Perf","published":1,"date":"2024-08-14T10:01:22.766Z","updated":"2024-08-14T10:01:22.766Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvb001oqwq2gl716v3p","content":"<h2 id=\"perf命令\"><a href=\"#perf命令\" class=\"headerlink\" title=\"perf命令\"></a>perf命令</h2><h3 id=\"stat\"><a href=\"#stat\" class=\"headerlink\" title=\"stat\"></a>stat</h3><p>记录给定条件下事件的发生次数<br>参数:</p>\n<ul>\n<li>-p 指定待分析进程的 pid(可以是多个,用,分隔列表)</li>\n<li>-t 指定待分析线程的 tid(可以是多个,用,分隔列表)</li>\n<li>-a 从所有 CPU 收集系统数据</li>\n<li>-d -d:打印更详细的信息,可重复 3 次;<br>追加显示L1 和 LLC data cache</li>\n<li>-d -d 追加显示dTLB 和 iTLB events</li>\n<li>-d -d -d 追加 prefetch events</li>\n<li>-r 重复运行命令 n 次,打印平均值。n 设为 0 时无限循环打印</li>\n<li>-c 只统计指定 CPU 列表的数据,如:0,1,3或1-2</li>\n<li>-A 与-a选项联用,不要将 CPU 计数聚合</li>\n</ul>\n<p>输出结果分析:</p>\n<ul>\n<li>Task-clock-msecs:CPU 利用率,该值高,说明程序的多数时间花费在 CPU 计算上而非 IO。</li>\n<li>Context-switches:进程切换次数,记录了程序运行过程中发生了多少次进程切换,一般来说,频繁的进程切换有可能只是CPU正常调度下一个任务,也有可能是一些性能问题的外在表现,导致的原因可能是锁竞争,IO阻塞,硬件中断等。如果可能,频繁的进程切换是应该避免的。</li>\n<li>Cache-misses:程序运行过程中总体的 cache 利用情况,对于性能敏感的程序来说,需要避免出现cache miss的情况。解决方法是对于程序频繁访问的热数据可以集中紧凑存储、程序不去大跨度离散的访问内存等等。</li>\n<li>CPU-migrations:表示进程 t1 运行过程中发生了多少次 CPU 迁移,即被调度器从一个 CPU 转移到另外一个 CPU 上运行。</li>\n<li>Cycles:处理器时钟,一条机器指令可能需要多个 cycles。</li>\n<li>Instructions: 机器指令数目。</li>\n<li>branches:为分支数量。</li>\n<li>branch-misses:为分支预测时失败的数量。</li>\n</ul>\n<h3 id=\"record\"><a href=\"#record\" class=\"headerlink\" title=\"record\"></a>record</h3><h4 id=\"lock\"><a href=\"#lock\" class=\"headerlink\" title=\"lock\"></a>lock</h4><p>内核锁性能<br>需要编译选项的支持:CONFIG_LOCKDEP、CONFIG_LOCK_STAT。<br>CONFIG_LOCKDEP :defines acquired and release events.<br>CONFIG_LOCK_STAT :defines contended and acquired lock events.<br>-i 输入文件<br>-k sorting key,默认为acquired,还可以按contended、wait_total、wait_max和wait_min来</p>\n<p>执行命令:</p>\n<ol>\n<li>perf lock record ./xxx</li>\n<li>perf lock report</li>\n</ol>\n<p>结果分析:</p>\n<ul>\n<li>Name 内核锁的名字</li>\n<li>aquired 该锁被直接获得的次数,因为没有其它内核路径占用该锁,此时不用等待。</li>\n<li>contended 该锁等待后获得的次数,此时被其它内核路径占用,需要等待</li>\n<li>total wait 为了获得该锁,总共的等待时间。</li>\n<li>max wait 为了获得该锁,最大的等待时间</li>\n<li>min wait 为了获得该锁,最小的等待时间。</li>\n</ul>\n<h4 id=\"kmem\"><a href=\"#kmem\" class=\"headerlink\" title=\"kmem\"></a>kmem</h4><p>slab分配器性能分析<br>执行命令:</p>\n<ol>\n<li>perf kmem record ./xxx</li>\n<li>perf kmem stat –caller –alloc -l 20<br>结果分析:</li>\n</ol>\n<ul>\n<li>Callsite 内核代码中调用kmalloc和kfree的地方</li>\n<li>Total_alloc/Per 总共分配的内存大小,平均每次分配的内存大小</li>\n<li>Total_req/Per 总共请求的内存大小,平均每次请求的内存大小</li>\n<li>Hit 调用的次数</li>\n<li>Ping-pong kmalloc和kfree不被同一个CPU执行时的次数,这会导致cache效率降低。</li>\n<li>Frag 碎片所占的百分比,碎片 = 分配的内存 - 请求的内存,这部分是浪费的。</li>\n<li>Alloc Ptr 有使用–alloc选项,还会看到此列,即所分配内存的地址(案例未使用)</li>\n</ul>\n<h4 id=\"sched\"><a href=\"#sched\" class=\"headerlink\" title=\"sched\"></a>sched</h4><p>执行命令记录1秒钟的调度事件:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">perf <span class=\"built_in\">sched</span> record -- <span class=\"built_in\">sleep</span> 1</span><br></pre></td></tr></table></figure>\n<p>执行以下命令可以对生成的recored进行分析:</p>\n<ol>\n<li>perf sched map</li>\n<li>perf sched timehist</li>\n<li></li>\n</ol>\n<h3 id=\"top\"><a href=\"#top\" class=\"headerlink\" title=\"top\"></a>top</h3><p>主要用于实时剖析各个函数在某个性能事件上的热度。利用perf top,能够直观地观察到当前的热点函数,并利用工具中内置的annotate功能,进一步查找热点指令</p>\n<h3 id=\"diff\"><a href=\"#diff\" class=\"headerlink\" title=\"diff\"></a>diff</h3><h3 id=\"timechart\"><a href=\"#timechart\" class=\"headerlink\" title=\"timechart\"></a>timechart</h3><p>由于perf timechart只记录线程粒度的信息,无法替代火焰图在函数级别上分析,需要结合火焰图一<br>起使用</p>\n<h3 id=\"probe\"><a href=\"#probe\" class=\"headerlink\" title=\"probe\"></a>probe</h3><p>可以在程序中添加或者删除动态追踪点,即自定义事件。<br>例如给malloc/free等添加事件来追踪内存泄露情况:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">perf probe --<span class=\"built_in\">exec</span>=/lib64/libc-2.17.so --add malloc</span><br><span class=\"line\">或者</span><br><span class=\"line\"><span class=\"comment\"># perf stat -e probe_libc:free -e probe_libc:malloc -ag -p $(pgrep $process_name$) sleep 4</span></span><br></pre></td></tr></table></figure>\n\n<p>probe也可以在(内核)函数的某一行添加事件进行追踪:<br>例如在schedule函数的12行处增加一个探测点</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">perf probe -a schedule:12</span><br></pre></td></tr></table></figure>\n\n<p>若需要对自定义函数进行跟踪,和上文相似,假设我们定义了一个名为loop的函数</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">#perf probe -x /root/code/test-perf-probe.o "--add=loop"</span></span><br></pre></td></tr></table></figure>\n<p>执行之后会显示:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">Added new event: probe_test_perf_probe:loop (on loop <span class=\"keyword\">in</span> /root/code/test_perf_probe.o)</span><br></pre></td></tr></table></figure>\n<p>然后就可以执行perf工具记录:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">perf record -e probe_test_perf_probe:loop -aR <span class=\"built_in\">sleep</span> 1</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"火焰图\"><a href=\"#火焰图\" class=\"headerlink\" title=\"火焰图\"></a>火焰图</h2><h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://www.brendangregg.com/perf.html\">https://www.brendangregg.com/perf.html</a></p>\n<p><a href=\"https://www.brendangregg.com/perf.html\">https://www.brendangregg.com/perf.html</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"perf命令\"><a href=\"#perf命令\" class=\"headerlink\" title=\"perf命令\"></a>perf命令</h2><h3 id=\"stat\"><a href=\"#stat\" class=\"headerlink\" title=\"stat\"></a>stat</h3><p>记录给定条件下事件的发生次数<br>参数:</p>\n<ul>\n<li>-p 指定待分析进程的 pid(可以是多个,用,分隔列表)</li>\n<li>-t 指定待分析线程的 tid(可以是多个,用,分隔列表)</li>\n<li>-a 从所有 CPU 收集系统数据</li>\n<li>-d -d:打印更详细的信息,可重复 3 次;<br>追加显示L1 和 LLC data cache</li>\n<li>-d -d 追加显示dTLB 和 iTLB events</li>\n<li>-d -d -d 追加 prefetch events</li>\n<li>-r 重复运行命令 n 次,打印平均值。n 设为 0 时无限循环打印</li>\n<li>-c 只统计指定 CPU 列表的数据,如:0,1,3或1-2</li>\n<li>-A 与-a选项联用,不要将 CPU 计数聚合</li>\n</ul>\n<p>输出结果分析:</p>\n<ul>\n<li>Task-clock-msecs:CPU 利用率,该值高,说明程序的多数时间花费在 CPU 计算上而非 IO。</li>\n<li>Context-switches:进程切换次数,记录了程序运行过程中发生了多少次进程切换,一般来说,频繁的进程切换有可能只是CPU正常调度下一个任务,也有可能是一些性能问题的外在表现,导致的原因可能是锁竞争,IO阻塞,硬件中断等。如果可能,频繁的进程切换是应该避免的。</li>\n<li>Cache-misses:程序运行过程中总体的 cache 利用情况,对于性能敏感的程序来说,需要避免出现cache miss的情况。解决方法是对于程序频繁访问的热数据可以集中紧凑存储、程序不去大跨度离散的访问内存等等。</li>\n<li>CPU-migrations:表示进程 t1 运行过程中发生了多少次 CPU 迁移,即被调度器从一个 CPU 转移到另外一个 CPU 上运行。</li>\n<li>Cycles:处理器时钟,一条机器指令可能需要多个 cycles。</li>\n<li>Instructions: 机器指令数目。</li>\n<li>branches:为分支数量。</li>\n<li>branch-misses:为分支预测时失败的数量。</li>\n</ul>\n<h3 id=\"record\"><a href=\"#record\" class=\"headerlink\" title=\"record\"></a>record</h3><h4 id=\"lock\"><a href=\"#lock\" class=\"headerlink\" title=\"lock\"></a>lock</h4><p>内核锁性能<br>需要编译选项的支持:CONFIG_LOCKDEP、CONFIG_LOCK_STAT。<br>CONFIG_LOCKDEP :defines acquired and release events.<br>CONFIG_LOCK_STAT :defines contended and acquired lock events.<br>-i 输入文件<br>-k sorting key,默认为acquired,还可以按contended、wait_total、wait_max和wait_min来</p>\n<p>执行命令:</p>\n<ol>\n<li>perf lock record ./xxx</li>\n<li>perf lock report</li>\n</ol>\n<p>结果分析:</p>\n<ul>\n<li>Name 内核锁的名字</li>\n<li>aquired 该锁被直接获得的次数,因为没有其它内核路径占用该锁,此时不用等待。</li>\n<li>contended 该锁等待后获得的次数,此时被其它内核路径占用,需要等待</li>\n<li>total wait 为了获得该锁,总共的等待时间。</li>\n<li>max wait 为了获得该锁,最大的等待时间</li>\n<li>min wait 为了获得该锁,最小的等待时间。</li>\n</ul>\n<h4 id=\"kmem\"><a href=\"#kmem\" class=\"headerlink\" title=\"kmem\"></a>kmem</h4><p>slab分配器性能分析<br>执行命令:</p>\n<ol>\n<li>perf kmem record ./xxx</li>\n<li>perf kmem stat –caller –alloc -l 20<br>结果分析:</li>\n</ol>\n<ul>\n<li>Callsite 内核代码中调用kmalloc和kfree的地方</li>\n<li>Total_alloc/Per 总共分配的内存大小,平均每次分配的内存大小</li>\n<li>Total_req/Per 总共请求的内存大小,平均每次请求的内存大小</li>\n<li>Hit 调用的次数</li>\n<li>Ping-pong kmalloc和kfree不被同一个CPU执行时的次数,这会导致cache效率降低。</li>\n<li>Frag 碎片所占的百分比,碎片 = 分配的内存 - 请求的内存,这部分是浪费的。</li>\n<li>Alloc Ptr 有使用–alloc选项,还会看到此列,即所分配内存的地址(案例未使用)</li>\n</ul>\n<h4 id=\"sched\"><a href=\"#sched\" class=\"headerlink\" title=\"sched\"></a>sched</h4><p>执行命令记录1秒钟的调度事件:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">perf <span class=\"built_in\">sched</span> record -- <span class=\"built_in\">sleep</span> 1</span><br></pre></td></tr></table></figure>\n<p>执行以下命令可以对生成的recored进行分析:</p>\n<ol>\n<li>perf sched map</li>\n<li>perf sched timehist</li>\n<li></li>\n</ol>\n<h3 id=\"top\"><a href=\"#top\" class=\"headerlink\" title=\"top\"></a>top</h3><p>主要用于实时剖析各个函数在某个性能事件上的热度。利用perf top,能够直观地观察到当前的热点函数,并利用工具中内置的annotate功能,进一步查找热点指令</p>\n<h3 id=\"diff\"><a href=\"#diff\" class=\"headerlink\" title=\"diff\"></a>diff</h3><h3 id=\"timechart\"><a href=\"#timechart\" class=\"headerlink\" title=\"timechart\"></a>timechart</h3><p>由于perf timechart只记录线程粒度的信息,无法替代火焰图在函数级别上分析,需要结合火焰图一<br>起使用</p>\n<h3 id=\"probe\"><a href=\"#probe\" class=\"headerlink\" title=\"probe\"></a>probe</h3><p>可以在程序中添加或者删除动态追踪点,即自定义事件。<br>例如给malloc/free等添加事件来追踪内存泄露情况:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">perf probe --<span class=\"built_in\">exec</span>=/lib64/libc-2.17.so --add malloc</span><br><span class=\"line\">或者</span><br><span class=\"line\"><span class=\"comment\"># perf stat -e probe_libc:free -e probe_libc:malloc -ag -p $(pgrep $process_name$) sleep 4</span></span><br></pre></td></tr></table></figure>\n\n<p>probe也可以在(内核)函数的某一行添加事件进行追踪:<br>例如在schedule函数的12行处增加一个探测点</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">perf probe -a schedule:12</span><br></pre></td></tr></table></figure>\n\n<p>若需要对自定义函数进行跟踪,和上文相似,假设我们定义了一个名为loop的函数</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">#perf probe -x /root/code/test-perf-probe.o "--add=loop"</span></span><br></pre></td></tr></table></figure>\n<p>执行之后会显示:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">Added new event: probe_test_perf_probe:loop (on loop <span class=\"keyword\">in</span> /root/code/test_perf_probe.o)</span><br></pre></td></tr></table></figure>\n<p>然后就可以执行perf工具记录:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">perf record -e probe_test_perf_probe:loop -aR <span class=\"built_in\">sleep</span> 1</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"火焰图\"><a href=\"#火焰图\" class=\"headerlink\" title=\"火焰图\"></a>火焰图</h2><h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://www.brendangregg.com/perf.html\">https://www.brendangregg.com/perf.html</a></p>\n<p><a href=\"https://www.brendangregg.com/perf.html\">https://www.brendangregg.com/perf.html</a></p>\n"},{"title":"PageTable","_content":"\n\n## 页表设置\n\n保存stage2的页表基地址\nPTE_SHARED\npgprot_val(PAGE_KERNEL)\npteval_t\n这些都有什么不同\n\n## 页表walk\n","source":"_posts/Pgtable.md","raw":"---\ntitle: PageTable\ncategories: \n- Linux\ntags:\n- Pgtable\n---\n\n\n## 页表设置\n\n保存stage2的页表基地址\nPTE_SHARED\npgprot_val(PAGE_KERNEL)\npteval_t\n这些都有什么不同\n\n## 页表walk\n","slug":"Pgtable","published":1,"date":"2024-08-12T10:37:47.840Z","updated":"2024-08-13T15:26:14.424Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvb001rqwq2ctts5hp2","content":"<h2 id=\"页表设置\"><a href=\"#页表设置\" class=\"headerlink\" title=\"页表设置\"></a>页表设置</h2><p>保存stage2的页表基地址<br>PTE_SHARED<br>pgprot_val(PAGE_KERNEL)<br>pteval_t<br>这些都有什么不同</p>\n<h2 id=\"页表walk\"><a href=\"#页表walk\" class=\"headerlink\" title=\"页表walk\"></a>页表walk</h2>","cover":false,"excerpt":"","more":"<h2 id=\"页表设置\"><a href=\"#页表设置\" class=\"headerlink\" title=\"页表设置\"></a>页表设置</h2><p>保存stage2的页表基地址<br>PTE_SHARED<br>pgprot_val(PAGE_KERNEL)<br>pteval_t<br>这些都有什么不同</p>\n<h2 id=\"页表walk\"><a href=\"#页表walk\" class=\"headerlink\" title=\"页表walk\"></a>页表walk</h2>"},{"title":"PowerManage","_content":"\n## wakelock接口\n\n\n## Suspend流程\n```c [include/linux/suspend.h]\n#define PM_HIBERNATION_PREPARE\t0x0001 /* Going to hibernate */\n#define PM_POST_HIBERNATION\t0x0002 /* Hibernation finished */\n#define PM_SUSPEND_PREPARE\t0x0003 /* Going to suspend the system */\n#define PM_POST_SUSPEND\t\t0x0004 /* Suspend finished */\n#define PM_RESTORE_PREPARE\t0x0005 /* Going to restore a saved image */\n#define PM_POST_RESTORE\t\t0x0006 /* Restore failed */\n```\nregister_pm_notifier接口注册监听上述几个状态。\n在进入睡眠之前会发送PM_SUSPEND_PREPARE, 等睡眠结束(进入睡眠失败或者从睡眠中唤醒的时候)会再发送PM_POST_SUSPEND\n\n### Suspend流程参考\n\nhttps://www.wowotech.net/pm_subsystem/suspend_and_resume.html\nhttps://blog.csdn.net/u012719256/article/details/52754492\nhttps://blog.csdn.net/MyArrow/article/details/8837756\n\n## 用户态进程冻结\n\n### 进程冻结参考\nhttp://www.wowotech.net/pm_subsystem/237.html\n","source":"_posts/PowerManage.md","raw":"---\ntitle: PowerManage\ncategories: \n- Linux\ntags:\n- Linux PowerManage\n---\n\n## wakelock接口\n\n\n## Suspend流程\n```c [include/linux/suspend.h]\n#define PM_HIBERNATION_PREPARE\t0x0001 /* Going to hibernate */\n#define PM_POST_HIBERNATION\t0x0002 /* Hibernation finished */\n#define PM_SUSPEND_PREPARE\t0x0003 /* Going to suspend the system */\n#define PM_POST_SUSPEND\t\t0x0004 /* Suspend finished */\n#define PM_RESTORE_PREPARE\t0x0005 /* Going to restore a saved image */\n#define PM_POST_RESTORE\t\t0x0006 /* Restore failed */\n```\nregister_pm_notifier接口注册监听上述几个状态。\n在进入睡眠之前会发送PM_SUSPEND_PREPARE, 等睡眠结束(进入睡眠失败或者从睡眠中唤醒的时候)会再发送PM_POST_SUSPEND\n\n### Suspend流程参考\n\nhttps://www.wowotech.net/pm_subsystem/suspend_and_resume.html\nhttps://blog.csdn.net/u012719256/article/details/52754492\nhttps://blog.csdn.net/MyArrow/article/details/8837756\n\n## 用户态进程冻结\n\n### 进程冻结参考\nhttp://www.wowotech.net/pm_subsystem/237.html\n","slug":"PowerManage","published":1,"date":"2024-08-16T12:53:51.256Z","updated":"2024-08-16T12:53:51.256Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvc001tqwq2cae7eo0l","content":"<h2 id=\"wakelock接口\"><a href=\"#wakelock接口\" class=\"headerlink\" title=\"wakelock接口\"></a>wakelock接口</h2><h2 id=\"Suspend流程\"><a href=\"#Suspend流程\" class=\"headerlink\" title=\"Suspend流程\"></a>Suspend流程</h2><figure class=\"highlight c\"><figcaption><span>[include/linux/suspend.h]</span></figcaption><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_HIBERNATION_PREPARE\t0x0001 <span class=\"comment\">/* Going to hibernate */</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_POST_HIBERNATION\t0x0002 <span class=\"comment\">/* Hibernation finished */</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_SUSPEND_PREPARE\t0x0003 <span class=\"comment\">/* Going to suspend the system */</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_POST_SUSPEND\t\t0x0004 <span class=\"comment\">/* Suspend finished */</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_RESTORE_PREPARE\t0x0005 <span class=\"comment\">/* Going to restore a saved image */</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_POST_RESTORE\t\t0x0006 <span class=\"comment\">/* Restore failed */</span></span></span><br></pre></td></tr></table></figure>\n<p>register_pm_notifier接口注册监听上述几个状态。<br>在进入睡眠之前会发送PM_SUSPEND_PREPARE, 等睡眠结束(进入睡眠失败或者从睡眠中唤醒的时候)会再发送PM_POST_SUSPEND</p>\n<h3 id=\"Suspend流程参考\"><a href=\"#Suspend流程参考\" class=\"headerlink\" title=\"Suspend流程参考\"></a>Suspend流程参考</h3><p><a href=\"https://www.wowotech.net/pm_subsystem/suspend_and_resume.html\">https://www.wowotech.net/pm_subsystem/suspend_and_resume.html</a><br><a href=\"https://blog.csdn.net/u012719256/article/details/52754492\">https://blog.csdn.net/u012719256/article/details/52754492</a><br><a href=\"https://blog.csdn.net/MyArrow/article/details/8837756\">https://blog.csdn.net/MyArrow/article/details/8837756</a></p>\n<h2 id=\"用户态进程冻结\"><a href=\"#用户态进程冻结\" class=\"headerlink\" title=\"用户态进程冻结\"></a>用户态进程冻结</h2><h3 id=\"进程冻结参考\"><a href=\"#进程冻结参考\" class=\"headerlink\" title=\"进程冻结参考\"></a>进程冻结参考</h3><p><a href=\"http://www.wowotech.net/pm_subsystem/237.html\">http://www.wowotech.net/pm_subsystem/237.html</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"wakelock接口\"><a href=\"#wakelock接口\" class=\"headerlink\" title=\"wakelock接口\"></a>wakelock接口</h2><h2 id=\"Suspend流程\"><a href=\"#Suspend流程\" class=\"headerlink\" title=\"Suspend流程\"></a>Suspend流程</h2><figure class=\"highlight c\"><figcaption><span>[include/linux/suspend.h]</span></figcaption><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_HIBERNATION_PREPARE\t0x0001 <span class=\"comment\">/* Going to hibernate */</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_POST_HIBERNATION\t0x0002 <span class=\"comment\">/* Hibernation finished */</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_SUSPEND_PREPARE\t0x0003 <span class=\"comment\">/* Going to suspend the system */</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_POST_SUSPEND\t\t0x0004 <span class=\"comment\">/* Suspend finished */</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_RESTORE_PREPARE\t0x0005 <span class=\"comment\">/* Going to restore a saved image */</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> PM_POST_RESTORE\t\t0x0006 <span class=\"comment\">/* Restore failed */</span></span></span><br></pre></td></tr></table></figure>\n<p>register_pm_notifier接口注册监听上述几个状态。<br>在进入睡眠之前会发送PM_SUSPEND_PREPARE, 等睡眠结束(进入睡眠失败或者从睡眠中唤醒的时候)会再发送PM_POST_SUSPEND</p>\n<h3 id=\"Suspend流程参考\"><a href=\"#Suspend流程参考\" class=\"headerlink\" title=\"Suspend流程参考\"></a>Suspend流程参考</h3><p><a href=\"https://www.wowotech.net/pm_subsystem/suspend_and_resume.html\">https://www.wowotech.net/pm_subsystem/suspend_and_resume.html</a><br><a href=\"https://blog.csdn.net/u012719256/article/details/52754492\">https://blog.csdn.net/u012719256/article/details/52754492</a><br><a href=\"https://blog.csdn.net/MyArrow/article/details/8837756\">https://blog.csdn.net/MyArrow/article/details/8837756</a></p>\n<h2 id=\"用户态进程冻结\"><a href=\"#用户态进程冻结\" class=\"headerlink\" title=\"用户态进程冻结\"></a>用户态进程冻结</h2><h3 id=\"进程冻结参考\"><a href=\"#进程冻结参考\" class=\"headerlink\" title=\"进程冻结参考\"></a>进程冻结参考</h3><p><a href=\"http://www.wowotech.net/pm_subsystem/237.html\">http://www.wowotech.net/pm_subsystem/237.html</a></p>\n"},{"title":"Prctl","_content":"\n## 参考\n\nhttps://man7.org/linux/man-pages/man2/prctl.2.html\n","source":"_posts/Prctl.md","raw":"---\ntitle: Prctl\ncategories: \n- Linux\ntags:\n- Linux Prctl\n---\n\n## 参考\n\nhttps://man7.org/linux/man-pages/man2/prctl.2.html\n","slug":"Prctl","published":1,"date":"2024-08-12T10:22:51.119Z","updated":"2024-08-12T10:23:44.627Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvc001xqwq2dj3ud2je","content":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://man7.org/linux/man-pages/man2/prctl.2.html\">https://man7.org/linux/man-pages/man2/prctl.2.html</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://man7.org/linux/man-pages/man2/prctl.2.html\">https://man7.org/linux/man-pages/man2/prctl.2.html</a></p>\n"},{"title":"Proc-pagemap","_content":"\n可以使用/proc/pid/pagemap和/proc/pid/map查看进程使用虚拟内存对应的物理地址\n## 参考\n\nhttps://www.kernel.org/doc/Documentation/vm/pagemap.txt\n\nhttps://www.cnblogs.com/pengdonglin137/p/6802108.html\n","source":"_posts/Proc-pagemap.md","raw":"---\ntitle: Proc-pagemap\ncategories: \n- Linux\ntags:\n- Linux Proc-pagemap\n---\n\n可以使用/proc/pid/pagemap和/proc/pid/map查看进程使用虚拟内存对应的物理地址\n## 参考\n\nhttps://www.kernel.org/doc/Documentation/vm/pagemap.txt\n\nhttps://www.cnblogs.com/pengdonglin137/p/6802108.html\n","slug":"Proc-pagemap","published":1,"date":"2024-08-14T10:01:22.766Z","updated":"2024-08-14T10:01:22.766Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvc001zqwq2ayi24uek","content":"<p>可以使用/proc/pid/pagemap和/proc/pid/map查看进程使用虚拟内存对应的物理地址</p>\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://www.kernel.org/doc/Documentation/vm/pagemap.txt\">https://www.kernel.org/doc/Documentation/vm/pagemap.txt</a></p>\n<p><a href=\"https://www.cnblogs.com/pengdonglin137/p/6802108.html\">https://www.cnblogs.com/pengdonglin137/p/6802108.html</a></p>\n","cover":false,"excerpt":"","more":"<p>可以使用/proc/pid/pagemap和/proc/pid/map查看进程使用虚拟内存对应的物理地址</p>\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://www.kernel.org/doc/Documentation/vm/pagemap.txt\">https://www.kernel.org/doc/Documentation/vm/pagemap.txt</a></p>\n<p><a href=\"https://www.cnblogs.com/pengdonglin137/p/6802108.html\">https://www.cnblogs.com/pengdonglin137/p/6802108.html</a></p>\n"},{"title":"Process Schedule","_content":"\n\n## 进程sched事件追踪\n```[bash] [sched事件追踪]\ncd /sys/kernel/debug/tracing/events/sched\necho 1 > sched_switch/enable\necho 1 > sched_wakeup/enable\necho 1 > sched_wakeup_new/enable\necho 1 > sched_waking/enable\necho 1 > sched_process_fork/enable\necho 1 > sched_stat_runtime/enable\necho 1 > /sys/kernel/debug/tracing/events/irq/enable\necho 1 > /sys/kernel/debug/tracing/tracing_on\n```\n\n## 参考\nhttps://blog.csdn.net/weixin_51760563/article/details/122789480\n\n\n\n","source":"_posts/ProcessSchedule.md","raw":"---\ntitle: Process Schedule\ncategories: \n- Linux\ntags:\n- Linux Process\n---\n\n\n## 进程sched事件追踪\n```[bash] [sched事件追踪]\ncd /sys/kernel/debug/tracing/events/sched\necho 1 > sched_switch/enable\necho 1 > sched_wakeup/enable\necho 1 > sched_wakeup_new/enable\necho 1 > sched_waking/enable\necho 1 > sched_process_fork/enable\necho 1 > sched_stat_runtime/enable\necho 1 > /sys/kernel/debug/tracing/events/irq/enable\necho 1 > /sys/kernel/debug/tracing/tracing_on\n```\n\n## 参考\nhttps://blog.csdn.net/weixin_51760563/article/details/122789480\n\n\n\n","slug":"ProcessSchedule","published":1,"date":"2024-08-16T12:53:51.256Z","updated":"2024-08-16T12:53:51.257Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvc0022qwq2hytjajnl","content":"<h2 id=\"进程sched事件追踪\"><a href=\"#进程sched事件追踪\" class=\"headerlink\" title=\"进程sched事件追踪\"></a>进程sched事件追踪</h2><figure class=\"highlight plaintext\"><figcaption><span>[sched事件追踪]</span></figcaption><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">cd /sys/kernel/debug/tracing/events/sched</span><br><span class=\"line\">echo 1 > sched_switch/enable</span><br><span class=\"line\">echo 1 > sched_wakeup/enable</span><br><span class=\"line\">echo 1 > sched_wakeup_new/enable</span><br><span class=\"line\">echo 1 > sched_waking/enable</span><br><span class=\"line\">echo 1 > sched_process_fork/enable</span><br><span class=\"line\">echo 1 > sched_stat_runtime/enable</span><br><span class=\"line\">echo 1 > /sys/kernel/debug/tracing/events/irq/enable</span><br><span class=\"line\">echo 1 > /sys/kernel/debug/tracing/tracing_on</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://blog.csdn.net/weixin_51760563/article/details/122789480\">https://blog.csdn.net/weixin_51760563/article/details/122789480</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"进程sched事件追踪\"><a href=\"#进程sched事件追踪\" class=\"headerlink\" title=\"进程sched事件追踪\"></a>进程sched事件追踪</h2><figure class=\"highlight plaintext\"><figcaption><span>[sched事件追踪]</span></figcaption><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">cd /sys/kernel/debug/tracing/events/sched</span><br><span class=\"line\">echo 1 > sched_switch/enable</span><br><span class=\"line\">echo 1 > sched_wakeup/enable</span><br><span class=\"line\">echo 1 > sched_wakeup_new/enable</span><br><span class=\"line\">echo 1 > sched_waking/enable</span><br><span class=\"line\">echo 1 > sched_process_fork/enable</span><br><span class=\"line\">echo 1 > sched_stat_runtime/enable</span><br><span class=\"line\">echo 1 > /sys/kernel/debug/tracing/events/irq/enable</span><br><span class=\"line\">echo 1 > /sys/kernel/debug/tracing/tracing_on</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://blog.csdn.net/weixin_51760563/article/details/122789480\">https://blog.csdn.net/weixin_51760563/article/details/122789480</a></p>\n"},{"title":"Proc-meminfo","_content":"\n## 参考\nhttp://www.wowotech.net/memory_management/meminfo_1.html\nhttp://linuxperf.com/?cat=7\n","source":"_posts/Proc-meminfo.md","raw":"---\ntitle: Proc-meminfo\ncategories: \n- Linux\ntags:\n- Linux Proc-meminfo\n---\n\n## 参考\nhttp://www.wowotech.net/memory_management/meminfo_1.html\nhttp://linuxperf.com/?cat=7\n","slug":"Proc-meminfo","published":1,"date":"2024-08-14T10:01:22.766Z","updated":"2024-08-14T10:01:22.766Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvd0025qwq2gwdu1ft3","content":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"http://www.wowotech.net/memory_management/meminfo_1.html\">http://www.wowotech.net/memory_management/meminfo_1.html</a><br><a href=\"http://linuxperf.com/?cat=7\">http://linuxperf.com/?cat=7</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"http://www.wowotech.net/memory_management/meminfo_1.html\">http://www.wowotech.net/memory_management/meminfo_1.html</a><br><a href=\"http://linuxperf.com/?cat=7\">http://linuxperf.com/?cat=7</a></p>\n"},{"title":"Ptrace","_content":"\n## 参考\nhttps://www.cnblogs.com/mysky007/p/11047943.html\n","source":"_posts/Ptrace.md","raw":"---\ntitle: Ptrace\ncategories: \n- Gcc Tool\ntags:\n- Gcc Tool\n---\n\n## 参考\nhttps://www.cnblogs.com/mysky007/p/11047943.html\n","slug":"Ptrace","published":1,"date":"2024-08-13T13:15:23.309Z","updated":"2024-08-13T13:15:23.310Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvd0028qwq208ml6kav","content":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://www.cnblogs.com/mysky007/p/11047943.html\">https://www.cnblogs.com/mysky007/p/11047943.html</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://www.cnblogs.com/mysky007/p/11047943.html\">https://www.cnblogs.com/mysky007/p/11047943.html</a></p>\n"},{"title":"Security","_content":"\n## 参考\nhttps://www.kernel.org/doc/html/v4.14/security/self-protection.html\n\n### 内核将_text区域和rodata区域置位只读\n1. 内核代码区域置位只读\n```c [arch/arm64/mm/mmu.c]\nvoid __init mark_linear_text_alias_ro(void)\n{\n\t/*\n\t * Remove the write permissions from the linear alias of .text/.rodata\n\t */\n\tupdate_mapping_prot(__pa_symbol(_text), (unsigned long)lm_alias(_text),\n\t\t\t (unsigned long)__init_begin - (unsigned long)_text,\n\t\t\t PAGE_KERNEL_RO);\n}\n```\nrodata区域置为只读需要使能CONFIG_STRICT_KERNEL_RWX或者是CONFIG_STRICT_MODULE_RWX\n```c\n#ifdef CONFIG_STRICT_KERNEL_RWX\nstatic void mark_readonly(void)\n{\n\tif (rodata_enabled) {\n\t\t/*\n\t\t * load_module() results in W+X mappings, which are cleaned\n\t\t * up with call_rcu(). Let's make sure that queued work is\n\t\t * flushed so that we don't hit false positives looking for\n\t\t * insecure pages which are W+X.\n\t\t */\n\t\trcu_barrier();\n\t\tmark_rodata_ro();\n\t\trodata_test();\n\t} else\n\t\tpr_info(\"Kernel memory protection disabled.\\n\");\n}\n#elif defined(CONFIG_ARCH_HAS_STRICT_KERNEL_RWX)\nstatic inline void mark_readonly(void)\n{\n\tpr_warn(\"Kernel memory protection not selected by kernel config.\\n\");\n}\n#else\nstatic inline void mark_readonly(void)\n{\n\tpr_warn(\"This architecture does not have kernel memory protection.\\n\");\n}\n#endif\n\n```\n","source":"_posts/Security.md","raw":"---\ntitle: Security\ncategories: \n- Linux\ntags:\n- Linux Security\n---\n\n## 参考\nhttps://www.kernel.org/doc/html/v4.14/security/self-protection.html\n\n### 内核将_text区域和rodata区域置位只读\n1. 内核代码区域置位只读\n```c [arch/arm64/mm/mmu.c]\nvoid __init mark_linear_text_alias_ro(void)\n{\n\t/*\n\t * Remove the write permissions from the linear alias of .text/.rodata\n\t */\n\tupdate_mapping_prot(__pa_symbol(_text), (unsigned long)lm_alias(_text),\n\t\t\t (unsigned long)__init_begin - (unsigned long)_text,\n\t\t\t PAGE_KERNEL_RO);\n}\n```\nrodata区域置为只读需要使能CONFIG_STRICT_KERNEL_RWX或者是CONFIG_STRICT_MODULE_RWX\n```c\n#ifdef CONFIG_STRICT_KERNEL_RWX\nstatic void mark_readonly(void)\n{\n\tif (rodata_enabled) {\n\t\t/*\n\t\t * load_module() results in W+X mappings, which are cleaned\n\t\t * up with call_rcu(). Let's make sure that queued work is\n\t\t * flushed so that we don't hit false positives looking for\n\t\t * insecure pages which are W+X.\n\t\t */\n\t\trcu_barrier();\n\t\tmark_rodata_ro();\n\t\trodata_test();\n\t} else\n\t\tpr_info(\"Kernel memory protection disabled.\\n\");\n}\n#elif defined(CONFIG_ARCH_HAS_STRICT_KERNEL_RWX)\nstatic inline void mark_readonly(void)\n{\n\tpr_warn(\"Kernel memory protection not selected by kernel config.\\n\");\n}\n#else\nstatic inline void mark_readonly(void)\n{\n\tpr_warn(\"This architecture does not have kernel memory protection.\\n\");\n}\n#endif\n\n```\n","slug":"Security","published":1,"date":"2024-08-14T10:01:22.766Z","updated":"2024-08-14T10:01:22.766Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvd002bqwq2de6pcrg0","content":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://www.kernel.org/doc/html/v4.14/security/self-protection.html\">https://www.kernel.org/doc/html/v4.14/security/self-protection.html</a></p>\n<h3 id=\"内核将-text区域和rodata区域置位只读\"><a href=\"#内核将-text区域和rodata区域置位只读\" class=\"headerlink\" title=\"内核将_text区域和rodata区域置位只读\"></a>内核将_text区域和rodata区域置位只读</h3><ol>\n<li>内核代码区域置位只读<figure class=\"highlight c\"><figcaption><span>[arch/arm64/mm/mmu.c]</span></figcaption><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">void</span> __init <span class=\"title function_\">mark_linear_text_alias_ro</span><span class=\"params\">(<span class=\"type\">void</span>)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\t<span class=\"comment\">/*</span></span><br><span class=\"line\"><span class=\"comment\">\t * Remove the write permissions from the linear alias of .text/.rodata</span></span><br><span class=\"line\"><span class=\"comment\">\t */</span></span><br><span class=\"line\">\tupdate_mapping_prot(__pa_symbol(_text), (<span class=\"type\">unsigned</span> <span class=\"type\">long</span>)lm_alias(_text),</span><br><span class=\"line\">\t\t\t (<span class=\"type\">unsigned</span> <span class=\"type\">long</span>)__init_begin - (<span class=\"type\">unsigned</span> <span class=\"type\">long</span>)_text,</span><br><span class=\"line\">\t\t\t PAGE_KERNEL_RO);</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\nrodata区域置为只读需要使能CONFIG_STRICT_KERNEL_RWX或者是CONFIG_STRICT_MODULE_RWX<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">ifdef</span> CONFIG_STRICT_KERNEL_RWX</span></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"type\">void</span> <span class=\"title function_\">mark_readonly</span><span class=\"params\">(<span class=\"type\">void</span>)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (rodata_enabled) {</span><br><span class=\"line\">\t\t<span class=\"comment\">/*</span></span><br><span class=\"line\"><span class=\"comment\">\t\t * load_module() results in W+X mappings, which are cleaned</span></span><br><span class=\"line\"><span class=\"comment\">\t\t * up with call_rcu(). Let's make sure that queued work is</span></span><br><span class=\"line\"><span class=\"comment\">\t\t * flushed so that we don't hit false positives looking for</span></span><br><span class=\"line\"><span class=\"comment\">\t\t * insecure pages which are W+X.</span></span><br><span class=\"line\"><span class=\"comment\">\t\t */</span></span><br><span class=\"line\">\t\trcu_barrier();</span><br><span class=\"line\">\t\tmark_rodata_ro();</span><br><span class=\"line\">\t\trodata_test();</span><br><span class=\"line\">\t} <span class=\"keyword\">else</span></span><br><span class=\"line\">\t\tpr_info(<span class=\"string\">"Kernel memory protection disabled.\\n"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">elif</span> defined(CONFIG_ARCH_HAS_STRICT_KERNEL_RWX)</span></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"keyword\">inline</span> <span class=\"type\">void</span> <span class=\"title function_\">mark_readonly</span><span class=\"params\">(<span class=\"type\">void</span>)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\tpr_warn(<span class=\"string\">"Kernel memory protection not selected by kernel config.\\n"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">else</span></span></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"keyword\">inline</span> <span class=\"type\">void</span> <span class=\"title function_\">mark_readonly</span><span class=\"params\">(<span class=\"type\">void</span>)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\tpr_warn(<span class=\"string\">"This architecture does not have kernel memory protection.\\n"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">endif</span></span></span><br><span class=\"line\"></span><br></pre></td></tr></table></figure></li>\n</ol>\n","cover":false,"excerpt":"","more":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://www.kernel.org/doc/html/v4.14/security/self-protection.html\">https://www.kernel.org/doc/html/v4.14/security/self-protection.html</a></p>\n<h3 id=\"内核将-text区域和rodata区域置位只读\"><a href=\"#内核将-text区域和rodata区域置位只读\" class=\"headerlink\" title=\"内核将_text区域和rodata区域置位只读\"></a>内核将_text区域和rodata区域置位只读</h3><ol>\n<li>内核代码区域置位只读<figure class=\"highlight c\"><figcaption><span>[arch/arm64/mm/mmu.c]</span></figcaption><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">void</span> __init <span class=\"title function_\">mark_linear_text_alias_ro</span><span class=\"params\">(<span class=\"type\">void</span>)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\t<span class=\"comment\">/*</span></span><br><span class=\"line\"><span class=\"comment\">\t * Remove the write permissions from the linear alias of .text/.rodata</span></span><br><span class=\"line\"><span class=\"comment\">\t */</span></span><br><span class=\"line\">\tupdate_mapping_prot(__pa_symbol(_text), (<span class=\"type\">unsigned</span> <span class=\"type\">long</span>)lm_alias(_text),</span><br><span class=\"line\">\t\t\t (<span class=\"type\">unsigned</span> <span class=\"type\">long</span>)__init_begin - (<span class=\"type\">unsigned</span> <span class=\"type\">long</span>)_text,</span><br><span class=\"line\">\t\t\t PAGE_KERNEL_RO);</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\nrodata区域置为只读需要使能CONFIG_STRICT_KERNEL_RWX或者是CONFIG_STRICT_MODULE_RWX<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">ifdef</span> CONFIG_STRICT_KERNEL_RWX</span></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"type\">void</span> <span class=\"title function_\">mark_readonly</span><span class=\"params\">(<span class=\"type\">void</span>)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> (rodata_enabled) {</span><br><span class=\"line\">\t\t<span class=\"comment\">/*</span></span><br><span class=\"line\"><span class=\"comment\">\t\t * load_module() results in W+X mappings, which are cleaned</span></span><br><span class=\"line\"><span class=\"comment\">\t\t * up with call_rcu(). Let's make sure that queued work is</span></span><br><span class=\"line\"><span class=\"comment\">\t\t * flushed so that we don't hit false positives looking for</span></span><br><span class=\"line\"><span class=\"comment\">\t\t * insecure pages which are W+X.</span></span><br><span class=\"line\"><span class=\"comment\">\t\t */</span></span><br><span class=\"line\">\t\trcu_barrier();</span><br><span class=\"line\">\t\tmark_rodata_ro();</span><br><span class=\"line\">\t\trodata_test();</span><br><span class=\"line\">\t} <span class=\"keyword\">else</span></span><br><span class=\"line\">\t\tpr_info(<span class=\"string\">"Kernel memory protection disabled.\\n"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">elif</span> defined(CONFIG_ARCH_HAS_STRICT_KERNEL_RWX)</span></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"keyword\">inline</span> <span class=\"type\">void</span> <span class=\"title function_\">mark_readonly</span><span class=\"params\">(<span class=\"type\">void</span>)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\tpr_warn(<span class=\"string\">"Kernel memory protection not selected by kernel config.\\n"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">else</span></span></span><br><span class=\"line\"><span class=\"type\">static</span> <span class=\"keyword\">inline</span> <span class=\"type\">void</span> <span class=\"title function_\">mark_readonly</span><span class=\"params\">(<span class=\"type\">void</span>)</span></span><br><span class=\"line\">{</span><br><span class=\"line\">\tpr_warn(<span class=\"string\">"This architecture does not have kernel memory protection.\\n"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">endif</span></span></span><br><span class=\"line\"></span><br></pre></td></tr></table></figure></li>\n</ol>\n"},{"title":"Rcu (Read Copy Update)","_content":"\n## 参考\nhttps://zhuanlan.zhihu.com/p/30583695\nhttp://www.wowotech.net/kernel_synchronization/rcu_fundamentals.html\nhttp://3ms.huawei.com/km/blogs/details/12175655\n\nhttp://3ms.huawei.com/km/blogs/details/5886747\nhttps://docs.google.com/document/d/1X0lThx8OK0ZgLMqVoXiR4ZrGURHrXK6NyLRbeXe3Xac/edit\n\nhttp://3ms.huawei.com/km/blogs/details/125081\n\n例子:\nhttps://github.com/jinb-park/rcu_example/blob/master/list_rcu_example.c\n","source":"_posts/Rcu.md","raw":"---\ntitle: Rcu (Read Copy Update)\ncategories: \n- Linux\ntags:\n- Linux RCU\n---\n\n## 参考\nhttps://zhuanlan.zhihu.com/p/30583695\nhttp://www.wowotech.net/kernel_synchronization/rcu_fundamentals.html\nhttp://3ms.huawei.com/km/blogs/details/12175655\n\nhttp://3ms.huawei.com/km/blogs/details/5886747\nhttps://docs.google.com/document/d/1X0lThx8OK0ZgLMqVoXiR4ZrGURHrXK6NyLRbeXe3Xac/edit\n\nhttp://3ms.huawei.com/km/blogs/details/125081\n\n例子:\nhttps://github.com/jinb-park/rcu_example/blob/master/list_rcu_example.c\n","slug":"Rcu","published":1,"date":"2024-08-09T10:53:15.490Z","updated":"2024-08-10T16:13:48.756Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvd002fqwq22mkhbyd1","content":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://zhuanlan.zhihu.com/p/30583695\">https://zhuanlan.zhihu.com/p/30583695</a><br><a href=\"http://www.wowotech.net/kernel_synchronization/rcu_fundamentals.html\">http://www.wowotech.net/kernel_synchronization/rcu_fundamentals.html</a><br><a href=\"http://3ms.huawei.com/km/blogs/details/12175655\">http://3ms.huawei.com/km/blogs/details/12175655</a></p>\n<p><a href=\"http://3ms.huawei.com/km/blogs/details/5886747\">http://3ms.huawei.com/km/blogs/details/5886747</a><br><a href=\"https://docs.google.com/document/d/1X0lThx8OK0ZgLMqVoXiR4ZrGURHrXK6NyLRbeXe3Xac/edit\">https://docs.google.com/document/d/1X0lThx8OK0ZgLMqVoXiR4ZrGURHrXK6NyLRbeXe3Xac/edit</a></p>\n<p><a href=\"http://3ms.huawei.com/km/blogs/details/125081\">http://3ms.huawei.com/km/blogs/details/125081</a></p>\n<p>例子:<br><a href=\"https://github.com/jinb-park/rcu_example/blob/master/list_rcu_example.c\">https://github.com/jinb-park/rcu_example/blob/master/list_rcu_example.c</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://zhuanlan.zhihu.com/p/30583695\">https://zhuanlan.zhihu.com/p/30583695</a><br><a href=\"http://www.wowotech.net/kernel_synchronization/rcu_fundamentals.html\">http://www.wowotech.net/kernel_synchronization/rcu_fundamentals.html</a><br><a href=\"http://3ms.huawei.com/km/blogs/details/12175655\">http://3ms.huawei.com/km/blogs/details/12175655</a></p>\n<p><a href=\"http://3ms.huawei.com/km/blogs/details/5886747\">http://3ms.huawei.com/km/blogs/details/5886747</a><br><a href=\"https://docs.google.com/document/d/1X0lThx8OK0ZgLMqVoXiR4ZrGURHrXK6NyLRbeXe3Xac/edit\">https://docs.google.com/document/d/1X0lThx8OK0ZgLMqVoXiR4ZrGURHrXK6NyLRbeXe3Xac/edit</a></p>\n<p><a href=\"http://3ms.huawei.com/km/blogs/details/125081\">http://3ms.huawei.com/km/blogs/details/125081</a></p>\n<p>例子:<br><a href=\"https://github.com/jinb-park/rcu_example/blob/master/list_rcu_example.c\">https://github.com/jinb-park/rcu_example/blob/master/list_rcu_example.c</a></p>\n"},{"title":"Smmu","_content":"\n## VMID/ASID/PASID\n### 概念\nVMID:每个虚拟机都被赋予一个VMID。VMID用于标识TLB项,区分每个TLB是属于哪个虚拟机。这允许多个不同的虚拟机转换在同一时间内在TLB中存在。\n\nASID:在多进程的情况下,每次切换进程都需要进行TLB清理。这样会导致切换的效率变低。为了解决问题,TLB 引入了 ASID(Address Space ID) 。ASID 的范围是 0-255。ASID 由操作系统分配,当前进程的ASID值被写在 ASID 寄存器 (使用CP15 c3访问)。TLB 在更新页表项时也会将 ASID 写入 TLB。\n\nPASID(Process Address Space ID) ,地址空间ID,是EP的本地ID,每个function都有一组不同的PASID,不同function间的PASID互不相关。带有PASID的TLP Prefix是一种End-End的TLP前缀,PASID与Requester ID一起共同作为请求TLP地址空间的唯一标识。同一PASID在同一系统中可以重复使用。PASID用来对多个进程进行区分。\n\n### PASID获取\niommu_sva_bind_device\niommu_sva_get_pasid\n获取pasid\n\nPASID的意义\nhttps://blog.csdn.net/yiyeguzhou100/article/details/128069086\nhttps://www.kernel.org/doc/html/next/x86/sva.html\nhttps://blog.csdn.net/qq_45024274/article/details/129224989\n\n## SVA的概念\nhttps://www.kernel.org/doc/html/next/x86/sva.html\n\n\n\n","source":"_posts/Smmu.md","raw":"---\ntitle: Smmu\ncategories: \n- Linux\ntags:\n- Linux Smmu\n---\n\n## VMID/ASID/PASID\n### 概念\nVMID:每个虚拟机都被赋予一个VMID。VMID用于标识TLB项,区分每个TLB是属于哪个虚拟机。这允许多个不同的虚拟机转换在同一时间内在TLB中存在。\n\nASID:在多进程的情况下,每次切换进程都需要进行TLB清理。这样会导致切换的效率变低。为了解决问题,TLB 引入了 ASID(Address Space ID) 。ASID 的范围是 0-255。ASID 由操作系统分配,当前进程的ASID值被写在 ASID 寄存器 (使用CP15 c3访问)。TLB 在更新页表项时也会将 ASID 写入 TLB。\n\nPASID(Process Address Space ID) ,地址空间ID,是EP的本地ID,每个function都有一组不同的PASID,不同function间的PASID互不相关。带有PASID的TLP Prefix是一种End-End的TLP前缀,PASID与Requester ID一起共同作为请求TLP地址空间的唯一标识。同一PASID在同一系统中可以重复使用。PASID用来对多个进程进行区分。\n\n### PASID获取\niommu_sva_bind_device\niommu_sva_get_pasid\n获取pasid\n\nPASID的意义\nhttps://blog.csdn.net/yiyeguzhou100/article/details/128069086\nhttps://www.kernel.org/doc/html/next/x86/sva.html\nhttps://blog.csdn.net/qq_45024274/article/details/129224989\n\n## SVA的概念\nhttps://www.kernel.org/doc/html/next/x86/sva.html\n\n\n\n","slug":"Smmu","published":1,"date":"2024-08-16T12:53:51.257Z","updated":"2024-08-16T12:53:51.257Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvd002iqwq2avoi2a9j","content":"<h2 id=\"VMID-ASID-PASID\"><a href=\"#VMID-ASID-PASID\" class=\"headerlink\" title=\"VMID/ASID/PASID\"></a>VMID/ASID/PASID</h2><h3 id=\"概念\"><a href=\"#概念\" class=\"headerlink\" title=\"概念\"></a>概念</h3><p>VMID:每个虚拟机都被赋予一个VMID。VMID用于标识TLB项,区分每个TLB是属于哪个虚拟机。这允许多个不同的虚拟机转换在同一时间内在TLB中存在。</p>\n<p>ASID:在多进程的情况下,每次切换进程都需要进行TLB清理。这样会导致切换的效率变低。为了解决问题,TLB 引入了 ASID(Address Space ID) 。ASID 的范围是 0-255。ASID 由操作系统分配,当前进程的ASID值被写在 ASID 寄存器 (使用CP15 c3访问)。TLB 在更新页表项时也会将 ASID 写入 TLB。</p>\n<p>PASID(Process Address Space ID) ,地址空间ID,是EP的本地ID,每个function都有一组不同的PASID,不同function间的PASID互不相关。带有PASID的TLP Prefix是一种End-End的TLP前缀,PASID与Requester ID一起共同作为请求TLP地址空间的唯一标识。同一PASID在同一系统中可以重复使用。PASID用来对多个进程进行区分。</p>\n<h3 id=\"PASID获取\"><a href=\"#PASID获取\" class=\"headerlink\" title=\"PASID获取\"></a>PASID获取</h3><p>iommu_sva_bind_device<br>iommu_sva_get_pasid<br>获取pasid</p>\n<p>PASID的意义<br><a href=\"https://blog.csdn.net/yiyeguzhou100/article/details/128069086\">https://blog.csdn.net/yiyeguzhou100/article/details/128069086</a><br><a href=\"https://www.kernel.org/doc/html/next/x86/sva.html\">https://www.kernel.org/doc/html/next/x86/sva.html</a><br><a href=\"https://blog.csdn.net/qq_45024274/article/details/129224989\">https://blog.csdn.net/qq_45024274/article/details/129224989</a></p>\n<h2 id=\"SVA的概念\"><a href=\"#SVA的概念\" class=\"headerlink\" title=\"SVA的概念\"></a>SVA的概念</h2><p><a href=\"https://www.kernel.org/doc/html/next/x86/sva.html\">https://www.kernel.org/doc/html/next/x86/sva.html</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"VMID-ASID-PASID\"><a href=\"#VMID-ASID-PASID\" class=\"headerlink\" title=\"VMID/ASID/PASID\"></a>VMID/ASID/PASID</h2><h3 id=\"概念\"><a href=\"#概念\" class=\"headerlink\" title=\"概念\"></a>概念</h3><p>VMID:每个虚拟机都被赋予一个VMID。VMID用于标识TLB项,区分每个TLB是属于哪个虚拟机。这允许多个不同的虚拟机转换在同一时间内在TLB中存在。</p>\n<p>ASID:在多进程的情况下,每次切换进程都需要进行TLB清理。这样会导致切换的效率变低。为了解决问题,TLB 引入了 ASID(Address Space ID) 。ASID 的范围是 0-255。ASID 由操作系统分配,当前进程的ASID值被写在 ASID 寄存器 (使用CP15 c3访问)。TLB 在更新页表项时也会将 ASID 写入 TLB。</p>\n<p>PASID(Process Address Space ID) ,地址空间ID,是EP的本地ID,每个function都有一组不同的PASID,不同function间的PASID互不相关。带有PASID的TLP Prefix是一种End-End的TLP前缀,PASID与Requester ID一起共同作为请求TLP地址空间的唯一标识。同一PASID在同一系统中可以重复使用。PASID用来对多个进程进行区分。</p>\n<h3 id=\"PASID获取\"><a href=\"#PASID获取\" class=\"headerlink\" title=\"PASID获取\"></a>PASID获取</h3><p>iommu_sva_bind_device<br>iommu_sva_get_pasid<br>获取pasid</p>\n<p>PASID的意义<br><a href=\"https://blog.csdn.net/yiyeguzhou100/article/details/128069086\">https://blog.csdn.net/yiyeguzhou100/article/details/128069086</a><br><a href=\"https://www.kernel.org/doc/html/next/x86/sva.html\">https://www.kernel.org/doc/html/next/x86/sva.html</a><br><a href=\"https://blog.csdn.net/qq_45024274/article/details/129224989\">https://blog.csdn.net/qq_45024274/article/details/129224989</a></p>\n<h2 id=\"SVA的概念\"><a href=\"#SVA的概念\" class=\"headerlink\" title=\"SVA的概念\"></a>SVA的概念</h2><p><a href=\"https://www.kernel.org/doc/html/next/x86/sva.html\">https://www.kernel.org/doc/html/next/x86/sva.html</a></p>\n"},{"title":"StartUp","_content":"\n## 内核入口\n内核入口需要查看lds链接脚本。KBUILD_LDS定义了链接脚本的路径:arch/$(SRCARCH)/kernel/vmlinux.lds。\n```c\n# Linker scripts preprocessor (.lds.S -> .lds)\n# ---------------------------------------------------------------------------\nquiet_cmd_cpp_lds_S = LDS $@\n cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \\\n -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<\n\n$(obj)/%.lds: $(src)/%.lds.S FORCE\n $(call if_changed_dep,cpp_lds_S)\n```\n\n从链接脚本 arch/arm64/kernel/vmlinux.lds可以查到,程序的入口为 _text,镜像起始位置存放的是 .head.text段生成的指令\n```c [arch/arm64/mm/proc.S]\nOUTPUT_ARCH(aarch64)\nENTRY(_text)\n\nSECTIONS\n{\n . = ((((((-(((1)) << ((((48))) - 1)))) + (0x08000000))) + (0x08000000)));\n .head.text : {\n _text = .;\n KEEP(*(.head.text))\n }\n ...\n}\n```\n\n搜索 .head.text,可以找到 include/linux/init.h对 __HEAD定义 .section \".head.text\",\"ax\"\n\n```c\n/* For assembly routines */\n#define __HEAD .section \".head.text\",\"ax\"\n#define __INIT .section \".init.text\",\"ax\"\n#define __FINIT .previous\n```\n\n通过搜索 __HEAD,可以看到程序起始代码位于 arch/arm64/kernel/head.S\n\n## 从入口到start_kernel\n```\n+-- _text() /// 内核启动入口\n \\-- primary_entry()\n +-- preserve_boot_args() /// 保存x0~x3到boot_args[0~3]\n +-- init_kernel_el() /// 根据内核运行异常等级进行配置,返回启动模式\n | +-- init_el1() /// 通常情况下从EL1启动内核\n | \\-- init_el2() /// 从EL2启动内核,用于开启VHE(Virtualization Host Extensions)\n +-- create_idmap() /// 建立恒等映射init_idmap_pg_dir和内核镜像映射init_pg_dir的页表\n +-- __cpu_setup() /// 为开启MMU做的CPU初始化\n \\-- __primary_switch()\n +-- __enable_mmu() /// 开启MMU,将init_idmap_pg_dir加载到ttbr0,reserved_pg_dir加载到ttbr1\n +-- clear_page_tables() /// 清空init_pg_dir\n +-- create_kernel_mapping() /// 填充init_pg_dir\n +-- load_ttbr1() /// 将init_pg_dir加载到ttbr1\n \\-- __primary_switched() /// 初始化init_task栈,设置VBAR_EL1,保存FDT地址,计算kimage_voffset,清空bss段\n +-- set_cpu_boot_mode_flag()/// 设置__boot_cpu_mode变量\n +-- early_fdt_map()\n | +-- early_fixmap_init() /// 尝试建立fixmap的页表,可能失败,后边init_feature_override会用到\n | \\-- fixmap_remap_fdt() /// 如果成功建立fixmap页表,将fdt映射到fixmap的FIX_FDT区域\n +-- init_feature_override() /// 根据BootLoader传入的bootargs,对一些参数的改写\n +-- finalise_el2() /// Prefer VHE if possible\n \\-- start_kernel() /// 跳转到start_kernel执行\n```\n","source":"_posts/StartUp.md","raw":"---\ntitle: StartUp\ncategories: \n- Linux\ntags:\n- Linux StartUp\n---\n\n## 内核入口\n内核入口需要查看lds链接脚本。KBUILD_LDS定义了链接脚本的路径:arch/$(SRCARCH)/kernel/vmlinux.lds。\n```c\n# Linker scripts preprocessor (.lds.S -> .lds)\n# ---------------------------------------------------------------------------\nquiet_cmd_cpp_lds_S = LDS $@\n cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \\\n -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<\n\n$(obj)/%.lds: $(src)/%.lds.S FORCE\n $(call if_changed_dep,cpp_lds_S)\n```\n\n从链接脚本 arch/arm64/kernel/vmlinux.lds可以查到,程序的入口为 _text,镜像起始位置存放的是 .head.text段生成的指令\n```c [arch/arm64/mm/proc.S]\nOUTPUT_ARCH(aarch64)\nENTRY(_text)\n\nSECTIONS\n{\n . = ((((((-(((1)) << ((((48))) - 1)))) + (0x08000000))) + (0x08000000)));\n .head.text : {\n _text = .;\n KEEP(*(.head.text))\n }\n ...\n}\n```\n\n搜索 .head.text,可以找到 include/linux/init.h对 __HEAD定义 .section \".head.text\",\"ax\"\n\n```c\n/* For assembly routines */\n#define __HEAD .section \".head.text\",\"ax\"\n#define __INIT .section \".init.text\",\"ax\"\n#define __FINIT .previous\n```\n\n通过搜索 __HEAD,可以看到程序起始代码位于 arch/arm64/kernel/head.S\n\n## 从入口到start_kernel\n```\n+-- _text() /// 内核启动入口\n \\-- primary_entry()\n +-- preserve_boot_args() /// 保存x0~x3到boot_args[0~3]\n +-- init_kernel_el() /// 根据内核运行异常等级进行配置,返回启动模式\n | +-- init_el1() /// 通常情况下从EL1启动内核\n | \\-- init_el2() /// 从EL2启动内核,用于开启VHE(Virtualization Host Extensions)\n +-- create_idmap() /// 建立恒等映射init_idmap_pg_dir和内核镜像映射init_pg_dir的页表\n +-- __cpu_setup() /// 为开启MMU做的CPU初始化\n \\-- __primary_switch()\n +-- __enable_mmu() /// 开启MMU,将init_idmap_pg_dir加载到ttbr0,reserved_pg_dir加载到ttbr1\n +-- clear_page_tables() /// 清空init_pg_dir\n +-- create_kernel_mapping() /// 填充init_pg_dir\n +-- load_ttbr1() /// 将init_pg_dir加载到ttbr1\n \\-- __primary_switched() /// 初始化init_task栈,设置VBAR_EL1,保存FDT地址,计算kimage_voffset,清空bss段\n +-- set_cpu_boot_mode_flag()/// 设置__boot_cpu_mode变量\n +-- early_fdt_map()\n | +-- early_fixmap_init() /// 尝试建立fixmap的页表,可能失败,后边init_feature_override会用到\n | \\-- fixmap_remap_fdt() /// 如果成功建立fixmap页表,将fdt映射到fixmap的FIX_FDT区域\n +-- init_feature_override() /// 根据BootLoader传入的bootargs,对一些参数的改写\n +-- finalise_el2() /// Prefer VHE if possible\n \\-- start_kernel() /// 跳转到start_kernel执行\n```\n","slug":"StartUp","published":1,"date":"2024-08-13T13:15:23.310Z","updated":"2024-08-13T16:07:07.365Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfve002kqwq2awsqgcyy","content":"<h2 id=\"内核入口\"><a href=\"#内核入口\" class=\"headerlink\" title=\"内核入口\"></a>内核入口</h2><p>内核入口需要查看lds链接脚本。KBUILD_LDS定义了链接脚本的路径:arch/$(SRCARCH)/kernel/vmlinux.lds。</p>\n<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"># Linker scripts <span class=\"title function_\">preprocessor</span> <span class=\"params\">(.lds.S -> .lds)</span></span><br><span class=\"line\"># ---------------------------------------------------------------------------</span><br><span class=\"line\">quiet_cmd_cpp_lds_S = LDS $@</span><br><span class=\"line\"> cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \\</span><br><span class=\"line\"> -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<</span><br><span class=\"line\"></span><br><span class=\"line\">$(obj)/%.lds: $(src)/%.lds.S FORCE</span><br><span class=\"line\"> $(call if_changed_dep,cpp_lds_S)</span><br></pre></td></tr></table></figure>\n\n<p>从链接脚本 arch/arm64/kernel/vmlinux.lds可以查到,程序的入口为 _text,镜像起始位置存放的是 .head.text段生成的指令</p>\n<figure class=\"highlight c\"><figcaption><span>[arch/arm64/mm/proc.S]</span></figcaption><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">OUTPUT_ARCH(aarch64)</span><br><span class=\"line\">ENTRY(_text)</span><br><span class=\"line\"></span><br><span class=\"line\">SECTIONS</span><br><span class=\"line\">{</span><br><span class=\"line\"> . = ((((((-(((<span class=\"number\">1</span>)) << ((((<span class=\"number\">48</span>))) - <span class=\"number\">1</span>)))) + (<span class=\"number\">0x08000000</span>))) + (<span class=\"number\">0x08000000</span>)));</span><br><span class=\"line\"> .head.text : {</span><br><span class=\"line\"> _text = .;</span><br><span class=\"line\"> KEEP(*(.head.text))</span><br><span class=\"line\"> }</span><br><span class=\"line\"> ...</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>搜索 .head.text,可以找到 include/linux/init.h对 __HEAD定义 .section “.head.text”,”ax”</p>\n<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* For assembly routines */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> __HEAD .section <span class=\"string\">".head.text"</span>,<span class=\"string\">"ax"</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> __INIT .section <span class=\"string\">".init.text"</span>,<span class=\"string\">"ax"</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> __FINIT .previous</span></span><br></pre></td></tr></table></figure>\n\n<p>通过搜索 __HEAD,可以看到程序起始代码位于 arch/arm64/kernel/head.S</p>\n<h2 id=\"从入口到start-kernel\"><a href=\"#从入口到start-kernel\" class=\"headerlink\" title=\"从入口到start_kernel\"></a>从入口到start_kernel</h2><figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">+-- _text() /// 内核启动入口</span><br><span class=\"line\"> \\-- primary_entry()</span><br><span class=\"line\"> +-- preserve_boot_args() /// 保存x0~x3到boot_args[0~3]</span><br><span class=\"line\"> +-- init_kernel_el() /// 根据内核运行异常等级进行配置,返回启动模式</span><br><span class=\"line\"> | +-- init_el1() /// 通常情况下从EL1启动内核</span><br><span class=\"line\"> | \\-- init_el2() /// 从EL2启动内核,用于开启VHE(Virtualization Host Extensions)</span><br><span class=\"line\"> +-- create_idmap() /// 建立恒等映射init_idmap_pg_dir和内核镜像映射init_pg_dir的页表</span><br><span class=\"line\"> +-- __cpu_setup() /// 为开启MMU做的CPU初始化</span><br><span class=\"line\"> \\-- __primary_switch()</span><br><span class=\"line\"> +-- __enable_mmu() /// 开启MMU,将init_idmap_pg_dir加载到ttbr0,reserved_pg_dir加载到ttbr1</span><br><span class=\"line\"> +-- clear_page_tables() /// 清空init_pg_dir</span><br><span class=\"line\"> +-- create_kernel_mapping() /// 填充init_pg_dir</span><br><span class=\"line\"> +-- load_ttbr1() /// 将init_pg_dir加载到ttbr1</span><br><span class=\"line\"> \\-- __primary_switched() /// 初始化init_task栈,设置VBAR_EL1,保存FDT地址,计算kimage_voffset,清空bss段</span><br><span class=\"line\"> +-- set_cpu_boot_mode_flag()/// 设置__boot_cpu_mode变量</span><br><span class=\"line\"> +-- early_fdt_map()</span><br><span class=\"line\"> | +-- early_fixmap_init() /// 尝试建立fixmap的页表,可能失败,后边init_feature_override会用到</span><br><span class=\"line\"> | \\-- fixmap_remap_fdt() /// 如果成功建立fixmap页表,将fdt映射到fixmap的FIX_FDT区域</span><br><span class=\"line\"> +-- init_feature_override() /// 根据BootLoader传入的bootargs,对一些参数的改写</span><br><span class=\"line\"> +-- finalise_el2() /// Prefer VHE if possible</span><br><span class=\"line\"> \\-- start_kernel() /// 跳转到start_kernel执行</span><br></pre></td></tr></table></figure>\n","cover":false,"excerpt":"","more":"<h2 id=\"内核入口\"><a href=\"#内核入口\" class=\"headerlink\" title=\"内核入口\"></a>内核入口</h2><p>内核入口需要查看lds链接脚本。KBUILD_LDS定义了链接脚本的路径:arch/$(SRCARCH)/kernel/vmlinux.lds。</p>\n<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"># Linker scripts <span class=\"title function_\">preprocessor</span> <span class=\"params\">(.lds.S -> .lds)</span></span><br><span class=\"line\"># ---------------------------------------------------------------------------</span><br><span class=\"line\">quiet_cmd_cpp_lds_S = LDS $@</span><br><span class=\"line\"> cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \\</span><br><span class=\"line\"> -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<</span><br><span class=\"line\"></span><br><span class=\"line\">$(obj)/%.lds: $(src)/%.lds.S FORCE</span><br><span class=\"line\"> $(call if_changed_dep,cpp_lds_S)</span><br></pre></td></tr></table></figure>\n\n<p>从链接脚本 arch/arm64/kernel/vmlinux.lds可以查到,程序的入口为 _text,镜像起始位置存放的是 .head.text段生成的指令</p>\n<figure class=\"highlight c\"><figcaption><span>[arch/arm64/mm/proc.S]</span></figcaption><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">OUTPUT_ARCH(aarch64)</span><br><span class=\"line\">ENTRY(_text)</span><br><span class=\"line\"></span><br><span class=\"line\">SECTIONS</span><br><span class=\"line\">{</span><br><span class=\"line\"> . = ((((((-(((<span class=\"number\">1</span>)) << ((((<span class=\"number\">48</span>))) - <span class=\"number\">1</span>)))) + (<span class=\"number\">0x08000000</span>))) + (<span class=\"number\">0x08000000</span>)));</span><br><span class=\"line\"> .head.text : {</span><br><span class=\"line\"> _text = .;</span><br><span class=\"line\"> KEEP(*(.head.text))</span><br><span class=\"line\"> }</span><br><span class=\"line\"> ...</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>搜索 .head.text,可以找到 include/linux/init.h对 __HEAD定义 .section “.head.text”,”ax”</p>\n<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* For assembly routines */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> __HEAD .section <span class=\"string\">".head.text"</span>,<span class=\"string\">"ax"</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> __INIT .section <span class=\"string\">".init.text"</span>,<span class=\"string\">"ax"</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">define</span> __FINIT .previous</span></span><br></pre></td></tr></table></figure>\n\n<p>通过搜索 __HEAD,可以看到程序起始代码位于 arch/arm64/kernel/head.S</p>\n<h2 id=\"从入口到start-kernel\"><a href=\"#从入口到start-kernel\" class=\"headerlink\" title=\"从入口到start_kernel\"></a>从入口到start_kernel</h2><figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">+-- _text() /// 内核启动入口</span><br><span class=\"line\"> \\-- primary_entry()</span><br><span class=\"line\"> +-- preserve_boot_args() /// 保存x0~x3到boot_args[0~3]</span><br><span class=\"line\"> +-- init_kernel_el() /// 根据内核运行异常等级进行配置,返回启动模式</span><br><span class=\"line\"> | +-- init_el1() /// 通常情况下从EL1启动内核</span><br><span class=\"line\"> | \\-- init_el2() /// 从EL2启动内核,用于开启VHE(Virtualization Host Extensions)</span><br><span class=\"line\"> +-- create_idmap() /// 建立恒等映射init_idmap_pg_dir和内核镜像映射init_pg_dir的页表</span><br><span class=\"line\"> +-- __cpu_setup() /// 为开启MMU做的CPU初始化</span><br><span class=\"line\"> \\-- __primary_switch()</span><br><span class=\"line\"> +-- __enable_mmu() /// 开启MMU,将init_idmap_pg_dir加载到ttbr0,reserved_pg_dir加载到ttbr1</span><br><span class=\"line\"> +-- clear_page_tables() /// 清空init_pg_dir</span><br><span class=\"line\"> +-- create_kernel_mapping() /// 填充init_pg_dir</span><br><span class=\"line\"> +-- load_ttbr1() /// 将init_pg_dir加载到ttbr1</span><br><span class=\"line\"> \\-- __primary_switched() /// 初始化init_task栈,设置VBAR_EL1,保存FDT地址,计算kimage_voffset,清空bss段</span><br><span class=\"line\"> +-- set_cpu_boot_mode_flag()/// 设置__boot_cpu_mode变量</span><br><span class=\"line\"> +-- early_fdt_map()</span><br><span class=\"line\"> | +-- early_fixmap_init() /// 尝试建立fixmap的页表,可能失败,后边init_feature_override会用到</span><br><span class=\"line\"> | \\-- fixmap_remap_fdt() /// 如果成功建立fixmap页表,将fdt映射到fixmap的FIX_FDT区域</span><br><span class=\"line\"> +-- init_feature_override() /// 根据BootLoader传入的bootargs,对一些参数的改写</span><br><span class=\"line\"> +-- finalise_el2() /// Prefer VHE if possible</span><br><span class=\"line\"> \\-- start_kernel() /// 跳转到start_kernel执行</span><br></pre></td></tr></table></figure>\n"},{"title":"Spinlock","_content":"\n## Spinlock嵌套使用\nspinlock锁的类型有以下几种:\n- spin_lock/spin_unlock\n- spin_lock_bh/spin_unlock_bh\n- spin_lock_irq/spin_unlock_irq\n- spin_lock_irqsave/spin_unlock_irqrestore\nspinlock锁的严格程度是由弱到强。弱的spinlock类型不能被强的spinlock类型给嵌套。\n\n### spin_lock_irq套spin_lock_bh\n如下图所示,spin_lock_irq套了spin_lock_bh来保护临界区的函数,分别在进程上下文和tasklet中都被调用。\n\n\n\n因为在spin_unlock_bh函数中,会查看当前是否有堆积的tasklet并直接调用do_softirq进行调用,导致spin_lock_irq死锁。\n","source":"_posts/Spinlock.md","raw":"---\ntitle: Spinlock\ncategories: \n- Linux\ntags:\n- Linux Spinlock\n---\n\n## Spinlock嵌套使用\nspinlock锁的类型有以下几种:\n- spin_lock/spin_unlock\n- spin_lock_bh/spin_unlock_bh\n- spin_lock_irq/spin_unlock_irq\n- spin_lock_irqsave/spin_unlock_irqrestore\nspinlock锁的严格程度是由弱到强。弱的spinlock类型不能被强的spinlock类型给嵌套。\n\n### spin_lock_irq套spin_lock_bh\n如下图所示,spin_lock_irq套了spin_lock_bh来保护临界区的函数,分别在进程上下文和tasklet中都被调用。\n\n\n\n因为在spin_unlock_bh函数中,会查看当前是否有堆积的tasklet并直接调用do_softirq进行调用,导致spin_lock_irq死锁。\n","slug":"Spinlock","published":1,"date":"2024-08-09T10:53:15.490Z","updated":"2024-08-13T16:39:20.843Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfve002oqwq21hatar30","content":"<h2 id=\"Spinlock嵌套使用\"><a href=\"#Spinlock嵌套使用\" class=\"headerlink\" title=\"Spinlock嵌套使用\"></a>Spinlock嵌套使用</h2><p>spinlock锁的类型有以下几种:</p>\n<ul>\n<li>spin_lock/spin_unlock</li>\n<li>spin_lock_bh/spin_unlock_bh</li>\n<li>spin_lock_irq/spin_unlock_irq</li>\n<li>spin_lock_irqsave/spin_unlock_irqrestore<br>spinlock锁的严格程度是由弱到强。弱的spinlock类型不能被强的spinlock类型给嵌套。</li>\n</ul>\n<h3 id=\"spin-lock-irq套spin-lock-bh\"><a href=\"#spin-lock-irq套spin-lock-bh\" class=\"headerlink\" title=\"spin_lock_irq套spin_lock_bh\"></a>spin_lock_irq套spin_lock_bh</h3><p>如下图所示,spin_lock_irq套了spin_lock_bh来保护临界区的函数,分别在进程上下文和tasklet中都被调用。</p>\n<p><img src=\"/images/Spinlock/spinlock%E5%B5%8C%E5%A5%97-1.svg\" alt=\"TTBR地址范围\"></p>\n<p>因为在spin_unlock_bh函数中,会查看当前是否有堆积的tasklet并直接调用do_softirq进行调用,导致spin_lock_irq死锁。</p>\n","cover":false,"excerpt":"","more":"<h2 id=\"Spinlock嵌套使用\"><a href=\"#Spinlock嵌套使用\" class=\"headerlink\" title=\"Spinlock嵌套使用\"></a>Spinlock嵌套使用</h2><p>spinlock锁的类型有以下几种:</p>\n<ul>\n<li>spin_lock/spin_unlock</li>\n<li>spin_lock_bh/spin_unlock_bh</li>\n<li>spin_lock_irq/spin_unlock_irq</li>\n<li>spin_lock_irqsave/spin_unlock_irqrestore<br>spinlock锁的严格程度是由弱到强。弱的spinlock类型不能被强的spinlock类型给嵌套。</li>\n</ul>\n<h3 id=\"spin-lock-irq套spin-lock-bh\"><a href=\"#spin-lock-irq套spin-lock-bh\" class=\"headerlink\" title=\"spin_lock_irq套spin_lock_bh\"></a>spin_lock_irq套spin_lock_bh</h3><p>如下图所示,spin_lock_irq套了spin_lock_bh来保护临界区的函数,分别在进程上下文和tasklet中都被调用。</p>\n<p><img src=\"/images/Spinlock/spinlock%E5%B5%8C%E5%A5%97-1.svg\" alt=\"TTBR地址范围\"></p>\n<p>因为在spin_unlock_bh函数中,会查看当前是否有堆积的tasklet并直接调用do_softirq进行调用,导致spin_lock_irq死锁。</p>\n"},{"title":"Sysrq","_content":"\n## 代码路径\nSysrq的代码路径在/drivers/tty/sysrq.c\ncmd对应的处理函数是static const struct sysrq_key_op *sysrq_key_table[62] = {};\n可以往/proc/sysrq-trigger中写入对应的cmd来触发某些事件\n例如往/proc/sysrq-trigger中写入c可以导致系统挂死:echo c > /proc/sysrq-trigger\n\n## 用法\n### 系统挂死\necho c > /proc/sysrq-trigger\n这个命令输入之后,系统就会挂死。\n\n### 打印所有cpu的调用栈\necho l > /proc/sysrq-trigger\n```c \n[94891.950482] CPU: 5 PID: 6174 Comm: bash Not tainted 6.9.8-orbstack-00170-g7b4100b7ced4 #1\n[94891.950491] Hardware name: orbstack,virt (DT)\n[94891.950494] Call trace:\n[94891.950496] dump_backtrace+0xe8/0x110\n[94891.950509] show_stack+0x1c/0x30\n[94891.950512] dump_stack_lvl+0x38/0x78\n[94891.950522] dump_stack+0x14/0x20\n[94891.950525] nmi_cpu_backtrace+0xe0/0x138\n[94891.950573] nmi_trigger_cpumask_backtrace+0x90/0x180\n[94891.950576] arch_trigger_cpumask_backtrace+0x1c/0x30\n[94891.950578] sysrq_handle_showallcpus+0x20/0x30\n[94891.950585] __handle_sysrq+0x14c/0x158\n[94891.950586] write_sysrq_trigger+0xec/0x100\n[94891.950588] proc_reg_write+0x98/0x110\n[94891.950596] vfs_write+0x124/0x378\n[94891.950601] ksys_write+0x78/0xe8\n[94891.950603] __arm64_sys_write+0x20/0x30\n[94891.950605] do_el0_svc+0x90/0xe8\n[94891.950607] el0_svc+0x24/0x50\n[94891.950714] el0t_64_sync_handler+0x7c/0xf0\n[94891.950717] el0t_64_sync+0x14c/0x150\n[94891.950722] Sending NMI from CPU 5 to CPUs 0-4,6-9:\n[94891.950743] NMI backtrace for cpu 0\n[94891.951110] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.9.8-orbstack-00170-g7b4100b7ced4 #1\n[94891.951114] Hardware name: orbstack,virt (DT)\n[94891.951117] pstate: 61400005 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)\n[94891.951120] pc : do_idle+0x100/0x2d8\n[94891.951127] lr : do_idle+0x100/0x2d8\n[94891.951133] sp : ffffc86062cf3dd0\n[94891.951135] x29: ffffc86062cf3de0 x28: 0000000040000000 x27: ffffc86062cfa000\n[94891.951140] x26: ffffc86062cfa748 x25: 0000000000000001 x24: ffffc86062cce000\n[94891.951143] x23: 0000000000000000 x22: ffffc86062d13780 x21: 00000003ffe00000\n[94891.951146] x20: 0000000000000000 x19: 0000000000000000 x18: 0000000000000005\n[94891.951149] x17: 00000000000000a2 x16: 0000000000000082 x15: 0000000000000010\n[94891.951151] x14: 0000000000000010 x13: ffffc86062cd38c0 x12: ffffffffffffffe1\n[94891.951154] x11: 000000000016080c x10: 0000000000000001 x9 : ffffc86062ccc470\n[94891.951157] x8 : 4000000000000000 x7 : 0000000000000000 x6 : 0000000000000000\n[94891.951159] x5 : 00002c74284a5c70 x4 : ffffc86062cf3c98 x3 : ffff151c4f0adec0\n[94891.951162] x2 : ffffc86062cf3d74 x1 : 0000000000000000 x0 : 00000000ffffffff\n[94891.951165] Call trace:\n[94891.951166] do_idle+0x100/0x2d8\n[94891.951168] cpu_startup_entry+0x38/0x48\n[94891.951170] rest_init+0xc8/0xd0\n[94891.951173] start_kernel+0x264/0x2b0\n[94891.951178] __primary_switched+0x80/0x90\n```\n\n### 将ftrace的buffer打印出来\n```bash\necho z > /proc/sysrq-trigger\n```\n输入完上面的命令之后,可以敲dmesg可以看到ftrace的buff里边的内容全部打印到内核日志中。\n\n### 显示内存信息\n```\necho m > /proc/sysrq-trigger\n```\n之前敲dmesg可以看到打印的内存信息。\n","source":"_posts/Sysrq.md","raw":"---\ntitle: Sysrq\ncategories: \n- Linux\ntags:\n- Linux Sysrq\n---\n\n## 代码路径\nSysrq的代码路径在/drivers/tty/sysrq.c\ncmd对应的处理函数是static const struct sysrq_key_op *sysrq_key_table[62] = {};\n可以往/proc/sysrq-trigger中写入对应的cmd来触发某些事件\n例如往/proc/sysrq-trigger中写入c可以导致系统挂死:echo c > /proc/sysrq-trigger\n\n## 用法\n### 系统挂死\necho c > /proc/sysrq-trigger\n这个命令输入之后,系统就会挂死。\n\n### 打印所有cpu的调用栈\necho l > /proc/sysrq-trigger\n```c \n[94891.950482] CPU: 5 PID: 6174 Comm: bash Not tainted 6.9.8-orbstack-00170-g7b4100b7ced4 #1\n[94891.950491] Hardware name: orbstack,virt (DT)\n[94891.950494] Call trace:\n[94891.950496] dump_backtrace+0xe8/0x110\n[94891.950509] show_stack+0x1c/0x30\n[94891.950512] dump_stack_lvl+0x38/0x78\n[94891.950522] dump_stack+0x14/0x20\n[94891.950525] nmi_cpu_backtrace+0xe0/0x138\n[94891.950573] nmi_trigger_cpumask_backtrace+0x90/0x180\n[94891.950576] arch_trigger_cpumask_backtrace+0x1c/0x30\n[94891.950578] sysrq_handle_showallcpus+0x20/0x30\n[94891.950585] __handle_sysrq+0x14c/0x158\n[94891.950586] write_sysrq_trigger+0xec/0x100\n[94891.950588] proc_reg_write+0x98/0x110\n[94891.950596] vfs_write+0x124/0x378\n[94891.950601] ksys_write+0x78/0xe8\n[94891.950603] __arm64_sys_write+0x20/0x30\n[94891.950605] do_el0_svc+0x90/0xe8\n[94891.950607] el0_svc+0x24/0x50\n[94891.950714] el0t_64_sync_handler+0x7c/0xf0\n[94891.950717] el0t_64_sync+0x14c/0x150\n[94891.950722] Sending NMI from CPU 5 to CPUs 0-4,6-9:\n[94891.950743] NMI backtrace for cpu 0\n[94891.951110] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.9.8-orbstack-00170-g7b4100b7ced4 #1\n[94891.951114] Hardware name: orbstack,virt (DT)\n[94891.951117] pstate: 61400005 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)\n[94891.951120] pc : do_idle+0x100/0x2d8\n[94891.951127] lr : do_idle+0x100/0x2d8\n[94891.951133] sp : ffffc86062cf3dd0\n[94891.951135] x29: ffffc86062cf3de0 x28: 0000000040000000 x27: ffffc86062cfa000\n[94891.951140] x26: ffffc86062cfa748 x25: 0000000000000001 x24: ffffc86062cce000\n[94891.951143] x23: 0000000000000000 x22: ffffc86062d13780 x21: 00000003ffe00000\n[94891.951146] x20: 0000000000000000 x19: 0000000000000000 x18: 0000000000000005\n[94891.951149] x17: 00000000000000a2 x16: 0000000000000082 x15: 0000000000000010\n[94891.951151] x14: 0000000000000010 x13: ffffc86062cd38c0 x12: ffffffffffffffe1\n[94891.951154] x11: 000000000016080c x10: 0000000000000001 x9 : ffffc86062ccc470\n[94891.951157] x8 : 4000000000000000 x7 : 0000000000000000 x6 : 0000000000000000\n[94891.951159] x5 : 00002c74284a5c70 x4 : ffffc86062cf3c98 x3 : ffff151c4f0adec0\n[94891.951162] x2 : ffffc86062cf3d74 x1 : 0000000000000000 x0 : 00000000ffffffff\n[94891.951165] Call trace:\n[94891.951166] do_idle+0x100/0x2d8\n[94891.951168] cpu_startup_entry+0x38/0x48\n[94891.951170] rest_init+0xc8/0xd0\n[94891.951173] start_kernel+0x264/0x2b0\n[94891.951178] __primary_switched+0x80/0x90\n```\n\n### 将ftrace的buffer打印出来\n```bash\necho z > /proc/sysrq-trigger\n```\n输入完上面的命令之后,可以敲dmesg可以看到ftrace的buff里边的内容全部打印到内核日志中。\n\n### 显示内存信息\n```\necho m > /proc/sysrq-trigger\n```\n之前敲dmesg可以看到打印的内存信息。\n","slug":"Sysrq","published":1,"date":"2024-08-13T13:15:23.310Z","updated":"2024-08-13T15:47:58.971Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfve002qqwq2hl5j7m9t","content":"<h2 id=\"代码路径\"><a href=\"#代码路径\" class=\"headerlink\" title=\"代码路径\"></a>代码路径</h2><p>Sysrq的代码路径在/drivers/tty/sysrq.c<br>cmd对应的处理函数是static const struct sysrq_key_op *sysrq_key_table[62] = {};<br>可以往/proc/sysrq-trigger中写入对应的cmd来触发某些事件<br>例如往/proc/sysrq-trigger中写入c可以导致系统挂死:echo c > /proc/sysrq-trigger</p>\n<h2 id=\"用法\"><a href=\"#用法\" class=\"headerlink\" title=\"用法\"></a>用法</h2><h3 id=\"系统挂死\"><a href=\"#系统挂死\" class=\"headerlink\" title=\"系统挂死\"></a>系统挂死</h3><p>echo c > /proc/sysrq-trigger<br>这个命令输入之后,系统就会挂死。</p>\n<h3 id=\"打印所有cpu的调用栈\"><a href=\"#打印所有cpu的调用栈\" class=\"headerlink\" title=\"打印所有cpu的调用栈\"></a>打印所有cpu的调用栈</h3><p>echo l > /proc/sysrq-trigger</p>\n<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">[<span class=\"number\">94891.950482</span>] CPU: <span class=\"number\">5</span> PID: <span class=\"number\">6174</span> Comm: bash Not tainted <span class=\"number\">6.9</span><span class=\"number\">.8</span>-orbstack<span class=\"number\">-00170</span>-g7b4100b7ced4 #<span class=\"number\">1</span></span><br><span class=\"line\">[<span class=\"number\">94891.950491</span>] Hardware name: orbstack,virt (DT)</span><br><span class=\"line\">[<span class=\"number\">94891.950494</span>] Call trace:</span><br><span class=\"line\">[<span class=\"number\">94891.950496</span>] dump_backtrace+<span class=\"number\">0xe8</span>/<span class=\"number\">0x110</span></span><br><span class=\"line\">[<span class=\"number\">94891.950509</span>] show_stack+<span class=\"number\">0x1c</span>/<span class=\"number\">0x30</span></span><br><span class=\"line\">[<span class=\"number\">94891.950512</span>] dump_stack_lvl+<span class=\"number\">0x38</span>/<span class=\"number\">0x78</span></span><br><span class=\"line\">[<span class=\"number\">94891.950522</span>] dump_stack+<span class=\"number\">0x14</span>/<span class=\"number\">0x20</span></span><br><span class=\"line\">[<span class=\"number\">94891.950525</span>] nmi_cpu_backtrace+<span class=\"number\">0xe0</span>/<span class=\"number\">0x138</span></span><br><span class=\"line\">[<span class=\"number\">94891.950573</span>] nmi_trigger_cpumask_backtrace+<span class=\"number\">0x90</span>/<span class=\"number\">0x180</span></span><br><span class=\"line\">[<span class=\"number\">94891.950576</span>] arch_trigger_cpumask_backtrace+<span class=\"number\">0x1c</span>/<span class=\"number\">0x30</span></span><br><span class=\"line\">[<span class=\"number\">94891.950578</span>] sysrq_handle_showallcpus+<span class=\"number\">0x20</span>/<span class=\"number\">0x30</span></span><br><span class=\"line\">[<span class=\"number\">94891.950585</span>] __handle_sysrq+<span class=\"number\">0x14c</span>/<span class=\"number\">0x158</span></span><br><span class=\"line\">[<span class=\"number\">94891.950586</span>] write_sysrq_trigger+<span class=\"number\">0xec</span>/<span class=\"number\">0x100</span></span><br><span class=\"line\">[<span class=\"number\">94891.950588</span>] proc_reg_write+<span class=\"number\">0x98</span>/<span class=\"number\">0x110</span></span><br><span class=\"line\">[<span class=\"number\">94891.950596</span>] vfs_write+<span class=\"number\">0x124</span>/<span class=\"number\">0x378</span></span><br><span class=\"line\">[<span class=\"number\">94891.950601</span>] ksys_write+<span class=\"number\">0x78</span>/<span class=\"number\">0xe8</span></span><br><span class=\"line\">[<span class=\"number\">94891.950603</span>] __arm64_sys_write+<span class=\"number\">0x20</span>/<span class=\"number\">0x30</span></span><br><span class=\"line\">[<span class=\"number\">94891.950605</span>] do_el0_svc+<span class=\"number\">0x90</span>/<span class=\"number\">0xe8</span></span><br><span class=\"line\">[<span class=\"number\">94891.950607</span>] el0_svc+<span class=\"number\">0x24</span>/<span class=\"number\">0x50</span></span><br><span class=\"line\">[<span class=\"number\">94891.950714</span>] el0t_64_sync_handler+<span class=\"number\">0x7c</span>/<span class=\"number\">0xf0</span></span><br><span class=\"line\">[<span class=\"number\">94891.950717</span>] el0t_64_sync+<span class=\"number\">0x14c</span>/<span class=\"number\">0x150</span></span><br><span class=\"line\">[<span class=\"number\">94891.950722</span>] Sending NMI from CPU <span class=\"number\">5</span> to CPUs <span class=\"number\">0</span><span class=\"number\">-4</span>,<span class=\"number\">6</span><span class=\"number\">-9</span>:</span><br><span class=\"line\">[<span class=\"number\">94891.950743</span>] NMI backtrace <span class=\"keyword\">for</span> cpu <span class=\"number\">0</span></span><br><span class=\"line\">[<span class=\"number\">94891.951110</span>] CPU: <span class=\"number\">0</span> PID: <span class=\"number\">0</span> Comm: swapper/<span class=\"number\">0</span> Not tainted <span class=\"number\">6.9</span><span class=\"number\">.8</span>-orbstack<span class=\"number\">-00170</span>-g7b4100b7ced4 #<span class=\"number\">1</span></span><br><span class=\"line\">[<span class=\"number\">94891.951114</span>] Hardware name: orbstack,virt (DT)</span><br><span class=\"line\">[<span class=\"number\">94891.951117</span>] pstate: <span class=\"number\">61400005</span> (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)</span><br><span class=\"line\">[<span class=\"number\">94891.951120</span>] pc : do_idle+<span class=\"number\">0x100</span>/<span class=\"number\">0x2d8</span></span><br><span class=\"line\">[<span class=\"number\">94891.951127</span>] lr : do_idle+<span class=\"number\">0x100</span>/<span class=\"number\">0x2d8</span></span><br><span class=\"line\">[<span class=\"number\">94891.951133</span>] sp : ffffc86062cf3dd0</span><br><span class=\"line\">[<span class=\"number\">94891.951135</span>] x29: ffffc86062cf3de0 x28: <span class=\"number\">0000000040000000</span> x27: ffffc86062cfa000</span><br><span class=\"line\">[<span class=\"number\">94891.951140</span>] x26: ffffc86062cfa748 x25: <span class=\"number\">0000000000000001</span> x24: ffffc86062cce000</span><br><span class=\"line\">[<span class=\"number\">94891.951143</span>] x23: <span class=\"number\">0000000000000000</span> x22: ffffc86062d13780 x21: <span class=\"number\">00000003f</span>fe00000</span><br><span class=\"line\">[<span class=\"number\">94891.951146</span>] x20: <span class=\"number\">0000000000000000</span> x19: <span class=\"number\">0000000000000000</span> x18: <span class=\"number\">0000000000000005</span></span><br><span class=\"line\">[<span class=\"number\">94891.951149</span>] x17: <span class=\"number\">00000000000000</span>a2 x16: <span class=\"number\">0000000000000082</span> x15: <span class=\"number\">0000000000000010</span></span><br><span class=\"line\">[<span class=\"number\">94891.951151</span>] x14: <span class=\"number\">0000000000000010</span> x13: ffffc86062cd38c0 x12: ffffffffffffffe1</span><br><span class=\"line\">[<span class=\"number\">94891.951154</span>] x11: <span class=\"number\">000000000016080</span>c x10: <span class=\"number\">0000000000000001</span> x9 : ffffc86062ccc470</span><br><span class=\"line\">[<span class=\"number\">94891.951157</span>] x8 : <span class=\"number\">4000000000000000</span> x7 : <span class=\"number\">0000000000000000</span> x6 : <span class=\"number\">0000000000000000</span></span><br><span class=\"line\">[<span class=\"number\">94891.951159</span>] x5 : <span class=\"number\">00002</span>c74284a5c70 x4 : ffffc86062cf3c98 x3 : ffff151c4f0adec0</span><br><span class=\"line\">[<span class=\"number\">94891.951162</span>] x2 : ffffc86062cf3d74 x1 : <span class=\"number\">0000000000000000</span> x0 : <span class=\"number\">00000000f</span>fffffff</span><br><span class=\"line\">[<span class=\"number\">94891.951165</span>] Call trace:</span><br><span class=\"line\">[<span class=\"number\">94891.951166</span>] do_idle+<span class=\"number\">0x100</span>/<span class=\"number\">0x2d8</span></span><br><span class=\"line\">[<span class=\"number\">94891.951168</span>] cpu_startup_entry+<span class=\"number\">0x38</span>/<span class=\"number\">0x48</span></span><br><span class=\"line\">[<span class=\"number\">94891.951170</span>] rest_init+<span class=\"number\">0xc8</span>/<span class=\"number\">0xd0</span></span><br><span class=\"line\">[<span class=\"number\">94891.951173</span>] start_kernel+<span class=\"number\">0x264</span>/<span class=\"number\">0x2b0</span></span><br><span class=\"line\">[<span class=\"number\">94891.951178</span>] __primary_switched+<span class=\"number\">0x80</span>/<span class=\"number\">0x90</span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"将ftrace的buffer打印出来\"><a href=\"#将ftrace的buffer打印出来\" class=\"headerlink\" title=\"将ftrace的buffer打印出来\"></a>将ftrace的buffer打印出来</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> z > /proc/sysrq-trigger</span><br></pre></td></tr></table></figure>\n<p>输入完上面的命令之后,可以敲dmesg可以看到ftrace的buff里边的内容全部打印到内核日志中。</p>\n<h3 id=\"显示内存信息\"><a href=\"#显示内存信息\" class=\"headerlink\" title=\"显示内存信息\"></a>显示内存信息</h3><figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">echo m > /proc/sysrq-trigger</span><br></pre></td></tr></table></figure>\n<p>之前敲dmesg可以看到打印的内存信息。</p>\n","cover":false,"excerpt":"","more":"<h2 id=\"代码路径\"><a href=\"#代码路径\" class=\"headerlink\" title=\"代码路径\"></a>代码路径</h2><p>Sysrq的代码路径在/drivers/tty/sysrq.c<br>cmd对应的处理函数是static const struct sysrq_key_op *sysrq_key_table[62] = {};<br>可以往/proc/sysrq-trigger中写入对应的cmd来触发某些事件<br>例如往/proc/sysrq-trigger中写入c可以导致系统挂死:echo c > /proc/sysrq-trigger</p>\n<h2 id=\"用法\"><a href=\"#用法\" class=\"headerlink\" title=\"用法\"></a>用法</h2><h3 id=\"系统挂死\"><a href=\"#系统挂死\" class=\"headerlink\" title=\"系统挂死\"></a>系统挂死</h3><p>echo c > /proc/sysrq-trigger<br>这个命令输入之后,系统就会挂死。</p>\n<h3 id=\"打印所有cpu的调用栈\"><a href=\"#打印所有cpu的调用栈\" class=\"headerlink\" title=\"打印所有cpu的调用栈\"></a>打印所有cpu的调用栈</h3><p>echo l > /proc/sysrq-trigger</p>\n<figure class=\"highlight c\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">[<span class=\"number\">94891.950482</span>] CPU: <span class=\"number\">5</span> PID: <span class=\"number\">6174</span> Comm: bash Not tainted <span class=\"number\">6.9</span><span class=\"number\">.8</span>-orbstack<span class=\"number\">-00170</span>-g7b4100b7ced4 #<span class=\"number\">1</span></span><br><span class=\"line\">[<span class=\"number\">94891.950491</span>] Hardware name: orbstack,virt (DT)</span><br><span class=\"line\">[<span class=\"number\">94891.950494</span>] Call trace:</span><br><span class=\"line\">[<span class=\"number\">94891.950496</span>] dump_backtrace+<span class=\"number\">0xe8</span>/<span class=\"number\">0x110</span></span><br><span class=\"line\">[<span class=\"number\">94891.950509</span>] show_stack+<span class=\"number\">0x1c</span>/<span class=\"number\">0x30</span></span><br><span class=\"line\">[<span class=\"number\">94891.950512</span>] dump_stack_lvl+<span class=\"number\">0x38</span>/<span class=\"number\">0x78</span></span><br><span class=\"line\">[<span class=\"number\">94891.950522</span>] dump_stack+<span class=\"number\">0x14</span>/<span class=\"number\">0x20</span></span><br><span class=\"line\">[<span class=\"number\">94891.950525</span>] nmi_cpu_backtrace+<span class=\"number\">0xe0</span>/<span class=\"number\">0x138</span></span><br><span class=\"line\">[<span class=\"number\">94891.950573</span>] nmi_trigger_cpumask_backtrace+<span class=\"number\">0x90</span>/<span class=\"number\">0x180</span></span><br><span class=\"line\">[<span class=\"number\">94891.950576</span>] arch_trigger_cpumask_backtrace+<span class=\"number\">0x1c</span>/<span class=\"number\">0x30</span></span><br><span class=\"line\">[<span class=\"number\">94891.950578</span>] sysrq_handle_showallcpus+<span class=\"number\">0x20</span>/<span class=\"number\">0x30</span></span><br><span class=\"line\">[<span class=\"number\">94891.950585</span>] __handle_sysrq+<span class=\"number\">0x14c</span>/<span class=\"number\">0x158</span></span><br><span class=\"line\">[<span class=\"number\">94891.950586</span>] write_sysrq_trigger+<span class=\"number\">0xec</span>/<span class=\"number\">0x100</span></span><br><span class=\"line\">[<span class=\"number\">94891.950588</span>] proc_reg_write+<span class=\"number\">0x98</span>/<span class=\"number\">0x110</span></span><br><span class=\"line\">[<span class=\"number\">94891.950596</span>] vfs_write+<span class=\"number\">0x124</span>/<span class=\"number\">0x378</span></span><br><span class=\"line\">[<span class=\"number\">94891.950601</span>] ksys_write+<span class=\"number\">0x78</span>/<span class=\"number\">0xe8</span></span><br><span class=\"line\">[<span class=\"number\">94891.950603</span>] __arm64_sys_write+<span class=\"number\">0x20</span>/<span class=\"number\">0x30</span></span><br><span class=\"line\">[<span class=\"number\">94891.950605</span>] do_el0_svc+<span class=\"number\">0x90</span>/<span class=\"number\">0xe8</span></span><br><span class=\"line\">[<span class=\"number\">94891.950607</span>] el0_svc+<span class=\"number\">0x24</span>/<span class=\"number\">0x50</span></span><br><span class=\"line\">[<span class=\"number\">94891.950714</span>] el0t_64_sync_handler+<span class=\"number\">0x7c</span>/<span class=\"number\">0xf0</span></span><br><span class=\"line\">[<span class=\"number\">94891.950717</span>] el0t_64_sync+<span class=\"number\">0x14c</span>/<span class=\"number\">0x150</span></span><br><span class=\"line\">[<span class=\"number\">94891.950722</span>] Sending NMI from CPU <span class=\"number\">5</span> to CPUs <span class=\"number\">0</span><span class=\"number\">-4</span>,<span class=\"number\">6</span><span class=\"number\">-9</span>:</span><br><span class=\"line\">[<span class=\"number\">94891.950743</span>] NMI backtrace <span class=\"keyword\">for</span> cpu <span class=\"number\">0</span></span><br><span class=\"line\">[<span class=\"number\">94891.951110</span>] CPU: <span class=\"number\">0</span> PID: <span class=\"number\">0</span> Comm: swapper/<span class=\"number\">0</span> Not tainted <span class=\"number\">6.9</span><span class=\"number\">.8</span>-orbstack<span class=\"number\">-00170</span>-g7b4100b7ced4 #<span class=\"number\">1</span></span><br><span class=\"line\">[<span class=\"number\">94891.951114</span>] Hardware name: orbstack,virt (DT)</span><br><span class=\"line\">[<span class=\"number\">94891.951117</span>] pstate: <span class=\"number\">61400005</span> (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)</span><br><span class=\"line\">[<span class=\"number\">94891.951120</span>] pc : do_idle+<span class=\"number\">0x100</span>/<span class=\"number\">0x2d8</span></span><br><span class=\"line\">[<span class=\"number\">94891.951127</span>] lr : do_idle+<span class=\"number\">0x100</span>/<span class=\"number\">0x2d8</span></span><br><span class=\"line\">[<span class=\"number\">94891.951133</span>] sp : ffffc86062cf3dd0</span><br><span class=\"line\">[<span class=\"number\">94891.951135</span>] x29: ffffc86062cf3de0 x28: <span class=\"number\">0000000040000000</span> x27: ffffc86062cfa000</span><br><span class=\"line\">[<span class=\"number\">94891.951140</span>] x26: ffffc86062cfa748 x25: <span class=\"number\">0000000000000001</span> x24: ffffc86062cce000</span><br><span class=\"line\">[<span class=\"number\">94891.951143</span>] x23: <span class=\"number\">0000000000000000</span> x22: ffffc86062d13780 x21: <span class=\"number\">00000003f</span>fe00000</span><br><span class=\"line\">[<span class=\"number\">94891.951146</span>] x20: <span class=\"number\">0000000000000000</span> x19: <span class=\"number\">0000000000000000</span> x18: <span class=\"number\">0000000000000005</span></span><br><span class=\"line\">[<span class=\"number\">94891.951149</span>] x17: <span class=\"number\">00000000000000</span>a2 x16: <span class=\"number\">0000000000000082</span> x15: <span class=\"number\">0000000000000010</span></span><br><span class=\"line\">[<span class=\"number\">94891.951151</span>] x14: <span class=\"number\">0000000000000010</span> x13: ffffc86062cd38c0 x12: ffffffffffffffe1</span><br><span class=\"line\">[<span class=\"number\">94891.951154</span>] x11: <span class=\"number\">000000000016080</span>c x10: <span class=\"number\">0000000000000001</span> x9 : ffffc86062ccc470</span><br><span class=\"line\">[<span class=\"number\">94891.951157</span>] x8 : <span class=\"number\">4000000000000000</span> x7 : <span class=\"number\">0000000000000000</span> x6 : <span class=\"number\">0000000000000000</span></span><br><span class=\"line\">[<span class=\"number\">94891.951159</span>] x5 : <span class=\"number\">00002</span>c74284a5c70 x4 : ffffc86062cf3c98 x3 : ffff151c4f0adec0</span><br><span class=\"line\">[<span class=\"number\">94891.951162</span>] x2 : ffffc86062cf3d74 x1 : <span class=\"number\">0000000000000000</span> x0 : <span class=\"number\">00000000f</span>fffffff</span><br><span class=\"line\">[<span class=\"number\">94891.951165</span>] Call trace:</span><br><span class=\"line\">[<span class=\"number\">94891.951166</span>] do_idle+<span class=\"number\">0x100</span>/<span class=\"number\">0x2d8</span></span><br><span class=\"line\">[<span class=\"number\">94891.951168</span>] cpu_startup_entry+<span class=\"number\">0x38</span>/<span class=\"number\">0x48</span></span><br><span class=\"line\">[<span class=\"number\">94891.951170</span>] rest_init+<span class=\"number\">0xc8</span>/<span class=\"number\">0xd0</span></span><br><span class=\"line\">[<span class=\"number\">94891.951173</span>] start_kernel+<span class=\"number\">0x264</span>/<span class=\"number\">0x2b0</span></span><br><span class=\"line\">[<span class=\"number\">94891.951178</span>] __primary_switched+<span class=\"number\">0x80</span>/<span class=\"number\">0x90</span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"将ftrace的buffer打印出来\"><a href=\"#将ftrace的buffer打印出来\" class=\"headerlink\" title=\"将ftrace的buffer打印出来\"></a>将ftrace的buffer打印出来</h3><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">echo</span> z > /proc/sysrq-trigger</span><br></pre></td></tr></table></figure>\n<p>输入完上面的命令之后,可以敲dmesg可以看到ftrace的buff里边的内容全部打印到内核日志中。</p>\n<h3 id=\"显示内存信息\"><a href=\"#显示内存信息\" class=\"headerlink\" title=\"显示内存信息\"></a>显示内存信息</h3><figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">echo m > /proc/sysrq-trigger</span><br></pre></td></tr></table></figure>\n<p>之前敲dmesg可以看到打印的内存信息。</p>\n"},{"title":"Tasklet","_content":"\n## Tasklet执行方式\n大概有一些同学对tasklet的串行化还有点困惑,其实在单处理器上最好理解,所以本帖主要讨论多处理器上tasklet如何实现串行化:同一个tasklet对象同一时刻只能在一个处理器上运行。\n\n在驱动程序中,tasklet是作为一种softirq形式出现的,所以对tasklet对象的提交一般发生在中断处理例程ISR中。一般一个tasklet用来对同一种中断类型进行后续的处理,所以完全不必要通过动态生成tasklet对象的方式在每次中断到来时重新生成一个tasklet对象来做后半段的处理。事实上Linux内核源码中,几乎所有的tasklet对象都是针对同一类型的中断只产生一个。如果有同学发现有例外的情况,请告诉我,将非常感谢。\n\n假设某个中断发生,由CPU0来处理,在它的ISR中会调用tasklet_schedule来提交一个tasklet对象,假设为tasklet_obj,那么tasklet_schedule首先会为该tasklet对象tasklet_obj.state打上一个标志:TASKLET_STATE_SCHED,表明该tasklet对象被提交但还没有被运行,前述的打标志的操作是个原子,代码里是test_and_set_bit,这意味着如果同时有处理器CPU0和CPU1都来提交该tasklet_obj,那么只有一个会被成功提交,不过不用担心一个tasklet对象没被提交成功的话会有啥副作用,因为在softirq的处理阶段,一个tasklet对象上的处理函数可以一并处理掉外设若干次同一中断要做的事,最典型的,比如网卡连续接收到两个数据包,产生两个中断到两个不同处理器上,因为只有一个tasklet对象被提交,当该对象上的延迟函数被执行时,它会将两个数据包都读到系统内存中。\n \nTASKLET_STATE_SCHED标志是确保tasklet串行化的第一道防线,但是如果该tasklet_obj对象已经被调度到处理器CPU0上运行了,那么TASKLET_STATE_SCHED标志会被清除,这意味着当一个tasklet_obj对象正在一个处理器上运行时,同一个tasklet_obj对象完全可以被提交到另一个处理器,比如CPU1上。那么这种情况下如何确保tasklet串行化呢,答案是tasklet_obj.state上为SMP系统增加的另一个标志位TASKLET_STATE_RUN,当一个tasklet_obj对象被某一处理器开始调度运行时,tasklet_action,也就是对应的softirq处理例程会通过tasklet_trylock来将该tasklet_obj对象的state成员打上标志TASKLET_STATE_RUN,这个操作同样是原子的,因此只会有一个处理器成功完成测试及打标志的动作,没成功的那个处理器上的tasklet_action会把当前的tasklet_obj重新加入到其所管理的tasklet_vec链表的尾部(因为一个相同的tasklet_obj对象已经在运行了,所以再期望其一并完成当前tasklet_obj所表示的任务变得不再可靠,这不同于刚提交时的情形,所以内核对此的策略是,把当前希望运行但是发现已经有同一个tasklet_obj对象的延迟函数正在被执行时,将当前对象加入到处理器tasklet_vec的链表尾部)。那先前成功的处理器就可以开始执行tasklet_obj对象上的延迟函数,执行完毕该tasklet_obj对象将从它所在的处理器tasklet_vec链表中消失,除非再次提交。所以一个成功执行的tasklet_obj对象的状态变化是:\nTASKLET_STATE_SCHED(被成功提交)-->TASKLET_STATE_RUN | TASKLET_STATE_SCHED(被提交并且即将被调度运行)-->TASKLET_STATE_RUN(正在被调度执行中)。\n \n而一个不成功的tasklet要么在tasklet_schedule处就被泯灭掉,此时它根本不会出现在任何一个处理器的tasklet_vec链表中,要么是在同一个tasklet对象正在其他处理器上被执行时被成功提交,但是它目前暂时无法被执行,会被放到它所属的处理器tasklet_vec链表的尾部等待下一次被调度运行。\n\n1.\t同一个tasklet在添加之后,在执行之前不能重新添加\n2.\t同一个tasklet在执行的时候,可以重新添加(同一个CPU或者不同的CPU),但不可能并行执行\n\n## Debug\n在sys trace目录下,可以打开相关的开关\n```\n/sys/kernel/debug/tracing/events/irq\nsoftirq_entry softirq_exit softirq_raise tasklet_entry tasklet_exit\n```\ntasklet_entry和tasklet_exit在5.10版本中是没有的,在6.9版本是有的。\n\n## 参考\nhttp://blog.chinaunix.net/uid-23769728-id-3195496.html\n\n","source":"_posts/Tasklet.md","raw":"---\ntitle: Tasklet\ncategories: \n- Linux\ntags:\n- Linux Tasklet\n---\n\n## Tasklet执行方式\n大概有一些同学对tasklet的串行化还有点困惑,其实在单处理器上最好理解,所以本帖主要讨论多处理器上tasklet如何实现串行化:同一个tasklet对象同一时刻只能在一个处理器上运行。\n\n在驱动程序中,tasklet是作为一种softirq形式出现的,所以对tasklet对象的提交一般发生在中断处理例程ISR中。一般一个tasklet用来对同一种中断类型进行后续的处理,所以完全不必要通过动态生成tasklet对象的方式在每次中断到来时重新生成一个tasklet对象来做后半段的处理。事实上Linux内核源码中,几乎所有的tasklet对象都是针对同一类型的中断只产生一个。如果有同学发现有例外的情况,请告诉我,将非常感谢。\n\n假设某个中断发生,由CPU0来处理,在它的ISR中会调用tasklet_schedule来提交一个tasklet对象,假设为tasklet_obj,那么tasklet_schedule首先会为该tasklet对象tasklet_obj.state打上一个标志:TASKLET_STATE_SCHED,表明该tasklet对象被提交但还没有被运行,前述的打标志的操作是个原子,代码里是test_and_set_bit,这意味着如果同时有处理器CPU0和CPU1都来提交该tasklet_obj,那么只有一个会被成功提交,不过不用担心一个tasklet对象没被提交成功的话会有啥副作用,因为在softirq的处理阶段,一个tasklet对象上的处理函数可以一并处理掉外设若干次同一中断要做的事,最典型的,比如网卡连续接收到两个数据包,产生两个中断到两个不同处理器上,因为只有一个tasklet对象被提交,当该对象上的延迟函数被执行时,它会将两个数据包都读到系统内存中。\n \nTASKLET_STATE_SCHED标志是确保tasklet串行化的第一道防线,但是如果该tasklet_obj对象已经被调度到处理器CPU0上运行了,那么TASKLET_STATE_SCHED标志会被清除,这意味着当一个tasklet_obj对象正在一个处理器上运行时,同一个tasklet_obj对象完全可以被提交到另一个处理器,比如CPU1上。那么这种情况下如何确保tasklet串行化呢,答案是tasklet_obj.state上为SMP系统增加的另一个标志位TASKLET_STATE_RUN,当一个tasklet_obj对象被某一处理器开始调度运行时,tasklet_action,也就是对应的softirq处理例程会通过tasklet_trylock来将该tasklet_obj对象的state成员打上标志TASKLET_STATE_RUN,这个操作同样是原子的,因此只会有一个处理器成功完成测试及打标志的动作,没成功的那个处理器上的tasklet_action会把当前的tasklet_obj重新加入到其所管理的tasklet_vec链表的尾部(因为一个相同的tasklet_obj对象已经在运行了,所以再期望其一并完成当前tasklet_obj所表示的任务变得不再可靠,这不同于刚提交时的情形,所以内核对此的策略是,把当前希望运行但是发现已经有同一个tasklet_obj对象的延迟函数正在被执行时,将当前对象加入到处理器tasklet_vec的链表尾部)。那先前成功的处理器就可以开始执行tasklet_obj对象上的延迟函数,执行完毕该tasklet_obj对象将从它所在的处理器tasklet_vec链表中消失,除非再次提交。所以一个成功执行的tasklet_obj对象的状态变化是:\nTASKLET_STATE_SCHED(被成功提交)-->TASKLET_STATE_RUN | TASKLET_STATE_SCHED(被提交并且即将被调度运行)-->TASKLET_STATE_RUN(正在被调度执行中)。\n \n而一个不成功的tasklet要么在tasklet_schedule处就被泯灭掉,此时它根本不会出现在任何一个处理器的tasklet_vec链表中,要么是在同一个tasklet对象正在其他处理器上被执行时被成功提交,但是它目前暂时无法被执行,会被放到它所属的处理器tasklet_vec链表的尾部等待下一次被调度运行。\n\n1.\t同一个tasklet在添加之后,在执行之前不能重新添加\n2.\t同一个tasklet在执行的时候,可以重新添加(同一个CPU或者不同的CPU),但不可能并行执行\n\n## Debug\n在sys trace目录下,可以打开相关的开关\n```\n/sys/kernel/debug/tracing/events/irq\nsoftirq_entry softirq_exit softirq_raise tasklet_entry tasklet_exit\n```\ntasklet_entry和tasklet_exit在5.10版本中是没有的,在6.9版本是有的。\n\n## 参考\nhttp://blog.chinaunix.net/uid-23769728-id-3195496.html\n\n","slug":"Tasklet","published":1,"date":"2024-08-14T10:01:22.767Z","updated":"2024-08-14T10:01:22.767Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfve002tqwq2ecg76s22","content":"<h2 id=\"Tasklet执行方式\"><a href=\"#Tasklet执行方式\" class=\"headerlink\" title=\"Tasklet执行方式\"></a>Tasklet执行方式</h2><p>大概有一些同学对tasklet的串行化还有点困惑,其实在单处理器上最好理解,所以本帖主要讨论多处理器上tasklet如何实现串行化:同一个tasklet对象同一时刻只能在一个处理器上运行。</p>\n<p>在驱动程序中,tasklet是作为一种softirq形式出现的,所以对tasklet对象的提交一般发生在中断处理例程ISR中。一般一个tasklet用来对同一种中断类型进行后续的处理,所以完全不必要通过动态生成tasklet对象的方式在每次中断到来时重新生成一个tasklet对象来做后半段的处理。事实上Linux内核源码中,几乎所有的tasklet对象都是针对同一类型的中断只产生一个。如果有同学发现有例外的情况,请告诉我,将非常感谢。</p>\n<p>假设某个中断发生,由CPU0来处理,在它的ISR中会调用tasklet_schedule来提交一个tasklet对象,假设为tasklet_obj,那么tasklet_schedule首先会为该tasklet对象tasklet_obj.state打上一个标志:TASKLET_STATE_SCHED,表明该tasklet对象被提交但还没有被运行,前述的打标志的操作是个原子,代码里是test_and_set_bit,这意味着如果同时有处理器CPU0和CPU1都来提交该tasklet_obj,那么只有一个会被成功提交,不过不用担心一个tasklet对象没被提交成功的话会有啥副作用,因为在softirq的处理阶段,一个tasklet对象上的处理函数可以一并处理掉外设若干次同一中断要做的事,最典型的,比如网卡连续接收到两个数据包,产生两个中断到两个不同处理器上,因为只有一个tasklet对象被提交,当该对象上的延迟函数被执行时,它会将两个数据包都读到系统内存中。</p>\n<p>TASKLET_STATE_SCHED标志是确保tasklet串行化的第一道防线,但是如果该tasklet_obj对象已经被调度到处理器CPU0上运行了,那么TASKLET_STATE_SCHED标志会被清除,这意味着当一个tasklet_obj对象正在一个处理器上运行时,同一个tasklet_obj对象完全可以被提交到另一个处理器,比如CPU1上。那么这种情况下如何确保tasklet串行化呢,答案是tasklet_obj.state上为SMP系统增加的另一个标志位TASKLET_STATE_RUN,当一个tasklet_obj对象被某一处理器开始调度运行时,tasklet_action,也就是对应的softirq处理例程会通过tasklet_trylock来将该tasklet_obj对象的state成员打上标志TASKLET_STATE_RUN,这个操作同样是原子的,因此只会有一个处理器成功完成测试及打标志的动作,没成功的那个处理器上的tasklet_action会把当前的tasklet_obj重新加入到其所管理的tasklet_vec链表的尾部(因为一个相同的tasklet_obj对象已经在运行了,所以再期望其一并完成当前tasklet_obj所表示的任务变得不再可靠,这不同于刚提交时的情形,所以内核对此的策略是,把当前希望运行但是发现已经有同一个tasklet_obj对象的延迟函数正在被执行时,将当前对象加入到处理器tasklet_vec的链表尾部)。那先前成功的处理器就可以开始执行tasklet_obj对象上的延迟函数,执行完毕该tasklet_obj对象将从它所在的处理器tasklet_vec链表中消失,除非再次提交。所以一个成功执行的tasklet_obj对象的状态变化是:<br>TASKLET_STATE_SCHED(被成功提交)–>TASKLET_STATE_RUN | TASKLET_STATE_SCHED(被提交并且即将被调度运行)–>TASKLET_STATE_RUN(正在被调度执行中)。</p>\n<p>而一个不成功的tasklet要么在tasklet_schedule处就被泯灭掉,此时它根本不会出现在任何一个处理器的tasklet_vec链表中,要么是在同一个tasklet对象正在其他处理器上被执行时被成功提交,但是它目前暂时无法被执行,会被放到它所属的处理器tasklet_vec链表的尾部等待下一次被调度运行。</p>\n<ol>\n<li> 同一个tasklet在添加之后,在执行之前不能重新添加</li>\n<li> 同一个tasklet在执行的时候,可以重新添加(同一个CPU或者不同的CPU),但不可能并行执行</li>\n</ol>\n<h2 id=\"Debug\"><a href=\"#Debug\" class=\"headerlink\" title=\"Debug\"></a>Debug</h2><p>在sys trace目录下,可以打开相关的开关</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">/sys/kernel/debug/tracing/events/irq</span><br><span class=\"line\">softirq_entry softirq_exit softirq_raise tasklet_entry tasklet_exit</span><br></pre></td></tr></table></figure>\n<p>tasklet_entry和tasklet_exit在5.10版本中是没有的,在6.9版本是有的。</p>\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"http://blog.chinaunix.net/uid-23769728-id-3195496.html\">http://blog.chinaunix.net/uid-23769728-id-3195496.html</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"Tasklet执行方式\"><a href=\"#Tasklet执行方式\" class=\"headerlink\" title=\"Tasklet执行方式\"></a>Tasklet执行方式</h2><p>大概有一些同学对tasklet的串行化还有点困惑,其实在单处理器上最好理解,所以本帖主要讨论多处理器上tasklet如何实现串行化:同一个tasklet对象同一时刻只能在一个处理器上运行。</p>\n<p>在驱动程序中,tasklet是作为一种softirq形式出现的,所以对tasklet对象的提交一般发生在中断处理例程ISR中。一般一个tasklet用来对同一种中断类型进行后续的处理,所以完全不必要通过动态生成tasklet对象的方式在每次中断到来时重新生成一个tasklet对象来做后半段的处理。事实上Linux内核源码中,几乎所有的tasklet对象都是针对同一类型的中断只产生一个。如果有同学发现有例外的情况,请告诉我,将非常感谢。</p>\n<p>假设某个中断发生,由CPU0来处理,在它的ISR中会调用tasklet_schedule来提交一个tasklet对象,假设为tasklet_obj,那么tasklet_schedule首先会为该tasklet对象tasklet_obj.state打上一个标志:TASKLET_STATE_SCHED,表明该tasklet对象被提交但还没有被运行,前述的打标志的操作是个原子,代码里是test_and_set_bit,这意味着如果同时有处理器CPU0和CPU1都来提交该tasklet_obj,那么只有一个会被成功提交,不过不用担心一个tasklet对象没被提交成功的话会有啥副作用,因为在softirq的处理阶段,一个tasklet对象上的处理函数可以一并处理掉外设若干次同一中断要做的事,最典型的,比如网卡连续接收到两个数据包,产生两个中断到两个不同处理器上,因为只有一个tasklet对象被提交,当该对象上的延迟函数被执行时,它会将两个数据包都读到系统内存中。</p>\n<p>TASKLET_STATE_SCHED标志是确保tasklet串行化的第一道防线,但是如果该tasklet_obj对象已经被调度到处理器CPU0上运行了,那么TASKLET_STATE_SCHED标志会被清除,这意味着当一个tasklet_obj对象正在一个处理器上运行时,同一个tasklet_obj对象完全可以被提交到另一个处理器,比如CPU1上。那么这种情况下如何确保tasklet串行化呢,答案是tasklet_obj.state上为SMP系统增加的另一个标志位TASKLET_STATE_RUN,当一个tasklet_obj对象被某一处理器开始调度运行时,tasklet_action,也就是对应的softirq处理例程会通过tasklet_trylock来将该tasklet_obj对象的state成员打上标志TASKLET_STATE_RUN,这个操作同样是原子的,因此只会有一个处理器成功完成测试及打标志的动作,没成功的那个处理器上的tasklet_action会把当前的tasklet_obj重新加入到其所管理的tasklet_vec链表的尾部(因为一个相同的tasklet_obj对象已经在运行了,所以再期望其一并完成当前tasklet_obj所表示的任务变得不再可靠,这不同于刚提交时的情形,所以内核对此的策略是,把当前希望运行但是发现已经有同一个tasklet_obj对象的延迟函数正在被执行时,将当前对象加入到处理器tasklet_vec的链表尾部)。那先前成功的处理器就可以开始执行tasklet_obj对象上的延迟函数,执行完毕该tasklet_obj对象将从它所在的处理器tasklet_vec链表中消失,除非再次提交。所以一个成功执行的tasklet_obj对象的状态变化是:<br>TASKLET_STATE_SCHED(被成功提交)–>TASKLET_STATE_RUN | TASKLET_STATE_SCHED(被提交并且即将被调度运行)–>TASKLET_STATE_RUN(正在被调度执行中)。</p>\n<p>而一个不成功的tasklet要么在tasklet_schedule处就被泯灭掉,此时它根本不会出现在任何一个处理器的tasklet_vec链表中,要么是在同一个tasklet对象正在其他处理器上被执行时被成功提交,但是它目前暂时无法被执行,会被放到它所属的处理器tasklet_vec链表的尾部等待下一次被调度运行。</p>\n<ol>\n<li> 同一个tasklet在添加之后,在执行之前不能重新添加</li>\n<li> 同一个tasklet在执行的时候,可以重新添加(同一个CPU或者不同的CPU),但不可能并行执行</li>\n</ol>\n<h2 id=\"Debug\"><a href=\"#Debug\" class=\"headerlink\" title=\"Debug\"></a>Debug</h2><p>在sys trace目录下,可以打开相关的开关</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">/sys/kernel/debug/tracing/events/irq</span><br><span class=\"line\">softirq_entry softirq_exit softirq_raise tasklet_entry tasklet_exit</span><br></pre></td></tr></table></figure>\n<p>tasklet_entry和tasklet_exit在5.10版本中是没有的,在6.9版本是有的。</p>\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"http://blog.chinaunix.net/uid-23769728-id-3195496.html\">http://blog.chinaunix.net/uid-23769728-id-3195496.html</a></p>\n"},{"title":"TLB","_content":"\n## TLB\n### TLB介绍\nTLB是一个cache、是保存MMU最近转换过的内容(TLB hit)。在每次MMU地址转换的时候、都会先\n查看TLB中是否存在、如果有的话就可以直接访问。如果TLB中没有(TLB miss)、就会通过MMU做\n转换并保存在TLB中。TLB中不仅保存虚拟地址和对应的物理地址、也保存\n1)\tattributes such as memory type (见memory ordering)\n2)\tcache policies\n3)\taccess permissions \n4)\tthe Address Space ID (ASID), and the Virtual Machine ID (VMID)。\n\n如果MMU页表在建立之后、中途需要调整变化、在修改完MMU对应的页表之后、就要刷新(invalidate)TLB。\n\n### TLB刷新\nTLBI命令就是负责刷新TLB。\n\nTLBI <type><level>{IS} {, <Xt>}\n\ntype字段:\nALL:刷新所有TLB entry\nVMALL: 刷新所有stage 1TLB entry\n\n\nhttps://aijishu.com/a/1060000000381352\n","source":"_posts/TLB.md","raw":"---\ntitle: TLB\ncategories: \n- Aarch64\ntags:\n- TLB\n---\n\n## TLB\n### TLB介绍\nTLB是一个cache、是保存MMU最近转换过的内容(TLB hit)。在每次MMU地址转换的时候、都会先\n查看TLB中是否存在、如果有的话就可以直接访问。如果TLB中没有(TLB miss)、就会通过MMU做\n转换并保存在TLB中。TLB中不仅保存虚拟地址和对应的物理地址、也保存\n1)\tattributes such as memory type (见memory ordering)\n2)\tcache policies\n3)\taccess permissions \n4)\tthe Address Space ID (ASID), and the Virtual Machine ID (VMID)。\n\n如果MMU页表在建立之后、中途需要调整变化、在修改完MMU对应的页表之后、就要刷新(invalidate)TLB。\n\n### TLB刷新\nTLBI命令就是负责刷新TLB。\n\nTLBI <type><level>{IS} {, <Xt>}\n\ntype字段:\nALL:刷新所有TLB entry\nVMALL: 刷新所有stage 1TLB entry\n\n\nhttps://aijishu.com/a/1060000000381352\n","slug":"TLB","published":1,"date":"2024-08-16T12:53:51.257Z","updated":"2024-08-16T12:53:51.257Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfve002wqwq2bbff9jyn","content":"<h2 id=\"TLB\"><a href=\"#TLB\" class=\"headerlink\" title=\"TLB\"></a>TLB</h2><h3 id=\"TLB介绍\"><a href=\"#TLB介绍\" class=\"headerlink\" title=\"TLB介绍\"></a>TLB介绍</h3><p>TLB是一个cache、是保存MMU最近转换过的内容(TLB hit)。在每次MMU地址转换的时候、都会先<br>查看TLB中是否存在、如果有的话就可以直接访问。如果TLB中没有(TLB miss)、就会通过MMU做<br>转换并保存在TLB中。TLB中不仅保存虚拟地址和对应的物理地址、也保存<br>1)\tattributes such as memory type (见memory ordering)<br>2)\tcache policies<br>3)\taccess permissions<br>4)\tthe Address Space ID (ASID), and the Virtual Machine ID (VMID)。</p>\n<p>如果MMU页表在建立之后、中途需要调整变化、在修改完MMU对应的页表之后、就要刷新(invalidate)TLB。</p>\n<h3 id=\"TLB刷新\"><a href=\"#TLB刷新\" class=\"headerlink\" title=\"TLB刷新\"></a>TLB刷新</h3><p>TLBI命令就是负责刷新TLB。</p>\n<p>TLBI <type><level>{IS} {, <Xt>}</Xt></level></type></p>\n<p>type字段:<br>ALL:刷新所有TLB entry<br>VMALL: 刷新所有stage 1TLB entry</p>\n<p><a href=\"https://aijishu.com/a/1060000000381352\">https://aijishu.com/a/1060000000381352</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"TLB\"><a href=\"#TLB\" class=\"headerlink\" title=\"TLB\"></a>TLB</h2><h3 id=\"TLB介绍\"><a href=\"#TLB介绍\" class=\"headerlink\" title=\"TLB介绍\"></a>TLB介绍</h3><p>TLB是一个cache、是保存MMU最近转换过的内容(TLB hit)。在每次MMU地址转换的时候、都会先<br>查看TLB中是否存在、如果有的话就可以直接访问。如果TLB中没有(TLB miss)、就会通过MMU做<br>转换并保存在TLB中。TLB中不仅保存虚拟地址和对应的物理地址、也保存<br>1)\tattributes such as memory type (见memory ordering)<br>2)\tcache policies<br>3)\taccess permissions<br>4)\tthe Address Space ID (ASID), and the Virtual Machine ID (VMID)。</p>\n<p>如果MMU页表在建立之后、中途需要调整变化、在修改完MMU对应的页表之后、就要刷新(invalidate)TLB。</p>\n<h3 id=\"TLB刷新\"><a href=\"#TLB刷新\" class=\"headerlink\" title=\"TLB刷新\"></a>TLB刷新</h3><p>TLBI命令就是负责刷新TLB。</p>\n<p>TLBI <type><level>{IS} {, <Xt>}</Xt></level></type></p>\n<p>type字段:<br>ALL:刷新所有TLB entry<br>VMALL: 刷新所有stage 1TLB entry</p>\n<p><a href=\"https://aijishu.com/a/1060000000381352\">https://aijishu.com/a/1060000000381352</a></p>\n"},{"title":"Timer","_content":"\n## Sleep接口注意\n在使用这类接口的时候,有一些原则需要遵守:(根据等待时间长短)\n\n1.等待时间很短(< ~10us)\n 这时最好使用udelay替换usleep_range。\n\n2.睡眠时间在(10us ~ 20ms)\n 这个时间范围,最好使用usleep_range进行睡眠\n\n3.睡眠时间较长(10ms+)\n 使用msleep或者msleep_interruptible。\n","source":"_posts/Timer.md","raw":"---\ntitle: Timer\ncategories: \n- Linux\ntags:\n- Linux Timer\n---\n\n## Sleep接口注意\n在使用这类接口的时候,有一些原则需要遵守:(根据等待时间长短)\n\n1.等待时间很短(< ~10us)\n 这时最好使用udelay替换usleep_range。\n\n2.睡眠时间在(10us ~ 20ms)\n 这个时间范围,最好使用usleep_range进行睡眠\n\n3.睡眠时间较长(10ms+)\n 使用msleep或者msleep_interruptible。\n","slug":"Timer","published":1,"date":"2024-08-14T10:01:22.767Z","updated":"2024-08-14T10:01:22.767Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfve002zqwq24zxoeww9","content":"<h2 id=\"Sleep接口注意\"><a href=\"#Sleep接口注意\" class=\"headerlink\" title=\"Sleep接口注意\"></a>Sleep接口注意</h2><p>在使用这类接口的时候,有一些原则需要遵守:(根据等待时间长短)</p>\n<p>1.等待时间很短(< ~10us)<br> 这时最好使用udelay替换usleep_range。</p>\n<p>2.睡眠时间在(10us ~ 20ms)<br> 这个时间范围,最好使用usleep_range进行睡眠</p>\n<p>3.睡眠时间较长(10ms+)<br> 使用msleep或者msleep_interruptible。</p>\n","cover":false,"excerpt":"","more":"<h2 id=\"Sleep接口注意\"><a href=\"#Sleep接口注意\" class=\"headerlink\" title=\"Sleep接口注意\"></a>Sleep接口注意</h2><p>在使用这类接口的时候,有一些原则需要遵守:(根据等待时间长短)</p>\n<p>1.等待时间很短(< ~10us)<br> 这时最好使用udelay替换usleep_range。</p>\n<p>2.睡眠时间在(10us ~ 20ms)<br> 这个时间范围,最好使用usleep_range进行睡眠</p>\n<p>3.睡眠时间较长(10ms+)<br> 使用msleep或者msleep_interruptible。</p>\n"},{"title":"Virt","_content":"\n## 参考\nhttps://www.cnblogs.com/LoyenWang/category/1828942.html\n","source":"_posts/Virt.md","raw":"---\ntitle: Virt\ncategories: \n- Linux\ntags:\n- Linux Virt\n---\n\n## 参考\nhttps://www.cnblogs.com/LoyenWang/category/1828942.html\n","slug":"Virt","published":1,"date":"2024-08-15T10:25:51.989Z","updated":"2024-08-15T10:25:51.989Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvf0032qwq23c85boe9","content":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://www.cnblogs.com/LoyenWang/category/1828942.html\">https://www.cnblogs.com/LoyenWang/category/1828942.html</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://www.cnblogs.com/LoyenWang/category/1828942.html\">https://www.cnblogs.com/LoyenWang/category/1828942.html</a></p>\n"},{"title":"TraceEvent","_content":"","source":"_posts/TraceEvent.md","raw":"---\ntitle: TraceEvent\ncategories: \n- Linux\ntags:\n- Linux Trace\n---\n","slug":"TraceEvent","published":1,"date":"2024-08-10T10:31:17.359Z","updated":"2024-08-10T16:14:25.065Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvf0035qwq2fq43cgxr","content":"","cover":false,"excerpt":"","more":""},{"title":"FileSystem","_content":"\n## 参考\n\nhttps://cloud.tencent.com/developer/article/1645411\n","source":"_posts/Vmcore.md","raw":"---\ntitle: FileSystem\ncategories: \n- Linux\ntags:\n- Linux Vmcore\n---\n\n## 参考\n\nhttps://cloud.tencent.com/developer/article/1645411\n","slug":"Vmcore","published":1,"date":"2024-08-13T13:15:23.310Z","updated":"2024-08-13T13:15:23.310Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvf0038qwq21dak3hh0","content":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://cloud.tencent.com/developer/article/1645411\">https://cloud.tencent.com/developer/article/1645411</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p><a href=\"https://cloud.tencent.com/developer/article/1645411\">https://cloud.tencent.com/developer/article/1645411</a></p>\n"},{"title":"Workqueue","_content":"\n## alloc_workqueue WQ_UNBOUND的时候创建线程\n在内核态ps -ef可以看到alloc_workqueue调用的时候创建的线程。例如名字是xxx_wq的时候, 5.15版本是[xxx_wq],6.6x版本是显示[kworker/R-xxx_wq]。\n这个线程是在init_rescuer的时候创建的。什么时候在这个worker里边执行,后面再看一下。\n在queue_work的时候,真正执行的并不是上面的线程,一般都是在新创建的kworkerxxx执行。因为在alloc_workqueue的时候会选择条件一致的\nstruct worker_pool并在这个上面执行。\n\n\n## work被中断抢占\n1. work每次都执行在cpu0的时候被中断抢占,可以设置work的cpumask不让work在cpu0上执行\n```bash\n/sys/devices/virtual/workqueue# echo ffe >cpumask\n```\n\n## Workqueue Trace\n### Trace节点\n在sys trace目录/sys/kernel/debug/tracing/events/workqueue下,可以看到几个event节点。\n\n```bash\n/sys/kernel/debug/tracing/events/workqueue/\nworkqueue_activate_work workqueue_execute_end workqueue_execute_start workqueue_queue_work\n```\n所有的都打开就可以看到所有work执行的过程\n\n### Work消耗太多CPU Cycles(Top命令能看到)\n\nWorker线程通过ps命令打印如下:\n```bash\nroot 5671 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/0:1]\nroot 5672 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/1:2]\nroot 5673 0.0 0.0 0 0 ? S 12:12 0:00 [kworker/0:0]\nroot 5674 0.0 0.0 0 0 ? S 12:13 0:00 [kworker/1:0]\n```\n\n以下几种可能\n1.Work切换频繁\n```bash\n$echo workqueue:workqueue_queue_work > /sys/kernel/tracing/set_event\n$cat /sys/kernel/tracing/trace_pipe > out.txt \n(wait a few secs) \n^C\n```\n这样可以看到所有的Work执行的情况。\n\n```bash\n<idle>-0 [005] dNs.. 25598.686997: workqueue_queue_work: work struct=00000000b8691ef7 function=nf_flow_offload_work_gc workqueue=events_power_efficient req_cpu=24 cpu=-1\n```\nfunction=‘Work函数名’就是Work的函数。\n\n2.Work一次执行消耗太多\n使用如下方式查看kwork的调用栈。\n```bash\n$cat /proc/THE_OFFENDING_KWORKER/stack\n```\nTHE_OFFENDING_KWORKER就是Worker线程的pid。\n\n\n## 接口使用注意\n#### cancle_work_sync\n如果work的回调函数中有等待信号量等操作的时候,直接调用destroy_workqueue是会有报错的。\n正确的做法是:\n\n1.唤醒work回调函数的信号量等待\n\n2.调用cancel_work_sync等待work结束\n\n3.调用destroy_workqueue销毁workqueue\n\n## 参考\nLinux/Documentation/core-api/workqueue.rst\nhttps://www.kernel.org/doc/html/v5.14/translations/zh_CN/core-api/workqueue.html\nhttps://events.static.linuxfound.org/sites/events/files/slides/Async%20execution%20with%20wqs.pdf\n\nhttps://www.kernel.org/doc/Documentation/core-api/workqueue.rst\n\nhttps://lwn.net/Articles/932431/\n\n\nhttps://docs.kernel.org/core-api/workqueue.html\n\n","source":"_posts/Workqueue.md","raw":"---\ntitle: Workqueue\ncategories: \n- Linux\ntags:\n- Linux Workqueue\n---\n\n## alloc_workqueue WQ_UNBOUND的时候创建线程\n在内核态ps -ef可以看到alloc_workqueue调用的时候创建的线程。例如名字是xxx_wq的时候, 5.15版本是[xxx_wq],6.6x版本是显示[kworker/R-xxx_wq]。\n这个线程是在init_rescuer的时候创建的。什么时候在这个worker里边执行,后面再看一下。\n在queue_work的时候,真正执行的并不是上面的线程,一般都是在新创建的kworkerxxx执行。因为在alloc_workqueue的时候会选择条件一致的\nstruct worker_pool并在这个上面执行。\n\n\n## work被中断抢占\n1. work每次都执行在cpu0的时候被中断抢占,可以设置work的cpumask不让work在cpu0上执行\n```bash\n/sys/devices/virtual/workqueue# echo ffe >cpumask\n```\n\n## Workqueue Trace\n### Trace节点\n在sys trace目录/sys/kernel/debug/tracing/events/workqueue下,可以看到几个event节点。\n\n```bash\n/sys/kernel/debug/tracing/events/workqueue/\nworkqueue_activate_work workqueue_execute_end workqueue_execute_start workqueue_queue_work\n```\n所有的都打开就可以看到所有work执行的过程\n\n### Work消耗太多CPU Cycles(Top命令能看到)\n\nWorker线程通过ps命令打印如下:\n```bash\nroot 5671 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/0:1]\nroot 5672 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/1:2]\nroot 5673 0.0 0.0 0 0 ? S 12:12 0:00 [kworker/0:0]\nroot 5674 0.0 0.0 0 0 ? S 12:13 0:00 [kworker/1:0]\n```\n\n以下几种可能\n1.Work切换频繁\n```bash\n$echo workqueue:workqueue_queue_work > /sys/kernel/tracing/set_event\n$cat /sys/kernel/tracing/trace_pipe > out.txt \n(wait a few secs) \n^C\n```\n这样可以看到所有的Work执行的情况。\n\n```bash\n<idle>-0 [005] dNs.. 25598.686997: workqueue_queue_work: work struct=00000000b8691ef7 function=nf_flow_offload_work_gc workqueue=events_power_efficient req_cpu=24 cpu=-1\n```\nfunction=‘Work函数名’就是Work的函数。\n\n2.Work一次执行消耗太多\n使用如下方式查看kwork的调用栈。\n```bash\n$cat /proc/THE_OFFENDING_KWORKER/stack\n```\nTHE_OFFENDING_KWORKER就是Worker线程的pid。\n\n\n## 接口使用注意\n#### cancle_work_sync\n如果work的回调函数中有等待信号量等操作的时候,直接调用destroy_workqueue是会有报错的。\n正确的做法是:\n\n1.唤醒work回调函数的信号量等待\n\n2.调用cancel_work_sync等待work结束\n\n3.调用destroy_workqueue销毁workqueue\n\n## 参考\nLinux/Documentation/core-api/workqueue.rst\nhttps://www.kernel.org/doc/html/v5.14/translations/zh_CN/core-api/workqueue.html\nhttps://events.static.linuxfound.org/sites/events/files/slides/Async%20execution%20with%20wqs.pdf\n\nhttps://www.kernel.org/doc/Documentation/core-api/workqueue.rst\n\nhttps://lwn.net/Articles/932431/\n\n\nhttps://docs.kernel.org/core-api/workqueue.html\n\n","slug":"Workqueue","published":1,"date":"2024-08-16T12:53:51.257Z","updated":"2024-08-16T12:53:51.257Z","comments":1,"layout":"post","photos":[],"_id":"clzy4nfvf003bqwq28ywt94x3","content":"<h2 id=\"alloc-workqueue-WQ-UNBOUND的时候创建线程\"><a href=\"#alloc-workqueue-WQ-UNBOUND的时候创建线程\" class=\"headerlink\" title=\"alloc_workqueue WQ_UNBOUND的时候创建线程\"></a>alloc_workqueue WQ_UNBOUND的时候创建线程</h2><p>在内核态ps -ef可以看到alloc_workqueue调用的时候创建的线程。例如名字是xxx_wq的时候, 5.15版本是[xxx_wq],6.6x版本是显示[kworker/R-xxx_wq]。<br>这个线程是在init_rescuer的时候创建的。什么时候在这个worker里边执行,后面再看一下。<br>在queue_work的时候,真正执行的并不是上面的线程,一般都是在新创建的kworkerxxx执行。因为在alloc_workqueue的时候会选择条件一致的<br>struct worker_pool并在这个上面执行。</p>\n<h2 id=\"work被中断抢占\"><a href=\"#work被中断抢占\" class=\"headerlink\" title=\"work被中断抢占\"></a>work被中断抢占</h2><ol>\n<li>work每次都执行在cpu0的时候被中断抢占,可以设置work的cpumask不让work在cpu0上执行<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">/sys/devices/virtual/workqueue# <span class=\"built_in\">echo</span> ffe >cpumask</span><br></pre></td></tr></table></figure></li>\n</ol>\n<h2 id=\"Workqueue-Trace\"><a href=\"#Workqueue-Trace\" class=\"headerlink\" title=\"Workqueue Trace\"></a>Workqueue Trace</h2><h3 id=\"Trace节点\"><a href=\"#Trace节点\" class=\"headerlink\" title=\"Trace节点\"></a>Trace节点</h3><p>在sys trace目录/sys/kernel/debug/tracing/events/workqueue下,可以看到几个event节点。</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">/sys/kernel/debug/tracing/events/workqueue/</span><br><span class=\"line\">workqueue_activate_work workqueue_execute_end workqueue_execute_start workqueue_queue_work</span><br></pre></td></tr></table></figure>\n<p>所有的都打开就可以看到所有work执行的过程</p>\n<h3 id=\"Work消耗太多CPU-Cycles-Top命令能看到\"><a href=\"#Work消耗太多CPU-Cycles-Top命令能看到\" class=\"headerlink\" title=\"Work消耗太多CPU Cycles(Top命令能看到)\"></a>Work消耗太多CPU Cycles(Top命令能看到)</h3><p>Worker线程通过ps命令打印如下:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">root 5671 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/0:1]</span><br><span class=\"line\">root 5672 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/1:2]</span><br><span class=\"line\">root 5673 0.0 0.0 0 0 ? S 12:12 0:00 [kworker/0:0]</span><br><span class=\"line\">root 5674 0.0 0.0 0 0 ? S 12:13 0:00 [kworker/1:0]</span><br></pre></td></tr></table></figure>\n\n<p>以下几种可能<br>1.Work切换频繁</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"variable\">$echo</span> workqueue:workqueue_queue_work > /sys/kernel/tracing/set_event</span><br><span class=\"line\"><span class=\"variable\">$cat</span> /sys/kernel/tracing/trace_pipe > out.txt </span><br><span class=\"line\">(<span class=\"built_in\">wait</span> a few secs) </span><br><span class=\"line\">^C</span><br></pre></td></tr></table></figure>\n<p>这样可以看到所有的Work执行的情况。</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><idle>-0 [005] dNs.. 25598.686997: workqueue_queue_work: work struct=00000000b8691ef7 <span class=\"keyword\">function</span>=nf_flow_offload_work_gc workqueue=events_power_efficient req_cpu=24 cpu=-1</span><br></pre></td></tr></table></figure>\n<p>function=‘Work函数名’就是Work的函数。</p>\n<p>2.Work一次执行消耗太多<br>使用如下方式查看kwork的调用栈。</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"variable\">$cat</span> /proc/THE_OFFENDING_KWORKER/stack</span><br></pre></td></tr></table></figure>\n<p>THE_OFFENDING_KWORKER就是Worker线程的pid。</p>\n<h2 id=\"接口使用注意\"><a href=\"#接口使用注意\" class=\"headerlink\" title=\"接口使用注意\"></a>接口使用注意</h2><h4 id=\"cancle-work-sync\"><a href=\"#cancle-work-sync\" class=\"headerlink\" title=\"cancle_work_sync\"></a>cancle_work_sync</h4><p>如果work的回调函数中有等待信号量等操作的时候,直接调用destroy_workqueue是会有报错的。<br>正确的做法是:</p>\n<p>1.唤醒work回调函数的信号量等待</p>\n<p>2.调用cancel_work_sync等待work结束</p>\n<p>3.调用destroy_workqueue销毁workqueue</p>\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p>Linux/Documentation/core-api/workqueue.rst<br><a href=\"https://www.kernel.org/doc/html/v5.14/translations/zh_CN/core-api/workqueue.html\">https://www.kernel.org/doc/html/v5.14/translations/zh_CN/core-api/workqueue.html</a><br><a href=\"https://events.static.linuxfound.org/sites/events/files/slides/Async%20execution%20with%20wqs.pdf\">https://events.static.linuxfound.org/sites/events/files/slides/Async%20execution%20with%20wqs.pdf</a></p>\n<p><a href=\"https://www.kernel.org/doc/Documentation/core-api/workqueue.rst\">https://www.kernel.org/doc/Documentation/core-api/workqueue.rst</a></p>\n<p><a href=\"https://lwn.net/Articles/932431/\">https://lwn.net/Articles/932431/</a></p>\n<p><a href=\"https://docs.kernel.org/core-api/workqueue.html\">https://docs.kernel.org/core-api/workqueue.html</a></p>\n","cover":false,"excerpt":"","more":"<h2 id=\"alloc-workqueue-WQ-UNBOUND的时候创建线程\"><a href=\"#alloc-workqueue-WQ-UNBOUND的时候创建线程\" class=\"headerlink\" title=\"alloc_workqueue WQ_UNBOUND的时候创建线程\"></a>alloc_workqueue WQ_UNBOUND的时候创建线程</h2><p>在内核态ps -ef可以看到alloc_workqueue调用的时候创建的线程。例如名字是xxx_wq的时候, 5.15版本是[xxx_wq],6.6x版本是显示[kworker/R-xxx_wq]。<br>这个线程是在init_rescuer的时候创建的。什么时候在这个worker里边执行,后面再看一下。<br>在queue_work的时候,真正执行的并不是上面的线程,一般都是在新创建的kworkerxxx执行。因为在alloc_workqueue的时候会选择条件一致的<br>struct worker_pool并在这个上面执行。</p>\n<h2 id=\"work被中断抢占\"><a href=\"#work被中断抢占\" class=\"headerlink\" title=\"work被中断抢占\"></a>work被中断抢占</h2><ol>\n<li>work每次都执行在cpu0的时候被中断抢占,可以设置work的cpumask不让work在cpu0上执行<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">/sys/devices/virtual/workqueue# <span class=\"built_in\">echo</span> ffe >cpumask</span><br></pre></td></tr></table></figure></li>\n</ol>\n<h2 id=\"Workqueue-Trace\"><a href=\"#Workqueue-Trace\" class=\"headerlink\" title=\"Workqueue Trace\"></a>Workqueue Trace</h2><h3 id=\"Trace节点\"><a href=\"#Trace节点\" class=\"headerlink\" title=\"Trace节点\"></a>Trace节点</h3><p>在sys trace目录/sys/kernel/debug/tracing/events/workqueue下,可以看到几个event节点。</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">/sys/kernel/debug/tracing/events/workqueue/</span><br><span class=\"line\">workqueue_activate_work workqueue_execute_end workqueue_execute_start workqueue_queue_work</span><br></pre></td></tr></table></figure>\n<p>所有的都打开就可以看到所有work执行的过程</p>\n<h3 id=\"Work消耗太多CPU-Cycles-Top命令能看到\"><a href=\"#Work消耗太多CPU-Cycles-Top命令能看到\" class=\"headerlink\" title=\"Work消耗太多CPU Cycles(Top命令能看到)\"></a>Work消耗太多CPU Cycles(Top命令能看到)</h3><p>Worker线程通过ps命令打印如下:</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">root 5671 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/0:1]</span><br><span class=\"line\">root 5672 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/1:2]</span><br><span class=\"line\">root 5673 0.0 0.0 0 0 ? S 12:12 0:00 [kworker/0:0]</span><br><span class=\"line\">root 5674 0.0 0.0 0 0 ? S 12:13 0:00 [kworker/1:0]</span><br></pre></td></tr></table></figure>\n\n<p>以下几种可能<br>1.Work切换频繁</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"variable\">$echo</span> workqueue:workqueue_queue_work > /sys/kernel/tracing/set_event</span><br><span class=\"line\"><span class=\"variable\">$cat</span> /sys/kernel/tracing/trace_pipe > out.txt </span><br><span class=\"line\">(<span class=\"built_in\">wait</span> a few secs) </span><br><span class=\"line\">^C</span><br></pre></td></tr></table></figure>\n<p>这样可以看到所有的Work执行的情况。</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><idle>-0 [005] dNs.. 25598.686997: workqueue_queue_work: work struct=00000000b8691ef7 <span class=\"keyword\">function</span>=nf_flow_offload_work_gc workqueue=events_power_efficient req_cpu=24 cpu=-1</span><br></pre></td></tr></table></figure>\n<p>function=‘Work函数名’就是Work的函数。</p>\n<p>2.Work一次执行消耗太多<br>使用如下方式查看kwork的调用栈。</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"variable\">$cat</span> /proc/THE_OFFENDING_KWORKER/stack</span><br></pre></td></tr></table></figure>\n<p>THE_OFFENDING_KWORKER就是Worker线程的pid。</p>\n<h2 id=\"接口使用注意\"><a href=\"#接口使用注意\" class=\"headerlink\" title=\"接口使用注意\"></a>接口使用注意</h2><h4 id=\"cancle-work-sync\"><a href=\"#cancle-work-sync\" class=\"headerlink\" title=\"cancle_work_sync\"></a>cancle_work_sync</h4><p>如果work的回调函数中有等待信号量等操作的时候,直接调用destroy_workqueue是会有报错的。<br>正确的做法是:</p>\n<p>1.唤醒work回调函数的信号量等待</p>\n<p>2.调用cancel_work_sync等待work结束</p>\n<p>3.调用destroy_workqueue销毁workqueue</p>\n<h2 id=\"参考\"><a href=\"#参考\" class=\"headerlink\" title=\"参考\"></a>参考</h2><p>Linux/Documentation/core-api/workqueue.rst<br><a href=\"https://www.kernel.org/doc/html/v5.14/translations/zh_CN/core-api/workqueue.html\">https://www.kernel.org/doc/html/v5.14/translations/zh_CN/core-api/workqueue.html</a><br><a href=\"https://events.static.linuxfound.org/sites/events/files/slides/Async%20execution%20with%20wqs.pdf\">https://events.static.linuxfound.org/sites/events/files/slides/Async%20execution%20with%20wqs.pdf</a></p>\n<p><a href=\"https://www.kernel.org/doc/Documentation/core-api/workqueue.rst\">https://www.kernel.org/doc/Documentation/core-api/workqueue.rst</a></p>\n<p><a href=\"https://lwn.net/Articles/932431/\">https://lwn.net/Articles/932431/</a></p>\n<p><a href=\"https://docs.kernel.org/core-api/workqueue.html\">https://docs.kernel.org/core-api/workqueue.html</a></p>\n"}],"PostAsset":[],"PostCategory":[{"post_id":"clzy4nfv60007qwq2bt90allp","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfv7000eqwq29ww8hel5"},{"post_id":"clzy4nfv30001qwq28ysbewz7","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfv8000iqwq214to21of"},{"post_id":"clzy4nfv60008qwq2a7oj7ofb","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfv8000lqwq2b68n4w3r"},{"post_id":"clzy4nfv40003qwq275l30yxs","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfv9000pqwq22j107f13"},{"post_id":"clzy4nfv60006qwq2g68adhqv","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfv9000sqwq2080t2ug6"},{"post_id":"clzy4nfv8000kqwq29vtja4vn","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfv9000wqwq2gr0f8zl7"},{"post_id":"clzy4nfv8000oqwq27co9cmc6","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfv9000zqwq29j5w5wqa"},{"post_id":"clzy4nfv7000cqwq2626mbjkl","category_id":"clzy4nfv8000mqwq2gvzq3hr1","_id":"clzy4nfva0012qwq225ua48k7"},{"post_id":"clzy4nfv9000vqwq2awaxh58w","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfva0016qwq24r9084wq"},{"post_id":"clzy4nfv7000dqwq2790t9qxu","category_id":"clzy4nfv9000tqwq24xr26zdp","_id":"clzy4nfva0019qwq23geceanp"},{"post_id":"clzy4nfv9000yqwq273651wqs","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfva001cqwq22cryc9a4"},{"post_id":"clzy4nfv90011qwq26vpcevfn","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfva001fqwq25uec4dj7"},{"post_id":"clzy4nfv8000hqwq22xw145j1","category_id":"clzy4nfv9000tqwq24xr26zdp","_id":"clzy4nfvb001jqwq25vtj258h"},{"post_id":"clzy4nfva0015qwq26vaoband","category_id":"clzy4nfv9000tqwq24xr26zdp","_id":"clzy4nfvb001mqwq2gmaw67jy"},{"post_id":"clzy4nfva0018qwq29u71ht4v","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvb001pqwq2dh4rcgon"},{"post_id":"clzy4nfv9000rqwq26vqd8xan","category_id":"clzy4nfva0017qwq21ps1ang8","_id":"clzy4nfvb001sqwq29s654w3t"},{"post_id":"clzy4nfva001bqwq28r3ygwqa","category_id":"clzy4nfv9000tqwq24xr26zdp","_id":"clzy4nfvc001uqwq22u33fabi"},{"post_id":"clzy4nfva001eqwq22fj0ctl7","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvc001yqwq2baqg22mf"},{"post_id":"clzy4nfvb001iqwq24r3e0lvy","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvc0020qwq282w21688"},{"post_id":"clzy4nfvb001oqwq2gl716v3p","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvd0023qwq2dz3qe01r"},{"post_id":"clzy4nfvb001rqwq2ctts5hp2","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvd0026qwq26hgogdbd"},{"post_id":"clzy4nfvc001tqwq2cae7eo0l","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvd0029qwq28upibog8"},{"post_id":"clzy4nfvc001xqwq2dj3ud2je","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvd002cqwq217x4d0gp"},{"post_id":"clzy4nfvc001zqwq2ayi24uek","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvd002gqwq2e3t0gq39"},{"post_id":"clzy4nfvc0022qwq2hytjajnl","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvd002jqwq22y7p0q76"},{"post_id":"clzy4nfvd0025qwq2gwdu1ft3","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfve002lqwq2gdjfar3e"},{"post_id":"clzy4nfvd0028qwq208ml6kav","category_id":"clzy4nfv8000mqwq2gvzq3hr1","_id":"clzy4nfve002pqwq29z7reexo"},{"post_id":"clzy4nfvd002bqwq2de6pcrg0","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfve002rqwq269zba9yg"},{"post_id":"clzy4nfvd002fqwq22mkhbyd1","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfve002uqwq254849kn5"},{"post_id":"clzy4nfvd002iqwq2avoi2a9j","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfve002xqwq2as2906tv"},{"post_id":"clzy4nfve002kqwq2awsqgcyy","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvf0030qwq27g2581v5"},{"post_id":"clzy4nfve002oqwq21hatar30","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvf0033qwq26vvlgas5"},{"post_id":"clzy4nfve002qqwq2hl5j7m9t","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvf0036qwq20fzv2r7f"},{"post_id":"clzy4nfve002tqwq2ecg76s22","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvf0039qwq2f5ps8hww"},{"post_id":"clzy4nfve002wqwq2bbff9jyn","category_id":"clzy4nfv9000tqwq24xr26zdp","_id":"clzy4nfvf003cqwq21alt3cjb"},{"post_id":"clzy4nfve002zqwq24zxoeww9","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvf003fqwq26v2wh96f"},{"post_id":"clzy4nfvf0032qwq23c85boe9","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvf003hqwq27cpzbr8u"},{"post_id":"clzy4nfvf0035qwq2fq43cgxr","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvf003jqwq2cuitcbl7"},{"post_id":"clzy4nfvf0038qwq21dak3hh0","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvf003lqwq29tzueie2"},{"post_id":"clzy4nfvf003bqwq28ywt94x3","category_id":"clzy4nfv50004qwq21w7igwdh","_id":"clzy4nfvg003nqwq23bbkbie3"}],"PostTag":[{"post_id":"clzy4nfv30001qwq28ysbewz7","tag_id":"clzy4nfv50005qwq2c233h9qx","_id":"clzy4nfv7000bqwq27ema6ooc"},{"post_id":"clzy4nfv40003qwq275l30yxs","tag_id":"clzy4nfv6000aqwq25pn0hvcw","_id":"clzy4nfv8000jqwq2fik2h18j"},{"post_id":"clzy4nfv60006qwq2g68adhqv","tag_id":"clzy4nfv8000gqwq2hgro1k6d","_id":"clzy4nfv9000qqwq2aq24hzd9"},{"post_id":"clzy4nfv60007qwq2bt90allp","tag_id":"clzy4nfv8000nqwq286av49n0","_id":"clzy4nfv9000xqwq28wdg9j91"},{"post_id":"clzy4nfv60008qwq2a7oj7ofb","tag_id":"clzy4nfv9000uqwq25uuq7xuz","_id":"clzy4nfva0014qwq2a74g4bou"},{"post_id":"clzy4nfv7000cqwq2626mbjkl","tag_id":"clzy4nfva0013qwq205a033df","_id":"clzy4nfva001dqwq2ed2i1k64"},{"post_id":"clzy4nfva0018qwq29u71ht4v","tag_id":"clzy4nfv9000uqwq25uuq7xuz","_id":"clzy4nfvb001gqwq23tuj8d21"},{"post_id":"clzy4nfv7000dqwq2790t9qxu","tag_id":"clzy4nfva001aqwq21vb3442u","_id":"clzy4nfvb001kqwq2hwdh6vbj"},{"post_id":"clzy4nfv8000hqwq22xw145j1","tag_id":"clzy4nfvb001hqwq2d0yj7rn8","_id":"clzy4nfvb001qqwq23wypef9i"},{"post_id":"clzy4nfv8000kqwq29vtja4vn","tag_id":"clzy4nfvb001nqwq2b0w2cxuw","_id":"clzy4nfvc001wqwq259ia6iub"},{"post_id":"clzy4nfv8000oqwq27co9cmc6","tag_id":"clzy4nfvc001vqwq2a9nxdtts","_id":"clzy4nfvd0024qwq22lru8t8n"},{"post_id":"clzy4nfv9000rqwq26vqd8xan","tag_id":"clzy4nfvc0021qwq2307ne2qb","_id":"clzy4nfvd002aqwq2bpxc3lw1"},{"post_id":"clzy4nfvd0028qwq208ml6kav","tag_id":"clzy4nfva0013qwq205a033df","_id":"clzy4nfvd002dqwq2adpa5u22"},{"post_id":"clzy4nfv9000vqwq2awaxh58w","tag_id":"clzy4nfvd0027qwq2gcdp91l3","_id":"clzy4nfvd002hqwq23p5d0sy7"},{"post_id":"clzy4nfv9000yqwq273651wqs","tag_id":"clzy4nfvd002eqwq2ckvsbkwn","_id":"clzy4nfve002nqwq21nlgcp2v"},{"post_id":"clzy4nfv90011qwq26vpcevfn","tag_id":"clzy4nfve002mqwq2d1fte70y","_id":"clzy4nfve002vqwq25lvrfx35"},{"post_id":"clzy4nfva0015qwq26vaoband","tag_id":"clzy4nfve002sqwq2b20x9rj6","_id":"clzy4nfvf0031qwq2fvsy7xec"},{"post_id":"clzy4nfva001bqwq28r3ygwqa","tag_id":"clzy4nfve002yqwq2cgg39b9s","_id":"clzy4nfvf0037qwq2bzb04w3b"},{"post_id":"clzy4nfvf0032qwq23c85boe9","tag_id":"clzy4nfvd0027qwq2gcdp91l3","_id":"clzy4nfvf003aqwq22q8o9o30"},{"post_id":"clzy4nfvf0035qwq2fq43cgxr","tag_id":"clzy4nfv9000uqwq25uuq7xuz","_id":"clzy4nfvf003eqwq27c1u5g7a"},{"post_id":"clzy4nfva001eqwq22fj0ctl7","tag_id":"clzy4nfvf0034qwq21bmu213i","_id":"clzy4nfvf003gqwq2ffdwa9b2"},{"post_id":"clzy4nfvb001iqwq24r3e0lvy","tag_id":"clzy4nfvf003dqwq2bdqug9tz","_id":"clzy4nfvf003kqwq273247ers"},{"post_id":"clzy4nfvb001oqwq2gl716v3p","tag_id":"clzy4nfvf003iqwq213ubhm9p","_id":"clzy4nfvg003oqwq20dul4msz"},{"post_id":"clzy4nfvb001rqwq2ctts5hp2","tag_id":"clzy4nfvf003mqwq25h3d0ipt","_id":"clzy4nfvg003qqwq2bsvc9k98"},{"post_id":"clzy4nfvc001tqwq2cae7eo0l","tag_id":"clzy4nfvg003pqwq26tje04rd","_id":"clzy4nfvg003sqwq2833y67i8"},{"post_id":"clzy4nfvc001xqwq2dj3ud2je","tag_id":"clzy4nfvg003rqwq2d4rlcog7","_id":"clzy4nfvg003uqwq2hfao3ex5"},{"post_id":"clzy4nfvc001zqwq2ayi24uek","tag_id":"clzy4nfvg003tqwq23sr7frkk","_id":"clzy4nfvg003wqwq2czopfadm"},{"post_id":"clzy4nfvc0022qwq2hytjajnl","tag_id":"clzy4nfvg003vqwq2ad98dw8t","_id":"clzy4nfvg003yqwq2d9tff30n"},{"post_id":"clzy4nfvd0025qwq2gwdu1ft3","tag_id":"clzy4nfvg003xqwq24anvf02o","_id":"clzy4nfvg0040qwq282xl08ef"},{"post_id":"clzy4nfvd002bqwq2de6pcrg0","tag_id":"clzy4nfvg003zqwq2b3fmc3hs","_id":"clzy4nfvg0042qwq29c6f7rfj"},{"post_id":"clzy4nfvd002fqwq22mkhbyd1","tag_id":"clzy4nfvg0041qwq25v9hck8f","_id":"clzy4nfvg0044qwq2eke593u3"},{"post_id":"clzy4nfvd002iqwq2avoi2a9j","tag_id":"clzy4nfvg0043qwq2hf70day3","_id":"clzy4nfvg0046qwq28cut0qn6"},{"post_id":"clzy4nfve002kqwq2awsqgcyy","tag_id":"clzy4nfvg0045qwq271ma2ou5","_id":"clzy4nfvg0048qwq2da0s33hx"},{"post_id":"clzy4nfve002oqwq21hatar30","tag_id":"clzy4nfvg0047qwq2excfeag5","_id":"clzy4nfvg004aqwq28tw50yjo"},{"post_id":"clzy4nfve002qqwq2hl5j7m9t","tag_id":"clzy4nfvg0049qwq246npdu6k","_id":"clzy4nfvg004cqwq253gm4yr3"},{"post_id":"clzy4nfve002tqwq2ecg76s22","tag_id":"clzy4nfvg004bqwq2b3al18to","_id":"clzy4nfvg004eqwq2fkn844g6"},{"post_id":"clzy4nfve002wqwq2bbff9jyn","tag_id":"clzy4nfvg004dqwq25m1z7dkt","_id":"clzy4nfvg004gqwq2gl3087pu"},{"post_id":"clzy4nfve002zqwq24zxoeww9","tag_id":"clzy4nfvg004fqwq2hefrf7dy","_id":"clzy4nfvg004iqwq2dewy5hwu"},{"post_id":"clzy4nfvf0038qwq21dak3hh0","tag_id":"clzy4nfvg004hqwq2g5dv0quj","_id":"clzy4nfvg004kqwq2dckza024"},{"post_id":"clzy4nfvf003bqwq28ywt94x3","tag_id":"clzy4nfvg004jqwq2dclcd27o","_id":"clzy4nfvg004lqwq27sw18obs"}],"Tag":[{"name":"Linux Cgroup","_id":"clzy4nfv50005qwq2c233h9qx"},{"name":"Linux Driver","_id":"clzy4nfv6000aqwq25pn0hvcw"},{"name":"Linux DeviceTree","_id":"clzy4nfv8000gqwq2hgro1k6d"},{"name":"Linux Ebuf","_id":"clzy4nfv8000nqwq286av49n0"},{"name":"Linux Trace","_id":"clzy4nfv9000uqwq25uuq7xuz"},{"name":"Gcc Tool","_id":"clzy4nfva0013qwq205a033df"},{"name":"Gic","_id":"clzy4nfva001aqwq21vb3442u"},{"name":"Aarch64","_id":"clzy4nfvb001hqwq2d0yj7rn8"},{"name":"Linux File System","_id":"clzy4nfvb001nqwq2b0w2cxuw"},{"name":"Linux MM","_id":"clzy4nfvc001vqwq2a9nxdtts"},{"name":"I2c Protocol","_id":"clzy4nfvc0021qwq2307ne2qb"},{"name":"Linux Virt","_id":"clzy4nfvd0027qwq2gcdp91l3"},{"name":"Linux Memblock","_id":"clzy4nfvd002eqwq2ckvsbkwn"},{"name":"Linux Debug","_id":"clzy4nfve002mqwq2d1fte70y"},{"name":"Mte","_id":"clzy4nfve002sqwq2b20x9rj6"},{"name":"Mmu","_id":"clzy4nfve002yqwq2cgg39b9s"},{"name":"Linux Net","_id":"clzy4nfvf0034qwq21bmu213i"},{"name":"Linux Numa","_id":"clzy4nfvf003dqwq2bdqug9tz"},{"name":"Linux Perf","_id":"clzy4nfvf003iqwq213ubhm9p"},{"name":"Pgtable","_id":"clzy4nfvf003mqwq25h3d0ipt"},{"name":"Linux PowerManage","_id":"clzy4nfvg003pqwq26tje04rd"},{"name":"Linux Prctl","_id":"clzy4nfvg003rqwq2d4rlcog7"},{"name":"Linux Proc-pagemap","_id":"clzy4nfvg003tqwq23sr7frkk"},{"name":"Linux Process","_id":"clzy4nfvg003vqwq2ad98dw8t"},{"name":"Linux Proc-meminfo","_id":"clzy4nfvg003xqwq24anvf02o"},{"name":"Linux Security","_id":"clzy4nfvg003zqwq2b3fmc3hs"},{"name":"Linux RCU","_id":"clzy4nfvg0041qwq25v9hck8f"},{"name":"Linux Smmu","_id":"clzy4nfvg0043qwq2hf70day3"},{"name":"Linux StartUp","_id":"clzy4nfvg0045qwq271ma2ou5"},{"name":"Linux Spinlock","_id":"clzy4nfvg0047qwq2excfeag5"},{"name":"Linux Sysrq","_id":"clzy4nfvg0049qwq246npdu6k"},{"name":"Linux Tasklet","_id":"clzy4nfvg004bqwq2b3al18to"},{"name":"TLB","_id":"clzy4nfvg004dqwq25m1z7dkt"},{"name":"Linux Timer","_id":"clzy4nfvg004fqwq2hefrf7dy"},{"name":"Linux Vmcore","_id":"clzy4nfvg004hqwq2g5dv0quj"},{"name":"Linux Workqueue","_id":"clzy4nfvg004jqwq2dclcd27o"}]}}