Compare commits
858 Commits
f467a9a309
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f77aa65dc5 | |||
| 9589b5984d | |||
| 32806a5af3 | |||
| 876fbe3d7c | |||
| c1b8f5e475 | |||
| cf31ea9cbe | |||
| 7e6b8c93b4 | |||
| dd2bbe4588 | |||
| e01e35713b | |||
| 82d5d9ba58 | |||
| d168492462 | |||
| 6f2e8320a9 | |||
| bf4831f468 | |||
| 5647cf24d2 | |||
| 85f61aded5 | |||
| 21639071c2 | |||
| 68506a789a | |||
| d9ca25b796 | |||
| e9c81477d7 | |||
| 5c20d5e291 | |||
| f89d690716 | |||
| c563efcd1c | |||
| dedeebbfbe | |||
| 35e2a70de0 | |||
| 81d5c86a7a | |||
| db6644bae9 | |||
| 14f1c1a358 | |||
| 5be9bc64a2 | |||
| 64d3a5c8b7 | |||
| ccb4d13a82 | |||
| cbe835a2c8 | |||
| 6a77754adf | |||
| 7d7d5ba734 | |||
| 684fa1c4b0 | |||
| a98d851fde | |||
| 9c3e2dab40 | |||
| eddb68f2fa | |||
| 791091174a | |||
| dd9280c6ea | |||
| a4d83f9fdb | |||
| f42c5c4a5b | |||
| 186fa4f1a1 | |||
| 09292bb87e | |||
| d18a0de879 | |||
| cdc45935b5 | |||
| 43e18148a6 | |||
| b0db645248 | |||
| 07712758a7 | |||
| c1a424a635 | |||
| a49588dbc7 | |||
| 1f22b9b982 | |||
| 1d07d8e08e | |||
| 05b2424fca | |||
| 07201c711e | |||
| 8fac88c9a6 | |||
| c9aafa78ec | |||
| e1c337a483 | |||
| acebe68dfa | |||
| eeef945c25 | |||
| a602753bda | |||
| 812ae77cd7 | |||
| 8b8af1a9d9 | |||
| 493b5cb9b1 | |||
| 1ecd7cc2fe | |||
| 5c38832456 | |||
| d16f07a547 | |||
| 54acb05131 | |||
| 9ddf19f605 | |||
| ff378e4538 | |||
| 2ea0a24795 | |||
| acf28d8170 | |||
| 666a7bb826 | |||
| 1ac20251cf | |||
| a318a19fe2 | |||
| f4a7aec167 | |||
| 9445332499 | |||
| 8edd63d115 | |||
| 304ace1172 | |||
| a5cdf0640f | |||
| 1fc2e43881 | |||
| 0964c9f928 | |||
| 8b1e820869 | |||
| 9edc6966db | |||
| 12207dcb77 | |||
| 2255e36810 | |||
| 5abddd448e | |||
| f022a1b08f | |||
| b3bbfaeff0 | |||
| 679a3d4209 | |||
| a0211d88e7 | |||
| e216fc7798 | |||
| c648ea12f2 | |||
| 2e59373a1e | |||
| a51a81b6cd | |||
| 9809f87010 | |||
| 8794122c2d | |||
| 8fb2270ecf | |||
| c304133224 | |||
| 7843d3de62 | |||
| aef536fff3 | |||
| d472e1ac0e | |||
| 120c08fb75 | |||
| ba6229b92d | |||
| 3d2362cb5f | |||
| a08b9b82a6 | |||
| 5d62fa3f10 | |||
| d3df00f0ba | |||
| 34e84f8b07 | |||
| 1143dc3cae | |||
| 0299d4d44e | |||
| 1d07151743 | |||
| a83fa6f4c6 | |||
| c30fc9d60f | |||
| 311a68160c | |||
| 343aef31c3 | |||
| 3ac8f7e14f | |||
| 0cef66d155 | |||
| 9ffbb9fbf0 | |||
| c9a8f5b456 | |||
| 4e3831e380 | |||
| cae2b3bd14 | |||
| 5637b8602b | |||
| 4af9699b22 | |||
| 35c97e2ff8 | |||
| 83e5cb81e8 | |||
| 7a49a0d986 | |||
| 78cd054d59 | |||
| d33a8eac9c | |||
| 9355ab1656 | |||
| 1f87bfbf2e | |||
| e06429da87 | |||
| 26058763df | |||
| 1f03d23dae | |||
| 2eea074473 | |||
| ed82a18e2a | |||
| 2961a49dc7 | |||
| 5c9151d3e9 | |||
| 90deb9fb43 | |||
| 12489a4c6b | |||
| 74f70ae4bd | |||
| a9ceab0415 | |||
| 94bd74d0bb | |||
| b2d8199480 | |||
| e60f3711f8 | |||
| 6ec9e4f7b8 | |||
| 9eb3834ae5 | |||
| ee57cf3e9a | |||
| fea5d1d82b | |||
| c84a30d4dd | |||
| 24d91eee90 | |||
| a5318448f5 | |||
| b7c40eeb57 | |||
| e7c9be1875 | |||
| 8f1b314802 | |||
| da6794c8ce | |||
| e926beba5a | |||
| 3ad053cf6d | |||
| bc11469a0b | |||
| a00695bdac | |||
| 89959b800c | |||
| 3e19c3b62e | |||
| d970debb4d | |||
| d0ba52073f | |||
| 943e3b6f51 | |||
| 25d43682aa | |||
| ad16de59f8 | |||
| 8634bbb792 | |||
| 60ec5d30fd | |||
| 7667fe6ca5 | |||
| 4b5a8196c3 | |||
| 706c0816dd | |||
| a8aa89362d | |||
| 7964698ae5 | |||
| 65664b0d65 | |||
| 08bfa0971e | |||
| 912c5ea0bf | |||
| 6cdf5a5a7f | |||
| 50ba743faf | |||
| e26aac3067 | |||
| 941e8aa5d5 | |||
| 33b6536e6b | |||
| 9fbd9288b2 | |||
| bef1a56007 | |||
| bc71ff5e81 | |||
| bd50444d06 | |||
| 2efd6f92b2 | |||
| 7fdfad4088 | |||
| 31a1968798 | |||
| b0bd4ad546 | |||
| dc454b9a6a | |||
| f06e5d33e7 | |||
| efdbd1576f | |||
| 0421fbdc25 | |||
| bd426199f8 | |||
| 8e00b3d110 | |||
| 6fbf1469aa | |||
| 280d3fd919 | |||
| 40ce95b87f | |||
| e7d644b874 | |||
| c64159d5c3 | |||
| e2ccc3026f | |||
| 2af6066ee3 | |||
| fc16b5331c | |||
| b2723a0c5f | |||
| 01042a24f0 | |||
| f9643b3881 | |||
| d2d18bea5d | |||
| 87e595b83e | |||
| 08031b1227 | |||
| 9a87c1f734 | |||
| edeb667ead | |||
| db2aa495b8 | |||
| ddfb591094 | |||
| e8f1ba3722 | |||
| 19c4f34ccb | |||
| 5d9e9c021a | |||
| 6a924db68c | |||
| 9d0990e5e8 | |||
| 3207f5d61f | |||
| c72b351bba | |||
| 1f9b296ae7 | |||
| e3e2e7b4df | |||
| 4ec8f4a4bf | |||
| 05d59a05df | |||
| 11ccbe6506 | |||
| 673711a246 | |||
| fff5139d80 | |||
| 812e70c626 | |||
| db7ffcf9d5 | |||
| 8f6cb9c057 | |||
| 291f298d19 | |||
| d60f12d3b8 | |||
| b8a2573bb4 | |||
| 7ce8e610f5 | |||
| 839b9c8f07 | |||
| db20801521 | |||
| 160a9278c9 | |||
| ee507de154 | |||
| dc0fa49de2 | |||
| b678541427 | |||
| 6c4cd0d8cb | |||
| c096d3cd42 | |||
| dcdab4df21 | |||
| 9803209ba1 | |||
| f166cb09ec | |||
| 2dd8b76289 | |||
| 2bf7c67767 | |||
| dd636ffcb2 | |||
| a44c45ff9e | |||
| dc2a455395 | |||
| c700d9f714 | |||
| 59cfc339b0 | |||
| e06c07ca89 | |||
| 6facd54a7e | |||
| 6f8d850726 | |||
| f3beee9874 | |||
| 35e063bdaf | |||
| 09175d1799 | |||
| 46f9a9053f | |||
| bb86520094 | |||
| c1e2c660bf | |||
| 89c0ff1a9d | |||
| 7a68ce7e94 | |||
| 9537922acc | |||
| a39aa73e21 | |||
| f1d12c330e | |||
| 82c8eeb4be | |||
| 3a951f4830 | |||
| 998ea25fb9 | |||
| 7b580b8f56 | |||
| 641ccfdd47 | |||
| 4288f70d04 | |||
| 95fda5dfb7 | |||
| 1903c5e0c6 | |||
| 362501a097 | |||
| 72982e3c2b | |||
| 04d24bce70 | |||
| 2f38306c6b | |||
| 4b36e5197d | |||
| b755cf3e42 | |||
| 3acad7c911 | |||
| f3319016c4 | |||
| 4e14f7d483 | |||
| 979059c804 | |||
| bdf4423512 | |||
| c6ef4b5840 | |||
| acd792d8b4 | |||
| fc730679ed | |||
| 00e5749e20 | |||
| 7b4d349574 | |||
| dc0cccfb6c | |||
| fdc1daefb6 | |||
| c9159b81c8 | |||
| 9233049356 | |||
| bd9015e474 | |||
| 3a79540d2d | |||
| 9e500dc387 | |||
| e05a735589 | |||
| 0be18c4a53 | |||
| e258fde25a | |||
| 7367672570 | |||
| b822d42889 | |||
| 10084ff1bb | |||
| c3c69ac727 | |||
| 0cfda6f6a7 | |||
| dc51ce9e92 | |||
| aa0de2b00e | |||
| 5f61581e1d | |||
| f519cb2cc0 | |||
| 37aef630d2 | |||
| d93fcff5db | |||
| 4952a82af5 | |||
| fecda6a034 | |||
| 9f0addbd8b | |||
| 7f8ea6b8e0 | |||
| 9d3ea6fed7 | |||
| 703b3eda56 | |||
| 84006e1e77 | |||
| 73fb085a41 | |||
| c89780178f | |||
| 2ac3976924 | |||
| ac9dbd24e4 | |||
| 3af9830a2e | |||
| da6b8eb2ab | |||
| da39e98adf | |||
| 791a541381 | |||
| 56684e753b | |||
| c7298edf65 | |||
| 30215963b2 | |||
| f15f88ebd6 | |||
| 391fc0c4c2 | |||
| 948ef2c820 | |||
| c1b6b6b76a | |||
| a8bb07052e | |||
| 6976a2dae7 | |||
| 51cd951b4c | |||
| 16a5a234c1 | |||
| f994210927 | |||
| aaa8760d09 | |||
| cea19ecc31 | |||
| 706cfeb443 | |||
| d9c91589f0 | |||
| 9854691265 | |||
| 32afa33a06 | |||
| c6946d0145 | |||
| abbe7b79d6 | |||
| e4abe75043 | |||
| b904503691 | |||
| 2db42dfb2e | |||
| 10bd24e585 | |||
| f926e599fa | |||
| e7b518ba67 | |||
| a4698f0bde | |||
| 9a6eae69ba | |||
| 0ff365c7f0 | |||
| 214e7a5672 | |||
| 24b69a6dea | |||
| 699235147c | |||
| 72ad413a61 | |||
| f11bb082e4 | |||
| 2f3fd6867d | |||
| 350ae90bb6 | |||
| fb61cab70d | |||
| 1d6c08478d | |||
| 0dfe0b7023 | |||
| def236b7cd | |||
| 247743ef9c | |||
| 49122cf729 | |||
| 84f579be81 | |||
| 3d5f23a1b2 | |||
| 8b26b6604d | |||
| f88e55ffa8 | |||
| 34bdcb12e5 | |||
| 95b353dae5 | |||
| 6560f229b1 | |||
| 8c9ab2d68c | |||
| 8496726ab1 | |||
| 32d7f429f8 | |||
| 0f52f49188 | |||
| b334259a07 | |||
| 74af4e9150 | |||
| 8b7790ded2 | |||
| 3e97a82af0 | |||
| 0066b20413 | |||
| 9d6656451a | |||
| 32f980e259 | |||
| ca9361abc1 | |||
| 36cb3d56fe | |||
| 0bece8a54c | |||
| 70bbdbd8f5 | |||
| df8365f0c7 | |||
| 974aae2ebe | |||
| ceca93c8b1 | |||
| b6793cc6f2 | |||
| 809d07546a | |||
| 804cbeb1a7 | |||
| c07188a60e | |||
| 3804d4332b | |||
| 064aaef6c3 | |||
| ce262a5d2d | |||
| d128f4d70b | |||
| 46d1ada708 | |||
| 2819e5f647 | |||
| c2017a5181 | |||
| 58ad839136 | |||
| 8ed5a71c45 | |||
| 57050a83ba | |||
| 6ed0e84421 | |||
| 9b09d2b47a | |||
| 1a6c5deb4b | |||
| 45a73b00de | |||
| 59fff26a5f | |||
| fde4d4662e | |||
| c9355ad94a | |||
| bad3b8b3e2 | |||
| 0b81bb9b10 | |||
| f61c78efd5 | |||
| 6b2307ab22 | |||
| 9ccb381c31 | |||
| 71133236f8 | |||
| e5786fe435 | |||
| ef6ee78fd1 | |||
| 695262624d | |||
| c96c264801 | |||
| af0bca74e4 | |||
| f41e254e35 | |||
| 7e472a9c1d | |||
| ee3f10313a | |||
| 5b587d199e | |||
| 009b073892 | |||
| 92e962430b | |||
| 3aa20a3a32 | |||
| de7c3d3d29 | |||
| 3f89df338e | |||
| c7f89c9b77 | |||
| a107e463e8 | |||
| 7a5cfe1728 | |||
| 7ad3f967db | |||
| d1c814cf9d | |||
| 72f85dce2b | |||
| f5bbcc017c | |||
| 2980173c8e | |||
| a84c348045 | |||
| d845ecc811 | |||
| 064d9009a2 | |||
| b6aa5bdfab | |||
| a3bdf0456e | |||
| e3ecf05866 | |||
| 6240374dd1 | |||
| e17ee831a7 | |||
| aef9bd6357 | |||
| 8857227a35 | |||
| 937250c681 | |||
| 66d3a1d025 | |||
| 647fedfa19 | |||
| c593d3ed75 | |||
| bd885a01e5 | |||
| 628825fdff | |||
| 46dd411273 | |||
| 2e2ee11452 | |||
| ce0df333b3 | |||
| 8bbda78272 | |||
| 945509fc93 | |||
| b586917930 | |||
| 45ad6082bc | |||
| f27823babe | |||
| 95cfac471a | |||
| f7c1084c3e | |||
| cf96bb6cc3 | |||
| f1369c8fd6 | |||
| eb7922ab88 | |||
| dfdfb7cdaf | |||
| 1cc0fb9c01 | |||
| a51b589bc9 | |||
| 5940e912b3 | |||
| 658a001d91 | |||
| 57c9f5a8a8 | |||
| fa7b58057c | |||
| 0e0f5295cf | |||
| 284c9e5f61 | |||
| 927fbda1e8 | |||
| d25a5034db | |||
| f197d39aaf | |||
| 4a95343936 | |||
| 4e705a91af | |||
| 82b351469b | |||
| ea91bdcce7 | |||
| 256c9daefd | |||
| af0a46e79c | |||
| 4519c48284 | |||
| 8ea32c7650 | |||
| 5972d40ced | |||
| f35a6b3922 | |||
| 21009c37b4 | |||
| 11a2d15003 | |||
| d8a695a88d | |||
| f82390424b | |||
| 08ed405a5b | |||
| 8c598a6902 | |||
| 8e9c40caa4 | |||
| 8c29036fbf | |||
| b46337d376 | |||
| 56d701492b | |||
| 07e4e764a0 | |||
| 66fe2f2e50 | |||
| fda0ced72e | |||
| 654e8bb7f6 | |||
| 80ffde5e1e | |||
| 52309e0754 | |||
| 31e411f8f1 | |||
| de45b760b5 | |||
| ff29e9c4d6 | |||
| cc04bd0f06 | |||
| e72e1e4e43 | |||
| 987cc3c237 | |||
| 935f69e011 | |||
| 9f0c2fb6e2 | |||
| 9b18bda9c8 | |||
| 7831c74e8c | |||
| c1978f9133 | |||
| 05affda20c | |||
| e2eb555ca0 | |||
| 418c3c9cfa | |||
| bc66e181a5 | |||
| 6971f76bd3 | |||
| 1e65f02ff7 | |||
| 4efaf65d3f | |||
| aa0249fadb | |||
| 2c65590134 | |||
| a0d1a9ad67 | |||
| 5df6270e32 | |||
| 7af6e1cd34 | |||
| cceb066284 | |||
| 7a054787ca | |||
| d27891c79f | |||
| 5874fd640e | |||
| 11ae220dbe | |||
| 22542a3a71 | |||
| e16fb6a8e9 | |||
| d941e6d70b | |||
| b65068dc7d | |||
| d5301508ec | |||
| 793cca423b | |||
| 3960687f9d | |||
| 3ec7aad432 | |||
| 84f1ad4f26 | |||
| 6b9dbf625d | |||
| 3aea2c007d | |||
| 85d195212a | |||
| 8a663cb94f | |||
| 674e194a91 | |||
| c57f0abb56 | |||
| 163fdcd582 | |||
| 3be17c6117 | |||
| 995dfa1455 | |||
| 544c8dbc13 | |||
| 8da4f80453 | |||
| 6084aae603 | |||
| e1319a06f2 | |||
| 51fd7a607d | |||
| 8aff315c7b | |||
| 8e0d79f301 | |||
| 8a0269d29e | |||
| 892e16dfb1 | |||
| 92e4078287 | |||
| 41e1819072 | |||
| fb7e9719a1 | |||
| c2d09b64ca | |||
| 1b2aa6c2da | |||
| a5b4cee298 | |||
| 17f1ac10e3 | |||
| c67198032f | |||
| 107b092982 | |||
| bac06e45a4 | |||
| 0e8a68831c | |||
| 5912abd541 | |||
| 13d33995cb | |||
| c8c05f62b4 | |||
| 944b045885 | |||
| 19897ffa26 | |||
| 42a10b21c7 | |||
| 5df0e25c1f | |||
| ebf2b16d09 | |||
| f2eaab6e43 | |||
| a847823411 | |||
| fe9a8b542a | |||
| cd101b6844 | |||
| 69229102c4 | |||
| 4bc3630d19 | |||
| ab00686ac9 | |||
| c3004a038f | |||
| 9cf9d8847b | |||
| 0a3c10566b | |||
| c94243e107 | |||
| 505388b9fa | |||
| 7314cf708c | |||
| 3e6a4f2b16 | |||
| c7c3dd7662 | |||
| e4f025edd6 | |||
| 96f3efbf86 | |||
| 2b2130ff42 | |||
| 463ce05da0 | |||
| fa4095ba95 | |||
| db571b4859 | |||
| e8491b34b8 | |||
| 521457eb92 | |||
| f26a445ce6 | |||
| f73bb242f3 | |||
| 9e895e5286 | |||
| 5b0e5512a8 | |||
| 850b3284ac | |||
| 05a727979a | |||
| d68c88c3f9 | |||
| 5f07d53034 | |||
| fe62ce4bae | |||
| fb09aa4d06 | |||
| 4d080b30ab | |||
| 2d314e72fe | |||
| cf07b747fe | |||
| 273e9bbc92 | |||
| 7dcf1797e9 | |||
| 7aa24b6157 | |||
| d73a667437 | |||
| 4695fa061d | |||
| 7bf7bfbe13 | |||
| 397219c22e | |||
| 83c0ef3514 | |||
| 4fa40de557 | |||
| bc06926702 | |||
| 9de27110e2 | |||
| 93e5d09a63 | |||
| 0cbc39698c | |||
| 83069e433f | |||
| bbb490b24f | |||
| 85f200bd86 | |||
| 0f2c02fb04 | |||
| 6d3d41abe2 | |||
| 6fa7fe26dc | |||
| fe804c123d | |||
| dba32fb95d | |||
| 7dc187fdb1 | |||
| ee5a627952 | |||
| 3b83561309 | |||
| 6fb0b5203a | |||
| 4677d7a1c6 | |||
| 3283359ac8 | |||
| fff16f6b8c | |||
| a347ceba74 | |||
| 05836fab4c | |||
| 15e84f28ed | |||
| 32c35a822b | |||
| 9c86e5e54d | |||
| 87f348b48e | |||
| ff289b25b6 | |||
| a9f58e96d2 | |||
| c61ded8a1e | |||
| 7651ca747d | |||
| 7ff7a4aa87 | |||
| cdcd226b1a | |||
| f9451915b9 | |||
| 5e4e174d61 | |||
| 4a00cb7d55 | |||
| b97c123764 | |||
| 69bdff6b7e | |||
| 8574fcf6e1 | |||
| f4f424bf04 | |||
| ac745bfa3d | |||
| aa691f236e | |||
| a0a9d49d81 | |||
| 125f8b591d | |||
| c97b60e7e5 | |||
| 8a73414e3e | |||
| ac22e006a4 | |||
| 30d5d85d1d | |||
| 6f74f3c386 | |||
| 515918329c | |||
| 8ea0a67280 | |||
| 5ad7d7edb1 | |||
| 00c6820825 | |||
| 6beaafcf11 | |||
| e92f039a17 | |||
| ef76ffa1c1 | |||
| 652eb2346c | |||
| 66726090ec | |||
| b668173cba | |||
| a7e20d6e85 | |||
| c6ded82406 | |||
| a76c6faffc | |||
| 81ff71a97f | |||
| 56db0efe58 | |||
| 5eefd98e1b | |||
| eecdad50a6 | |||
| 96d5ed9cc7 | |||
| 73090ecb37 | |||
| 8812704601 | |||
| 0f189d410e | |||
| cfeabc4580 | |||
| 49f203d61d | |||
| a912a4dc67 | |||
| f79db874bf | |||
| 8de19aff3c | |||
| bf41b448d6 | |||
| 448632cf11 | |||
| 11174bfa14 | |||
| 84b1f3990c | |||
| 943069b2a3 | |||
| e305698e6b | |||
| 4c0b7d44b4 | |||
| 775c77c0fa | |||
| fb466b5af7 | |||
| e473118ec8 | |||
| 755d41ca4e | |||
| bbff9f89b0 | |||
| fdcb38ac1f | |||
| fac742c038 | |||
| 5a6b43fc90 | |||
| 317f413746 | |||
| 895909b7fa | |||
| 2ee8b6c8b4 | |||
| 022bb69782 | |||
| be6da3e0db | |||
| 1f07e02298 | |||
| 7a645b8555 | |||
| c5b0d0235f | |||
| b7948551ff | |||
| e109b5cff6 | |||
| 9883fb7bf6 | |||
| e9f8471a28 | |||
| 4656b11256 | |||
| f2ccab2df7 | |||
| b2e3aefa72 | |||
| 2b48933f29 | |||
| 4ac6cbe70e | |||
| cc07c3df94 | |||
| 31bcad2535 | |||
| b75970958e | |||
| 91756c057e | |||
| df7f245cf8 | |||
| dbdefa0f4a | |||
| 56fdf6002c | |||
| c957f1ddca | |||
| 423386a052 | |||
| 1c882ea361 | |||
| b1065fa01d | |||
| 8ff9c030bf | |||
| 9b875fb930 | |||
| 857bac4b78 | |||
| 30074c290d | |||
| 60d1c26114 | |||
| 692ba43182 | |||
| 6542a037df | |||
| 9f4b451501 | |||
| 1bd454b8fd | |||
| 8392472bac | |||
| cd5b351ce4 | |||
| 50024fbf8b | |||
| 4d4fb3b6ec | |||
| 37dea8aee7 | |||
| 69c4940b27 | |||
| 7691b019e2 | |||
| f55d6b11c5 | |||
| f52877abb4 | |||
| ee7c9b6731 | |||
| 4721344518 | |||
| e0d986dcd7 | |||
| c7be3dcd5b | |||
| 89c9bfd052 | |||
| 12b93567f7 | |||
| 2f37776614 | |||
| f778bca3f2 | |||
| a945d19750 | |||
| 7f04b2c96c | |||
| 8aa4e4ff1e | |||
| 7eade002a7 | |||
| a8f8d27f4e | |||
| 356935bd4f | |||
| bce3dd045f | |||
| 79a2b84c81 | |||
| 44b762f916 | |||
| 5d80c880c8 | |||
| b907263f35 | |||
| 0f0accf82c | |||
| ddcf414107 | |||
| 6be3b1d7f2 | |||
| 0e0d7016b3 | |||
| 553c76ab0f | |||
| b90cfa8e5c | |||
| e7f0cd0c4b | |||
| 0661b339a0 | |||
| d1bb72f6fb | |||
| 1bcd1edbf5 | |||
| 143a00626b | |||
| 0eb981f51c | |||
| 6cc01349f7 | |||
| a7bd4acd46 | |||
| 8e0a56b49a | |||
| a8844ddd28 | |||
| c18fefd5f3 | |||
| 3040940e35 | |||
| df3d2d57c3 | |||
| 92d26f2216 | |||
| 0380c68f89 | |||
| 2a6dc6a7b7 | |||
| 40617f0d5c | |||
| 09745a7835 | |||
| 57f6f50939 | |||
| f959905adf | |||
| f78c7e7926 | |||
| 96496da0ab | |||
| 2dc4733ac1 | |||
| f14774d034 | |||
| c08c63f420 | |||
| eb79c6c47c | |||
| bf1cbb4cde | |||
| 592675022e | |||
| b2e10d7e6e | |||
| 0689954433 | |||
| 5c37f198cb | |||
| 3b02a9d4fe | |||
| c9057aa498 | |||
| 2b0d198b05 | |||
| 7798145c74 | |||
| fcfadd7c74 | |||
| c0181820a9 | |||
| 76d4e6bd18 | |||
| ccb81de85d | |||
| 82f4975f45 | |||
| d457e6ad6a | |||
| abf7c8e68a | |||
| 1a38d0c31e | |||
| 9ff9d679e9 | |||
| 9f3f8f950a | |||
| 006a196e4a | |||
| 418678466c | |||
| 9f4cb5c4dd | |||
| 73f9de6635 | |||
| 12b9c82086 | |||
| a8edb8870e | |||
| dabc3c6cc4 | |||
| cc7c1ad30d | |||
| 4d840a8d9a | |||
| 95a80bfe81 | |||
| 53e9eab0cd | |||
| 35b3c3c98c | |||
| 20e17a28cf | |||
| 28bf2d6374 | |||
| 8a00b53050 | |||
| 8834241417 | |||
| 96740d6be4 | |||
| b853d29992 | |||
| 33a0f562d3 | |||
| f8e3ae0525 | |||
| c790bad667 | |||
| d54489bbcb | |||
| 808c97020a | |||
| 34e680d792 | |||
| 32d543943b | |||
| 2632507980 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@
|
||||
build/
|
||||
base/
|
||||
script/fakeroot-context
|
||||
tools/update-image-perms
|
||||
|
||||
@@ -18,78 +18,78 @@ namespace BAN
|
||||
using const_iterator = ConstIteratorSimple<T, Array>;
|
||||
|
||||
public:
|
||||
Array() = default;
|
||||
Array(const T&);
|
||||
constexpr Array() = default;
|
||||
constexpr Array(const T&);
|
||||
|
||||
iterator begin() { return iterator(m_data); }
|
||||
iterator end() { return iterator(m_data + size()); }
|
||||
const_iterator begin() const { return const_iterator(m_data); }
|
||||
const_iterator end() const { return const_iterator(m_data + size()); }
|
||||
|
||||
const T& operator[](size_type) const;
|
||||
T& operator[](size_type);
|
||||
constexpr const T& operator[](size_type) const;
|
||||
constexpr T& operator[](size_type);
|
||||
|
||||
const T& back() const;
|
||||
T& back();
|
||||
const T& front() const;
|
||||
T& front();
|
||||
constexpr const T& back() const;
|
||||
constexpr T& back();
|
||||
constexpr const T& front() const;
|
||||
constexpr T& front();
|
||||
|
||||
Span<T> span() { return Span(m_data, size()); }
|
||||
const Span<T> span() const { return Span(m_data, size()); }
|
||||
Span<const T> span() const { return Span(m_data, size()); }
|
||||
|
||||
constexpr size_type size() const;
|
||||
|
||||
const T* data() const { return m_data; }
|
||||
T* data() { return m_data; }
|
||||
constexpr const T* data() const { return m_data; }
|
||||
constexpr T* data() { return m_data; }
|
||||
|
||||
private:
|
||||
T m_data[S] {};
|
||||
};
|
||||
|
||||
template<typename T, size_t S>
|
||||
Array<T, S>::Array(const T& value)
|
||||
constexpr Array<T, S>::Array(const T& value)
|
||||
{
|
||||
for (size_type i = 0; i < S; i++)
|
||||
m_data[i] = value;
|
||||
}
|
||||
|
||||
template<typename T, size_t S>
|
||||
const T& Array<T, S>::operator[](size_type index) const
|
||||
constexpr const T& Array<T, S>::operator[](size_type index) const
|
||||
{
|
||||
ASSERT(index < S);
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
template<typename T, size_t S>
|
||||
T& Array<T, S>::operator[](size_type index)
|
||||
constexpr T& Array<T, S>::operator[](size_type index)
|
||||
{
|
||||
ASSERT(index < S);
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
template<typename T, size_t S>
|
||||
const T& Array<T, S>::back() const
|
||||
constexpr const T& Array<T, S>::back() const
|
||||
{
|
||||
ASSERT(S != 0);
|
||||
return m_data[S - 1];
|
||||
}
|
||||
|
||||
template<typename T, size_t S>
|
||||
T& Array<T, S>::back()
|
||||
constexpr T& Array<T, S>::back()
|
||||
{
|
||||
ASSERT(S != 0);
|
||||
return m_data[S - 1];
|
||||
}
|
||||
|
||||
template<typename T, size_t S>
|
||||
const T& Array<T, S>::front() const
|
||||
constexpr const T& Array<T, S>::front() const
|
||||
{
|
||||
ASSERT(S != 0);
|
||||
return m_data[0];
|
||||
}
|
||||
|
||||
template<typename T, size_t S>
|
||||
T& Array<T, S>::front()
|
||||
constexpr T& Array<T, S>::front()
|
||||
{
|
||||
ASSERT(S != 0);
|
||||
return m_data[0];
|
||||
|
||||
@@ -34,6 +34,11 @@ namespace BAN
|
||||
const T& back() const;
|
||||
T& back();
|
||||
|
||||
const T& operator[](size_t index) const;
|
||||
T& operator[](size_t index);
|
||||
|
||||
void clear();
|
||||
|
||||
size_type size() const { return m_size; }
|
||||
bool empty() const { return size() == 0; }
|
||||
bool full() const { return size() == capacity(); }
|
||||
@@ -53,8 +58,7 @@ namespace BAN
|
||||
template<typename T, size_t S>
|
||||
CircularQueue<T, S>::~CircularQueue()
|
||||
{
|
||||
for (size_type i = 0; i < m_size; i++)
|
||||
element_at((m_first + i) % capacity())->~T();
|
||||
clear();
|
||||
}
|
||||
|
||||
template<typename T, size_t S>
|
||||
@@ -115,6 +119,28 @@ namespace BAN
|
||||
return *element_at((m_first + m_size - 1) % capacity());
|
||||
}
|
||||
|
||||
template<typename T, size_t S>
|
||||
const T& CircularQueue<T, S>::operator[](size_t index) const
|
||||
{
|
||||
ASSERT(index < m_size);
|
||||
return *element_at((m_first + index) % capacity());
|
||||
}
|
||||
|
||||
template<typename T, size_t S>
|
||||
T& CircularQueue<T, S>::operator[](size_t index)
|
||||
{
|
||||
ASSERT(index < m_size);
|
||||
return *element_at((m_first + index) % capacity());
|
||||
}
|
||||
|
||||
template<typename T, size_t S>
|
||||
void CircularQueue<T, S>::clear()
|
||||
{
|
||||
for (size_type i = 0; i < m_size; i++)
|
||||
element_at((m_first + i) % capacity())->~T();
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
template<typename T, size_t S>
|
||||
const T* CircularQueue<T, S>::element_at(size_type index) const
|
||||
{
|
||||
|
||||
@@ -9,29 +9,35 @@
|
||||
#include <BAN/Formatter.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define __debug_putchar [](int c) { putc(c, stddbg); }
|
||||
#define __debug_putchar [](int c) { putc_unlocked(c, stddbg); }
|
||||
|
||||
#define dprintln(...) \
|
||||
do { \
|
||||
flockfile(stddbg); \
|
||||
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
|
||||
BAN::Formatter::print(__debug_putchar,"\r\n"); \
|
||||
BAN::Formatter::print(__debug_putchar,"\n"); \
|
||||
fflush(stddbg); \
|
||||
funlockfile(stddbg); \
|
||||
} while (false)
|
||||
|
||||
#define dwarnln(...) \
|
||||
do { \
|
||||
flockfile(stddbg); \
|
||||
BAN::Formatter::print(__debug_putchar, "\e[33m"); \
|
||||
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
|
||||
BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \
|
||||
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
|
||||
fflush(stddbg); \
|
||||
funlockfile(stddbg); \
|
||||
} while(false)
|
||||
|
||||
#define derrorln(...) \
|
||||
do { \
|
||||
flockfile(stddbg); \
|
||||
BAN::Formatter::print(__debug_putchar, "\e[31m"); \
|
||||
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
|
||||
BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \
|
||||
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
|
||||
fflush(stddbg); \
|
||||
funlockfile(stddbg); \
|
||||
} while(false)
|
||||
|
||||
#define dprintln_if(cond, ...) \
|
||||
|
||||
89
BAN/include/BAN/Heap.h
Normal file
89
BAN/include/BAN/Heap.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Iterators.h>
|
||||
#include <BAN/Swap.h>
|
||||
#include <BAN/Traits.h>
|
||||
|
||||
namespace BAN
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename It, typename Comp>
|
||||
void heapify_up(It begin, size_t index, Comp comp)
|
||||
{
|
||||
size_t parent = (index - 1) / 2;
|
||||
while (parent < index)
|
||||
{
|
||||
if (comp(*(begin + index), *(begin + parent)))
|
||||
break;
|
||||
swap(*(begin + parent), *(begin + index));
|
||||
index = parent;
|
||||
parent = (index - 1) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename It, typename Comp>
|
||||
void heapify_down(It begin, size_t index, size_t len, Comp comp)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
const size_t lchild = 2 * index + 1;
|
||||
const size_t rchild = 2 * index + 2;
|
||||
|
||||
size_t child = 0;
|
||||
if (lchild < len && !comp(*(begin + lchild), *(begin + index)))
|
||||
{
|
||||
if (rchild < len && !comp(*(begin + rchild), *(begin + lchild)))
|
||||
child = rchild;
|
||||
else
|
||||
child = lchild;
|
||||
}
|
||||
else if (rchild < len && !comp(*(begin + rchild), *(begin + index)))
|
||||
child = rchild;
|
||||
else
|
||||
break;
|
||||
|
||||
swap(*(begin + child), *(begin + index));
|
||||
index = child;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void make_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
if (len <= 1)
|
||||
return;
|
||||
|
||||
size_t index = (len - 2) / 2;
|
||||
while (index < len)
|
||||
detail::heapify_down(begin, index--, len, comp);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void push_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
detail::heapify_up(begin, len - 1, comp);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void pop_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
swap(*begin, *(begin + len - 1));
|
||||
detail::heapify_down(begin, 0, len - 1, comp);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void sort_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
while (begin != end)
|
||||
pop_heap(begin, end--, comp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,10 @@ namespace BAN
|
||||
|
||||
struct IPv4Address
|
||||
{
|
||||
constexpr IPv4Address()
|
||||
: IPv4Address(0)
|
||||
{ }
|
||||
|
||||
constexpr IPv4Address(uint32_t u32_address)
|
||||
{
|
||||
raw = u32_address;
|
||||
|
||||
@@ -36,12 +36,11 @@ namespace BAN::Math
|
||||
template<integral T>
|
||||
inline constexpr T gcd(T a, T b)
|
||||
{
|
||||
T t;
|
||||
while (b)
|
||||
{
|
||||
t = b;
|
||||
T temp = b;
|
||||
b = a % b;
|
||||
a = t;
|
||||
a = temp;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
@@ -66,25 +65,20 @@ namespace BAN::Math
|
||||
return (x & (x - 1)) == 0;
|
||||
}
|
||||
|
||||
template<BAN::integral T>
|
||||
static constexpr bool will_multiplication_overflow(T a, T b)
|
||||
template<integral T>
|
||||
__attribute__((always_inline))
|
||||
inline constexpr bool will_multiplication_overflow(T a, T b)
|
||||
{
|
||||
if (a == 0 || b == 0)
|
||||
return false;
|
||||
if ((a > 0) == (b > 0))
|
||||
return a > BAN::numeric_limits<T>::max() / b;
|
||||
else
|
||||
return a < BAN::numeric_limits<T>::min() / b;
|
||||
T dummy;
|
||||
return __builtin_mul_overflow(a, b, &dummy);
|
||||
}
|
||||
|
||||
template<BAN::integral T>
|
||||
static constexpr bool will_addition_overflow(T a, T b)
|
||||
template<integral T>
|
||||
__attribute__((always_inline))
|
||||
inline constexpr bool will_addition_overflow(T a, T b)
|
||||
{
|
||||
if (a > 0 && b > 0)
|
||||
return a > BAN::numeric_limits<T>::max() - b;
|
||||
if (a < 0 && b < 0)
|
||||
return a < BAN::numeric_limits<T>::min() - b;
|
||||
return false;
|
||||
T dummy;
|
||||
return __builtin_add_overflow(a, b, &dummy);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -98,6 +92,19 @@ namespace BAN::Math
|
||||
return sizeof(T) * 8 - __builtin_clzll(x) - 1;
|
||||
}
|
||||
|
||||
// This is ugly but my clangd does not like including
|
||||
// intrinsic headers at all
|
||||
#if !defined(__SSE__) || !defined(__SSE2__)
|
||||
#pragma GCC push_options
|
||||
#ifndef __SSE__
|
||||
#pragma GCC target("sse")
|
||||
#endif
|
||||
#ifndef __SSE2__
|
||||
#pragma GCC target("sse2")
|
||||
#endif
|
||||
#define BAN_MATH_POP_OPTIONS
|
||||
#endif
|
||||
|
||||
template<floating_point T>
|
||||
inline constexpr T floor(T x)
|
||||
{
|
||||
@@ -159,7 +166,23 @@ namespace BAN::Math
|
||||
"jne 1b;"
|
||||
: "+t"(a)
|
||||
: "u"(b)
|
||||
: "ax"
|
||||
: "ax", "cc"
|
||||
);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<floating_point T>
|
||||
inline constexpr T remainder(T a, T b)
|
||||
{
|
||||
asm(
|
||||
"1:"
|
||||
"fprem1;"
|
||||
"fnstsw %%ax;"
|
||||
"testb $4, %%ah;"
|
||||
"jne 1b;"
|
||||
: "+t"(a)
|
||||
: "u"(b)
|
||||
: "ax", "cc"
|
||||
);
|
||||
return a;
|
||||
}
|
||||
@@ -167,7 +190,7 @@ namespace BAN::Math
|
||||
template<floating_point T>
|
||||
static T modf(T x, T* iptr)
|
||||
{
|
||||
const T frac = BAN::Math::fmod<T>(x, 1);
|
||||
const T frac = BAN::Math::fmod<T>(x, (T)1.0);
|
||||
*iptr = x - frac;
|
||||
return frac;
|
||||
}
|
||||
@@ -175,15 +198,15 @@ namespace BAN::Math
|
||||
template<floating_point T>
|
||||
inline constexpr T frexp(T num, int* exp)
|
||||
{
|
||||
if (num == 0.0)
|
||||
if (num == (T)0.0)
|
||||
{
|
||||
*exp = 0;
|
||||
return 0.0;
|
||||
return (T)0.0;
|
||||
}
|
||||
|
||||
T _exp;
|
||||
asm("fxtract" : "+t"(num), "=u"(_exp));
|
||||
*exp = (int)_exp + 1;
|
||||
T e;
|
||||
asm("fxtract" : "+t"(num), "=u"(e));
|
||||
*exp = (int)e + 1;
|
||||
return num / (T)2.0;
|
||||
}
|
||||
|
||||
@@ -251,6 +274,7 @@ namespace BAN::Math
|
||||
"fstp %%st(1);"
|
||||
: "+t"(x)
|
||||
);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -263,18 +287,9 @@ namespace BAN::Math
|
||||
template<floating_point T>
|
||||
inline constexpr T pow(T x, T y)
|
||||
{
|
||||
asm(
|
||||
"fyl2x;"
|
||||
"fld1;"
|
||||
"fld %%st(1);"
|
||||
"fprem;"
|
||||
"f2xm1;"
|
||||
"faddp;"
|
||||
"fscale;"
|
||||
: "+t"(x), "+u"(y)
|
||||
);
|
||||
|
||||
return x;
|
||||
if (x == (T)0.0)
|
||||
return (T)0.0;
|
||||
return exp2<T>(y * log2<T>(x));
|
||||
}
|
||||
|
||||
template<floating_point T>
|
||||
@@ -310,16 +325,27 @@ namespace BAN::Math
|
||||
template<floating_point T>
|
||||
inline constexpr T sqrt(T x)
|
||||
{
|
||||
asm("fsqrt" : "+t"(x));
|
||||
return x;
|
||||
if constexpr(BAN::is_same_v<T, float>)
|
||||
{
|
||||
using v4sf = float __attribute__((vector_size(16)));
|
||||
return __builtin_ia32_sqrtss((v4sf) { x, 0.0f, 0.0f, 0.0f })[0];
|
||||
}
|
||||
else if constexpr(BAN::is_same_v<T, double>)
|
||||
{
|
||||
using v2df = double __attribute__((vector_size(16)));
|
||||
return __builtin_ia32_sqrtsd((v2df) { x, 0.0 })[0];
|
||||
}
|
||||
else if constexpr(BAN::is_same_v<T, long double>)
|
||||
{
|
||||
asm("fsqrt" : "+t"(x));
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
template<floating_point T>
|
||||
inline constexpr T cbrt(T value)
|
||||
{
|
||||
if (value == 0.0)
|
||||
return 0.0;
|
||||
return pow<T>(value, 1.0 / 3.0);
|
||||
return pow<T>(value, (T)1.0 / (T)3.0);
|
||||
}
|
||||
|
||||
template<floating_point T>
|
||||
@@ -346,30 +372,21 @@ namespace BAN::Math
|
||||
inline constexpr T tan(T x)
|
||||
{
|
||||
T one, ret;
|
||||
asm(
|
||||
"fptan"
|
||||
: "=t"(one), "=u"(ret)
|
||||
: "0"(x)
|
||||
);
|
||||
asm("fptan" : "=t"(one), "=u"(ret) : "0"(x));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<floating_point T>
|
||||
inline constexpr T atan2(T y, T x)
|
||||
{
|
||||
asm(
|
||||
"fpatan"
|
||||
: "+t"(x)
|
||||
: "u"(y)
|
||||
: "st(1)"
|
||||
);
|
||||
asm("fpatan" : "+t"(x) : "u"(y) : "st(1)");
|
||||
return x;
|
||||
}
|
||||
|
||||
template<floating_point T>
|
||||
inline constexpr T atan(T x)
|
||||
{
|
||||
return atan2<T>(x, 1.0);
|
||||
return atan2<T>(x, (T)1.0);
|
||||
}
|
||||
|
||||
template<floating_point T>
|
||||
@@ -378,10 +395,10 @@ namespace BAN::Math
|
||||
if (x == (T)0.0)
|
||||
return (T)0.0;
|
||||
if (x == (T)1.0)
|
||||
return numbers::pi_v<T> / (T)2.0;
|
||||
return +numbers::pi_v<T> / (T)2.0;
|
||||
if (x == (T)-1.0)
|
||||
return -numbers::pi_v<T> / (T)2.0;
|
||||
return (T)2.0 * atan<T>(x / (T(1.0) + sqrt<T>((T)1.0 - x * x)));
|
||||
return (T)2.0 * atan<T>(x / ((T)1.0 + sqrt<T>((T)1.0 - x * x)));
|
||||
}
|
||||
|
||||
template<floating_point T>
|
||||
@@ -411,7 +428,7 @@ namespace BAN::Math
|
||||
template<floating_point T>
|
||||
inline constexpr T tanh(T x)
|
||||
{
|
||||
const T exp_px = exp<T>(x);
|
||||
const T exp_px = exp<T>(+x);
|
||||
const T exp_nx = exp<T>(-x);
|
||||
return (exp_px - exp_nx) / (exp_px + exp_nx);
|
||||
}
|
||||
@@ -440,4 +457,9 @@ namespace BAN::Math
|
||||
return sqrt<T>(x * x + y * y);
|
||||
}
|
||||
|
||||
#ifdef BAN_MATH_POP_OPTIONS
|
||||
#undef BAN_MATH_POP_OPTIONS
|
||||
#pragma GCC pop_options
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
namespace BAN
|
||||
{
|
||||
#if defined(__is_kernel)
|
||||
static constexpr void*(&allocator)(size_t) = kmalloc;
|
||||
static constexpr void(&deallocator)(void*) = kfree;
|
||||
static constexpr void*(*allocator)(size_t) = kmalloc;
|
||||
static constexpr void*(*reallocator)(void*, size_t) = nullptr;
|
||||
static constexpr void(*deallocator)(void*) = kfree;
|
||||
#else
|
||||
static constexpr void*(&allocator)(size_t) = malloc;
|
||||
static constexpr void(&deallocator)(void*) = free;
|
||||
static constexpr void*(*allocator)(size_t) = malloc;
|
||||
static constexpr void*(*reallocator)(void*, size_t) = realloc;
|
||||
static constexpr void(*deallocator)(void*) = free;
|
||||
#endif
|
||||
}
|
||||
|
||||
64
BAN/include/BAN/PriorityQueue.h
Normal file
64
BAN/include/BAN/PriorityQueue.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include "BAN/Errors.h"
|
||||
#include <BAN/Vector.h>
|
||||
#include <BAN/Heap.h>
|
||||
|
||||
namespace BAN
|
||||
{
|
||||
|
||||
template<typename T, typename Comp = less<T>>
|
||||
class PriorityQueue
|
||||
{
|
||||
public:
|
||||
PriorityQueue() = default;
|
||||
PriorityQueue(Comp comp)
|
||||
: m_comp(comp)
|
||||
{ }
|
||||
|
||||
ErrorOr<void> push(const T& value)
|
||||
{
|
||||
TRY(m_data.push_back(value));
|
||||
push_heap(m_data.begin(), m_data.end());
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> push(T&& value)
|
||||
{
|
||||
TRY(m_data.push_back(move(value)));
|
||||
push_heap(m_data.begin(), m_data.end());
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
ErrorOr<void> emplace(Args&&... args) requires is_constructible_v<T, Args...>
|
||||
{
|
||||
TRY(m_data.emplace_back(forward<Args>(args)...));
|
||||
push_heap(m_data.begin(), m_data.end());
|
||||
return {};
|
||||
}
|
||||
|
||||
void pop()
|
||||
{
|
||||
pop_heap(m_data.begin(), m_data.end());
|
||||
m_data.pop_back();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> reserve(Vector<T>::size_type size)
|
||||
{
|
||||
return m_data.reserve(size);
|
||||
}
|
||||
|
||||
T& top() { return m_data.front(); }
|
||||
const T& top() const { return m_data.front(); }
|
||||
|
||||
bool empty() const { return m_data.empty(); }
|
||||
Vector<T>::size_type size() const { return m_data.size(); }
|
||||
Vector<T>::size_type capacity() const { return m_data.capacity(); }
|
||||
|
||||
private:
|
||||
Comp m_comp;
|
||||
Vector<T> m_data;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Heap.h>
|
||||
#include <BAN/Math.h>
|
||||
#include <BAN/Swap.h>
|
||||
#include <BAN/Traits.h>
|
||||
@@ -8,7 +9,7 @@
|
||||
namespace BAN::sort
|
||||
{
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void exchange_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
for (It lhs = begin; lhs != end; ++lhs)
|
||||
@@ -42,7 +43,7 @@ namespace BAN::sort
|
||||
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void quick_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
if (distance(begin, end) <= 1)
|
||||
@@ -52,14 +53,14 @@ namespace BAN::sort
|
||||
quick_sort(++mid, end, comp);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void insertion_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
if (distance(begin, end) <= 1)
|
||||
return;
|
||||
for (It it1 = next(begin, 1); it1 != end; ++it1)
|
||||
{
|
||||
typename It::value_type x = move(*it1);
|
||||
auto x = move(*it1);
|
||||
It it2 = it1;
|
||||
for (; it2 != begin && comp(x, *prev(it2, 1)); --it2)
|
||||
*it2 = move(*prev(it2, 1));
|
||||
@@ -67,83 +68,7 @@ namespace BAN::sort
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename It, typename Comp>
|
||||
void push_heap(It begin, size_t hole_index, size_t top_index, typename It::value_type value, Comp comp)
|
||||
{
|
||||
size_t parent = (hole_index - 1) / 2;
|
||||
while (hole_index > top_index && comp(*next(begin, parent), value))
|
||||
{
|
||||
*next(begin, hole_index) = move(*next(begin, parent));
|
||||
hole_index = parent;
|
||||
parent = (hole_index - 1) / 2;
|
||||
}
|
||||
*next(begin, hole_index) = move(value);
|
||||
}
|
||||
|
||||
template<typename It, typename Comp>
|
||||
void adjust_heap(It begin, size_t hole_index, size_t len, typename It::value_type value, Comp comp)
|
||||
{
|
||||
const size_t top_index = hole_index;
|
||||
size_t child = hole_index;
|
||||
while (child < (len - 1) / 2)
|
||||
{
|
||||
child = 2 * (child + 1);
|
||||
if (comp(*next(begin, child), *next(begin, child - 1)))
|
||||
child--;
|
||||
*next(begin, hole_index) = move(*next(begin, child));
|
||||
hole_index = child;
|
||||
}
|
||||
if (len % 2 == 0 && child == (len - 2) / 2)
|
||||
{
|
||||
child = 2 * (child + 1);
|
||||
*next(begin, hole_index) = move(*next(begin, child - 1));
|
||||
hole_index = child - 1;
|
||||
}
|
||||
push_heap(begin, hole_index, top_index, move(value), comp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
void make_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
if (len <= 1)
|
||||
return;
|
||||
|
||||
size_t parent = (len - 2) / 2;
|
||||
while (true)
|
||||
{
|
||||
detail::adjust_heap(begin, parent, len, move(*next(begin, parent)), comp);
|
||||
|
||||
if (parent == 0)
|
||||
break;
|
||||
|
||||
parent--;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
void sort_heap(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
if (len <= 1)
|
||||
return;
|
||||
|
||||
size_t last = len;
|
||||
while (last > 1)
|
||||
{
|
||||
last--;
|
||||
typename It::value_type x = move(*next(begin, last));
|
||||
*next(begin, last) = move(*begin);
|
||||
detail::adjust_heap(begin, 0, last, move(x), comp);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void heap_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
make_heap(begin, end, comp);
|
||||
@@ -167,7 +92,7 @@ namespace BAN::sort
|
||||
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void intro_sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
const size_t len = distance(begin, end);
|
||||
@@ -190,10 +115,10 @@ namespace BAN::sort
|
||||
}
|
||||
|
||||
template<typename It, size_t radix = 256>
|
||||
requires is_unsigned_v<typename It::value_type> && (radix > 0 && (radix & (radix - 1)) == 0)
|
||||
requires is_unsigned_v<it_value_type_t<It>> && (radix > 0 && (radix & (radix - 1)) == 0)
|
||||
BAN::ErrorOr<void> radix_sort(It begin, It end)
|
||||
{
|
||||
using value_type = typename It::value_type;
|
||||
using value_type = it_value_type_t<It>;
|
||||
|
||||
const size_t len = distance(begin, end);
|
||||
if (len <= 1)
|
||||
@@ -231,7 +156,7 @@ namespace BAN::sort
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename It, typename Comp = less<typename It::value_type>>
|
||||
template<typename It, typename Comp = less<it_value_type_t<It>>>
|
||||
void sort(It begin, It end, Comp comp = {})
|
||||
{
|
||||
return intro_sort(begin, end, comp);
|
||||
|
||||
@@ -69,7 +69,6 @@ namespace BAN
|
||||
|
||||
value_type* data() const
|
||||
{
|
||||
ASSERT(m_data);
|
||||
return m_data;
|
||||
}
|
||||
|
||||
@@ -84,7 +83,6 @@ namespace BAN
|
||||
|
||||
Span slice(size_type start, size_type length = ~size_type(0)) const
|
||||
{
|
||||
ASSERT(m_data);
|
||||
ASSERT(start <= m_size);
|
||||
if (length == ~size_type(0))
|
||||
length = m_size - start;
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace BAN
|
||||
{
|
||||
public:
|
||||
using size_type = size_t;
|
||||
using value_type = char;
|
||||
using iterator = IteratorSimple<char, String>;
|
||||
using const_iterator = ConstIteratorSimple<char, String>;
|
||||
static constexpr size_type sso_capacity = 15;
|
||||
@@ -352,10 +353,9 @@ namespace BAN::Formatter
|
||||
{
|
||||
|
||||
template<typename F>
|
||||
void print_argument(F putc, const String& string, const ValueFormat&)
|
||||
void print_argument(F putc, const String& string, const ValueFormat& format)
|
||||
{
|
||||
for (String::size_type i = 0; i < string.size(); i++)
|
||||
putc(string[i]);
|
||||
print_argument(putc, string.sv(), format);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace BAN
|
||||
{
|
||||
public:
|
||||
using size_type = size_t;
|
||||
using value_type = char;
|
||||
using const_iterator = ConstIteratorSimple<char, StringView>;
|
||||
|
||||
public:
|
||||
@@ -21,7 +22,8 @@ namespace BAN
|
||||
constexpr StringView(const char* string, size_type len = -1)
|
||||
{
|
||||
if (len == size_type(-1))
|
||||
len = strlen(string);
|
||||
for (len = 0; string[len];)
|
||||
len++;
|
||||
m_data = string;
|
||||
m_size = len;
|
||||
}
|
||||
@@ -245,10 +247,12 @@ namespace BAN::Formatter
|
||||
{
|
||||
|
||||
template<typename F>
|
||||
void print_argument(F putc, const StringView& sv, const ValueFormat&)
|
||||
void print_argument(F putc, const StringView& sv, const ValueFormat& format)
|
||||
{
|
||||
for (StringView::size_type i = 0; i < sv.size(); i++)
|
||||
putc(sv[i]);
|
||||
for (int i = sv.size(); i < format.fill; i++)
|
||||
putc(' ');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,6 +61,9 @@ namespace BAN
|
||||
template<typename T> struct is_move_constructible { static constexpr bool value = is_constructible_v<T, T&&>; };
|
||||
template<typename T> inline constexpr bool is_move_constructible_v = is_move_constructible<T>::value;
|
||||
|
||||
template<typename T> struct is_trivially_copyable { static constexpr bool value = __is_trivially_copyable(T); };
|
||||
template<typename T> inline constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value;
|
||||
|
||||
template<typename T> struct is_integral { static constexpr bool value = requires (T t, T* p, void (*f)(T)) { reinterpret_cast<T>(t); f(0); p + t; }; };
|
||||
template<typename T> inline constexpr bool is_integral_v = is_integral<T>::value;
|
||||
template<typename T> concept integral = is_integral_v<T>;
|
||||
@@ -139,6 +142,10 @@ namespace BAN
|
||||
template<typename T> using make_signed_t = typename make_signed<T>::type;
|
||||
#undef __BAN_TRAITS_MAKE_SIGNED_CV
|
||||
|
||||
template<typename T> struct it_value_type { using value_type = T::value_type; };
|
||||
template<typename T> struct it_value_type<T*> { using value_type = T; };
|
||||
template<typename T> using it_value_type_t = typename it_value_type<T>::value_type;
|
||||
|
||||
template<typename T> struct less { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs < rhs; } };
|
||||
template<typename T> struct equal { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; } };
|
||||
template<typename T> struct greater { constexpr bool operator()(const T& lhs, const T& rhs) const { return lhs > rhs; } };
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace BAN::UTF8
|
||||
return 3;
|
||||
if ((first_byte & 0xF8) == 0xF0)
|
||||
return 4;
|
||||
return 0;
|
||||
return UTF8::invalid;
|
||||
}
|
||||
|
||||
template<typename T> requires (sizeof(T) == 1)
|
||||
|
||||
@@ -126,14 +126,16 @@ namespace BAN
|
||||
Variant(Variant&& other)
|
||||
: m_index(other.m_index)
|
||||
{
|
||||
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
if (other.has_value())
|
||||
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
other.clear();
|
||||
}
|
||||
|
||||
Variant(const Variant& other)
|
||||
: m_index(other.m_index)
|
||||
{
|
||||
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
if (other.has_value())
|
||||
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -157,12 +159,13 @@ namespace BAN
|
||||
|
||||
Variant& operator=(Variant&& other)
|
||||
{
|
||||
if (m_index == other.m_index)
|
||||
if (m_index == other.m_index && m_index != invalid_index())
|
||||
detail::move_assign<Ts...>(m_index, other.m_storage, m_storage);
|
||||
else
|
||||
{
|
||||
clear();
|
||||
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
if (other.has_value())
|
||||
detail::move_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
m_index = other.m_index;
|
||||
}
|
||||
other.clear();
|
||||
@@ -171,12 +174,13 @@ namespace BAN
|
||||
|
||||
Variant& operator=(const Variant& other)
|
||||
{
|
||||
if (m_index == other.m_index)
|
||||
if (m_index == other.m_index && m_index != invalid_index())
|
||||
detail::copy_assign<Ts...>(m_index, other.m_storage, m_storage);
|
||||
else
|
||||
{
|
||||
clear();
|
||||
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
if (other.has_value())
|
||||
detail::copy_construct<Ts...>(other.m_index, other.m_storage, m_storage);
|
||||
m_index = other.m_index;
|
||||
}
|
||||
return *this;
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace BAN
|
||||
bool contains(const T&) const;
|
||||
|
||||
Span<T> span() { return Span(m_data, m_size); }
|
||||
const Span<T> span() const { return Span(m_data, m_size); }
|
||||
Span<const T> span() const { return Span(m_data, m_size); }
|
||||
|
||||
const T& operator[](size_type) const;
|
||||
T& operator[](size_type);
|
||||
@@ -381,19 +381,46 @@ namespace BAN
|
||||
template<typename T>
|
||||
ErrorOr<void> Vector<T>::ensure_capacity(size_type size)
|
||||
{
|
||||
static_assert(alignof(T) <= alignof(max_align_t), "over aligned types not supported");
|
||||
|
||||
if (m_capacity >= size)
|
||||
return {};
|
||||
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
|
||||
T* new_data = (T*)BAN::allocator(new_cap * sizeof(T));
|
||||
if (new_data == nullptr)
|
||||
return Error::from_errno(ENOMEM);
|
||||
for (size_type i = 0; i < m_size; i++)
|
||||
|
||||
const size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
|
||||
|
||||
if constexpr (BAN::is_trivially_copyable_v<T>)
|
||||
{
|
||||
new (new_data + i) T(move(m_data[i]));
|
||||
m_data[i].~T();
|
||||
if constexpr (BAN::reallocator)
|
||||
{
|
||||
auto* new_data = static_cast<T*>(BAN::reallocator(m_data, new_cap * sizeof(T)));
|
||||
if (new_data == nullptr)
|
||||
return Error::from_errno(ENOMEM);
|
||||
m_data = new_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
|
||||
if (new_data == nullptr)
|
||||
return Error::from_errno(ENOMEM);
|
||||
memcpy(new_data, m_data, m_size * sizeof(T));
|
||||
BAN::deallocator(m_data);
|
||||
m_data = new_data;
|
||||
}
|
||||
}
|
||||
BAN::deallocator(m_data);
|
||||
m_data = new_data;
|
||||
else
|
||||
{
|
||||
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
|
||||
if (new_data == nullptr)
|
||||
return Error::from_errno(ENOMEM);
|
||||
for (size_type i = 0; i < m_size; i++)
|
||||
{
|
||||
new (new_data + i) T(move(m_data[i]));
|
||||
m_data[i].~T();
|
||||
}
|
||||
BAN::deallocator(m_data);
|
||||
m_data = new_data;
|
||||
}
|
||||
|
||||
m_capacity = new_cap;
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace BAN
|
||||
class WeakLink : public RefCounted<WeakLink<T>>
|
||||
{
|
||||
public:
|
||||
RefPtr<T> try_lock()
|
||||
RefPtr<T> try_lock() const
|
||||
{
|
||||
#if __is_kernel
|
||||
Kernel::SpinLockGuard _(m_weak_lock);
|
||||
@@ -44,7 +44,7 @@ namespace BAN
|
||||
private:
|
||||
T* m_ptr;
|
||||
#if __is_kernel
|
||||
Kernel::SpinLock m_weak_lock;
|
||||
mutable Kernel::SpinLock m_weak_lock;
|
||||
#endif
|
||||
friend class RefPtr<WeakLink<T>>;
|
||||
};
|
||||
@@ -99,7 +99,7 @@ namespace BAN
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefPtr<T> lock()
|
||||
RefPtr<T> lock() const
|
||||
{
|
||||
if (m_link)
|
||||
return m_link->try_lock();
|
||||
|
||||
@@ -29,12 +29,12 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# include headers of ${library} to ${target}
|
||||
function(banan_include_headers target library)
|
||||
target_include_directories(${target} PRIVATE $<TARGET_PROPERTY:${library},SOURCE_DIR>/include)
|
||||
target_include_directories(${target} PUBLIC $<TARGET_PROPERTY:${library},SOURCE_DIR>/include)
|
||||
endfunction()
|
||||
|
||||
# include headers and link ${library} to ${target}
|
||||
function(banan_link_library target library)
|
||||
target_link_libraries(${target} PRIVATE ${library})
|
||||
target_link_libraries(${target} PUBLIC ${library})
|
||||
banan_include_headers(${target} ${library})
|
||||
endfunction()
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ If you want to try out DOOM, you should first enter the GUI environment using th
|
||||
- [x] Basic graphical environment
|
||||
- [x] Terminal emulator
|
||||
- [x] Status bar
|
||||
- [ ] Program launcher
|
||||
- [x] Program launcher
|
||||
- [ ] Some nice apps
|
||||
- [x] ELF dynamic linking
|
||||
- [x] copy-on-write memory
|
||||
@@ -118,6 +118,8 @@ To change the bootloader you can set environment variable BANAN\_BOOTLOADER; sup
|
||||
|
||||
To run with UEFI set environment variable BANAN\_UEFI\_BOOT=1. You will also have to set OVMF\_PATH to the correct OVMF (default */usr/share/ovmf/x64/OVMF.fd*).
|
||||
|
||||
To build an image with no physical root filesystem, but an initrd set environment variable BANAN\_INITRD=1. This can be used when testing on hardware with unsupported USB controller.
|
||||
|
||||
If you have corrupted your disk image or want to create new one, you can either manually delete *build/banan-os.img* and build system will automatically create you a new one or you can run the following command.
|
||||
```sh
|
||||
./bos image-full
|
||||
|
||||
Binary file not shown.
@@ -1,11 +1,16 @@
|
||||
set(KERNEL_SOURCES
|
||||
font/prefs.psf.o
|
||||
kernel/ACPI/ACPI.cpp
|
||||
kernel/ACPI/BatterySystem.cpp
|
||||
kernel/ACPI/AML/Namespace.cpp
|
||||
kernel/ACPI/AML/Node.cpp
|
||||
kernel/ACPI/AML/OpRegion.cpp
|
||||
kernel/ACPI/BatterySystem.cpp
|
||||
kernel/ACPI/EmbeddedController.cpp
|
||||
kernel/APIC.cpp
|
||||
kernel/Audio/AC97/Controller.cpp
|
||||
kernel/Audio/Controller.cpp
|
||||
kernel/Audio/HDAudio/AudioFunctionGroup.cpp
|
||||
kernel/Audio/HDAudio/Controller.cpp
|
||||
kernel/BootInfo.cpp
|
||||
kernel/CPUID.cpp
|
||||
kernel/Credentials.cpp
|
||||
@@ -17,8 +22,10 @@ set(KERNEL_SOURCES
|
||||
kernel/Device/RandomDevice.cpp
|
||||
kernel/Device/ZeroDevice.cpp
|
||||
kernel/ELF.cpp
|
||||
kernel/Epoll.cpp
|
||||
kernel/Errors.cpp
|
||||
kernel/FS/DevFS/FileSystem.cpp
|
||||
kernel/FS/EventFD.cpp
|
||||
kernel/FS/Ext2/FileSystem.cpp
|
||||
kernel/FS/Ext2/Inode.cpp
|
||||
kernel/FS/FAT/FileSystem.cpp
|
||||
@@ -30,6 +37,7 @@ set(KERNEL_SOURCES
|
||||
kernel/FS/ProcFS/Inode.cpp
|
||||
kernel/FS/TmpFS/FileSystem.cpp
|
||||
kernel/FS/TmpFS/Inode.cpp
|
||||
kernel/FS/USTARModule.cpp
|
||||
kernel/FS/VirtualFileSystem.cpp
|
||||
kernel/GDT.cpp
|
||||
kernel/IDT.cpp
|
||||
@@ -42,6 +50,8 @@ set(KERNEL_SOURCES
|
||||
kernel/Interruptable.cpp
|
||||
kernel/InterruptController.cpp
|
||||
kernel/kernel.cpp
|
||||
kernel/Lock/SpinLock.cpp
|
||||
kernel/Memory/ByteRingBuffer.cpp
|
||||
kernel/Memory/DMARegion.cpp
|
||||
kernel/Memory/FileBackedRegion.cpp
|
||||
kernel/Memory/Heap.cpp
|
||||
@@ -55,6 +65,7 @@ set(KERNEL_SOURCES
|
||||
kernel/Networking/E1000/E1000.cpp
|
||||
kernel/Networking/E1000/E1000E.cpp
|
||||
kernel/Networking/IPv4Layer.cpp
|
||||
kernel/Networking/Loopback.cpp
|
||||
kernel/Networking/NetworkInterface.cpp
|
||||
kernel/Networking/NetworkLayer.cpp
|
||||
kernel/Networking/NetworkManager.cpp
|
||||
@@ -71,7 +82,6 @@ set(KERNEL_SOURCES
|
||||
kernel/Processor.cpp
|
||||
kernel/Random.cpp
|
||||
kernel/Scheduler.cpp
|
||||
kernel/ThreadBlocker.cpp
|
||||
kernel/SSP.cpp
|
||||
kernel/Storage/ATA/AHCI/Controller.cpp
|
||||
kernel/Storage/ATA/AHCI/Device.cpp
|
||||
@@ -94,6 +104,7 @@ set(KERNEL_SOURCES
|
||||
kernel/Terminal/TTY.cpp
|
||||
kernel/Terminal/VirtualTTY.cpp
|
||||
kernel/Thread.cpp
|
||||
kernel/ThreadBlocker.cpp
|
||||
kernel/Timer/HPET.cpp
|
||||
kernel/Timer/PIT.cpp
|
||||
kernel/Timer/RTC.cpp
|
||||
@@ -101,6 +112,7 @@ set(KERNEL_SOURCES
|
||||
kernel/USB/Controller.cpp
|
||||
kernel/USB/Device.cpp
|
||||
kernel/USB/HID/HIDDriver.cpp
|
||||
kernel/USB/HID/Joystick.cpp
|
||||
kernel/USB/HID/Keyboard.cpp
|
||||
kernel/USB/HID/Mouse.cpp
|
||||
kernel/USB/Hub/HubDriver.cpp
|
||||
@@ -127,6 +139,8 @@ if("${BANAN_ARCH}" STREQUAL "x86_64")
|
||||
arch/x86_64/Signal.S
|
||||
arch/x86_64/Syscall.S
|
||||
arch/x86_64/Thread.S
|
||||
arch/x86_64/User.S
|
||||
arch/x86_64/Yield.S
|
||||
)
|
||||
elseif("${BANAN_ARCH}" STREQUAL "i686")
|
||||
set(KERNEL_SOURCES
|
||||
@@ -137,6 +151,8 @@ elseif("${BANAN_ARCH}" STREQUAL "i686")
|
||||
arch/i686/Signal.S
|
||||
arch/i686/Syscall.S
|
||||
arch/i686/Thread.S
|
||||
arch/i686/User.S
|
||||
arch/i686/Yield.S
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "unsupported architecure ${BANAN_ARCH}")
|
||||
@@ -158,6 +174,12 @@ set(KLIBC_SOURCES
|
||||
../userspace/libraries/LibC/arch/${BANAN_ARCH}/string.S
|
||||
)
|
||||
|
||||
set(LIBDEFLATE_SOURCE
|
||||
../userspace/libraries/LibDEFLATE/Compressor.cpp
|
||||
../userspace/libraries/LibDEFLATE/Decompressor.cpp
|
||||
../userspace/libraries/LibDEFLATE/HuffmanTree.cpp
|
||||
)
|
||||
|
||||
set(LIBFONT_SOURCES
|
||||
../userspace/libraries/LibFont/Font.cpp
|
||||
../userspace/libraries/LibFont/PSF.cpp
|
||||
@@ -168,18 +190,25 @@ set(LIBINPUT_SOURCE
|
||||
../userspace/libraries/LibInput/KeyEvent.cpp
|
||||
)
|
||||
|
||||
set(LIBQR_SOURCE
|
||||
../userspace/libraries/LibQR/QRCode.cpp
|
||||
)
|
||||
|
||||
set(KERNEL_SOURCES
|
||||
${KERNEL_SOURCES}
|
||||
${BAN_SOURCES}
|
||||
${KLIBC_SOURCES}
|
||||
${LIBDEFLATE_SOURCE}
|
||||
${LIBFONT_SOURCES}
|
||||
${LIBINPUT_SOURCE}
|
||||
${LIBQR_SOURCE}
|
||||
)
|
||||
|
||||
add_executable(kernel ${KERNEL_SOURCES})
|
||||
|
||||
target_compile_definitions(kernel PRIVATE __is_kernel)
|
||||
target_compile_definitions(kernel PRIVATE __arch=${BANAN_ARCH})
|
||||
target_compile_definitions(kernel PRIVATE LIBDEFLATE_AVOID_STACK=1)
|
||||
|
||||
target_compile_options(kernel PRIVATE
|
||||
-O2 -g
|
||||
@@ -233,9 +262,11 @@ add_custom_command(
|
||||
|
||||
banan_include_headers(kernel ban)
|
||||
banan_include_headers(kernel libc)
|
||||
banan_include_headers(kernel libfont)
|
||||
banan_include_headers(kernel libdeflate)
|
||||
banan_include_headers(kernel libelf)
|
||||
banan_include_headers(kernel libfont)
|
||||
banan_include_headers(kernel libinput)
|
||||
banan_include_headers(kernel libqr)
|
||||
|
||||
banan_install_headers(kernel)
|
||||
set_target_properties(kernel PROPERTIES OUTPUT_NAME banan-os.kernel)
|
||||
|
||||
@@ -206,6 +206,7 @@ namespace Kernel
|
||||
{
|
||||
ASSERT(s_kernel);
|
||||
ASSERT(paddr);
|
||||
ASSERT(paddr % PAGE_SIZE == 0);
|
||||
|
||||
ASSERT(s_fast_page_lock.current_processor_has_lock());
|
||||
|
||||
@@ -220,7 +221,7 @@ namespace Kernel
|
||||
ASSERT(!(pt[pte] & Flags::Present));
|
||||
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
|
||||
|
||||
invalidate(fast_page(), false);
|
||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
||||
}
|
||||
|
||||
void PageTable::unmap_fast_page()
|
||||
@@ -240,7 +241,7 @@ namespace Kernel
|
||||
ASSERT(pt[pte] & Flags::Present);
|
||||
pt[pte] = 0;
|
||||
|
||||
invalidate(fast_page(), false);
|
||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
||||
}
|
||||
|
||||
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
|
||||
@@ -313,7 +314,8 @@ namespace Kernel
|
||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = 1
|
||||
.page_count = 1,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -342,8 +344,12 @@ namespace Kernel
|
||||
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
|
||||
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
||||
|
||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
||||
|
||||
pt[pte] = 0;
|
||||
invalidate(vaddr, send_smp_message);
|
||||
|
||||
if (old_paddr != 0)
|
||||
invalidate(vaddr, send_smp_message);
|
||||
}
|
||||
|
||||
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
||||
@@ -360,7 +366,8 @@ namespace Kernel
|
||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = page_count
|
||||
.page_count = page_count,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -416,9 +423,13 @@ namespace Kernel
|
||||
uwr_flags &= ~Flags::Present;
|
||||
|
||||
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
||||
|
||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
||||
|
||||
pt[pte] = paddr | uwr_flags | extra_flags;
|
||||
|
||||
invalidate(vaddr, send_smp_message);
|
||||
if (old_paddr != 0)
|
||||
invalidate(vaddr, send_smp_message);
|
||||
}
|
||||
|
||||
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags, MemoryType memory_type)
|
||||
@@ -437,7 +448,8 @@ namespace Kernel
|
||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = page_count
|
||||
.page_count = page_count,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -496,13 +508,13 @@ namespace Kernel
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free)
|
||||
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free, bool send_smp_message)
|
||||
{
|
||||
SpinLockGuard _(m_lock);
|
||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||
if (only_free && !is_page_free(vaddr))
|
||||
return false;
|
||||
map_page_at(0, vaddr, Flags::Reserved);
|
||||
map_page_at(0, vaddr, Flags::Reserved, MemoryType::Normal, send_smp_message);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -516,7 +528,15 @@ namespace Kernel
|
||||
if (only_free && !is_range_free(vaddr, bytes))
|
||||
return false;
|
||||
for (size_t offset = 0; offset < bytes; offset += PAGE_SIZE)
|
||||
reserve_page(vaddr + offset);
|
||||
reserve_page(vaddr + offset, true, false);
|
||||
Processor::broadcast_smp_message({
|
||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = bytes / PAGE_SIZE,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,33 +2,72 @@
|
||||
|
||||
// stack contains
|
||||
// return address
|
||||
// return stack
|
||||
// return rflags
|
||||
// siginfo_t
|
||||
// signal number
|
||||
// signal handler
|
||||
|
||||
.global signal_trampoline
|
||||
signal_trampoline:
|
||||
pushl %esi // gregs
|
||||
pushl %edi
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
|
||||
pusha
|
||||
// FIXME: populate these
|
||||
xorl %eax, %eax
|
||||
pushl %eax // stack
|
||||
pushl %eax
|
||||
pushl %eax
|
||||
pushl %eax // sigset
|
||||
pushl %eax
|
||||
pushl %eax // link
|
||||
|
||||
movl 40(%esp), %edi
|
||||
movl 36(%esp), %eax
|
||||
movl %esp, %edx // ucontext
|
||||
leal 60(%esp), %esi // siginfo
|
||||
movl 56(%esp), %edi // signal number
|
||||
movl 52(%esp), %eax // handlers
|
||||
|
||||
// align stack to 16 bytes
|
||||
movl %esp, %ebp
|
||||
andl $-16, %esp
|
||||
|
||||
subl $12, %esp
|
||||
subl $512, %esp
|
||||
fxsave (%esp)
|
||||
|
||||
subl $4, %esp
|
||||
pushl %edx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
call *%eax
|
||||
addl $16, %esp
|
||||
|
||||
fxrstor (%esp)
|
||||
addl $512, %esp
|
||||
|
||||
// restore stack
|
||||
movl %ebp, %esp
|
||||
popa
|
||||
addl $24, %esp
|
||||
|
||||
leave
|
||||
addl $8, %esp
|
||||
// restore registers
|
||||
popl %ebp
|
||||
popl %eax
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %edi
|
||||
popl %esi
|
||||
|
||||
// skip handler, number, siginfo_t
|
||||
addl $44, %esp
|
||||
|
||||
// restore flags
|
||||
popf
|
||||
|
||||
movl (%esp), %esp
|
||||
|
||||
ret
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
// arguments in EAX, EBX, ECX, EDX, ESI, EDI
|
||||
.global asm_syscall_handler
|
||||
asm_syscall_handler:
|
||||
# save segment registers
|
||||
pushw %ds
|
||||
pushw %es
|
||||
pushw %fs
|
||||
pushw %gs
|
||||
|
||||
# save general purpose registers
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
@@ -18,13 +12,10 @@ asm_syscall_handler:
|
||||
|
||||
# align stack
|
||||
movl %esp, %ebp
|
||||
subl $15, %esp
|
||||
andl $0xFFFFFFF0, %esp
|
||||
andl $-16, %esp
|
||||
|
||||
# push arguments
|
||||
subl $4, %esp
|
||||
pushl %ebp
|
||||
addl $32, (%esp)
|
||||
subl $8, %esp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
@@ -44,6 +35,15 @@ asm_syscall_handler:
|
||||
|
||||
movl %ebp, %esp
|
||||
|
||||
# restore userspace segments
|
||||
movw $(0x20 | 3), %bx
|
||||
movw %bx, %ds
|
||||
movw %bx, %es
|
||||
movw $(0x30 | 3), %bx
|
||||
movw %bx, %fs
|
||||
movw $(0x38 | 3), %bx
|
||||
movw %bx, %gs
|
||||
|
||||
# restore general purpose registers
|
||||
popl %ebp
|
||||
popl %esi
|
||||
@@ -52,12 +52,6 @@ asm_syscall_handler:
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
|
||||
# restore segment registers
|
||||
popw %gs
|
||||
popw %fs
|
||||
popw %es
|
||||
popw %ds
|
||||
|
||||
iret
|
||||
|
||||
.global sys_fork_trampoline
|
||||
|
||||
@@ -31,25 +31,18 @@ start_kernel_thread:
|
||||
subl $12, %esp
|
||||
pushl %edi
|
||||
call *%esi
|
||||
addl $16, %esp
|
||||
|
||||
|
||||
.global start_userspace_thread
|
||||
start_userspace_thread:
|
||||
call load_thread_sse
|
||||
|
||||
call get_thread_start_sp
|
||||
movl %eax, %esp
|
||||
|
||||
# ds, es = user data
|
||||
movw $(0x20 | 3), %bx
|
||||
movw %bx, %ds
|
||||
movw %bx, %es
|
||||
# gs = thread local
|
||||
movw $(0x30 | 3), %bx
|
||||
movw %bx, %gs
|
||||
# fs = 0
|
||||
xorw %bx, %bx
|
||||
movw %bx, %fs
|
||||
movw $(0x38 | 3), %bx
|
||||
movw %bx, %gs
|
||||
|
||||
iret
|
||||
|
||||
54
kernel/arch/i686/User.S
Normal file
54
kernel/arch/i686/User.S
Normal file
@@ -0,0 +1,54 @@
|
||||
# bool safe_user_memcpy(void*, const void*, size_t)
|
||||
.global safe_user_memcpy
|
||||
.global safe_user_memcpy_end
|
||||
.global safe_user_memcpy_fault
|
||||
safe_user_memcpy:
|
||||
xorl %eax, %eax
|
||||
xchgl 4(%esp), %edi
|
||||
xchgl 8(%esp), %esi
|
||||
movl 12(%esp), %ecx
|
||||
movl %edi, %edx
|
||||
rep movsb
|
||||
movl 4(%esp), %edi
|
||||
movl 8(%esp), %esi
|
||||
incl %eax
|
||||
safe_user_memcpy_fault:
|
||||
ret
|
||||
safe_user_memcpy_end:
|
||||
|
||||
# bool safe_user_strncpy(void*, const void*, size_t)
|
||||
.global safe_user_strncpy
|
||||
.global safe_user_strncpy_end
|
||||
.global safe_user_strncpy_fault
|
||||
safe_user_strncpy:
|
||||
xchgl 4(%esp), %edi
|
||||
xchgl 8(%esp), %esi
|
||||
movl 12(%esp), %ecx
|
||||
|
||||
testl %ecx, %ecx
|
||||
jz safe_user_strncpy_fault
|
||||
|
||||
.safe_user_strncpy_loop:
|
||||
movb (%esi), %al
|
||||
movb %al, (%edi)
|
||||
testb %al, %al
|
||||
jz .safe_user_strncpy_done
|
||||
|
||||
incl %edi
|
||||
incl %esi
|
||||
decl %ecx
|
||||
jnz .safe_user_strncpy_loop
|
||||
|
||||
safe_user_strncpy_fault:
|
||||
xorl %eax, %eax
|
||||
jmp .safe_user_strncpy_return
|
||||
|
||||
.safe_user_strncpy_done:
|
||||
movl $1, %eax
|
||||
|
||||
.safe_user_strncpy_return:
|
||||
movl 4(%esp), %edi
|
||||
movl 8(%esp), %esi
|
||||
ret
|
||||
|
||||
safe_user_strncpy_end:
|
||||
25
kernel/arch/i686/Yield.S
Normal file
25
kernel/arch/i686/Yield.S
Normal file
@@ -0,0 +1,25 @@
|
||||
.global asm_yield_trampoline
|
||||
asm_yield_trampoline:
|
||||
leal 4(%esp), %ecx
|
||||
movl 4(%esp), %esp
|
||||
|
||||
pushl -4(%ecx)
|
||||
pushl %ecx
|
||||
pushl %eax
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
pushl %ebp
|
||||
|
||||
pushl %esp
|
||||
call scheduler_on_yield
|
||||
addl $4, %esp
|
||||
|
||||
popl %ebp
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebx
|
||||
popl %eax
|
||||
movl 4(%esp), %ecx
|
||||
movl 0(%esp), %esp
|
||||
jmp *%ecx
|
||||
@@ -14,6 +14,23 @@
|
||||
# multiboot2 header
|
||||
.section .multiboot, "aw"
|
||||
.align 8
|
||||
multiboot_start:
|
||||
.long 0x1BADB002
|
||||
.long (1 << 2) # page align modules
|
||||
.long -(0x1BADB002 + (1 << 2))
|
||||
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.long 0
|
||||
.long FB_WIDTH
|
||||
.long FB_HEIGHT
|
||||
.long FB_BPP
|
||||
multiboot_end:
|
||||
.align 8
|
||||
multiboot2_start:
|
||||
.long 0xE85250D6
|
||||
.long 0
|
||||
@@ -36,6 +53,12 @@ multiboot2_start:
|
||||
.long 12
|
||||
.long V2P(_start)
|
||||
|
||||
# page align modules
|
||||
.align 8
|
||||
.short 6
|
||||
.short 0
|
||||
.long 8
|
||||
|
||||
.align 8
|
||||
.short 0
|
||||
.short 0
|
||||
@@ -53,10 +76,10 @@ bananboot_start:
|
||||
bananboot_end:
|
||||
|
||||
.section .bss, "aw", @nobits
|
||||
.align 4096
|
||||
boot_stack_bottom:
|
||||
.global g_boot_stack_top
|
||||
g_boot_stack_bottom:
|
||||
.skip 4096 * 4
|
||||
boot_stack_top:
|
||||
g_boot_stack_top:
|
||||
|
||||
.global g_kernel_cmdline
|
||||
g_kernel_cmdline:
|
||||
@@ -161,6 +184,13 @@ enable_sse:
|
||||
movl %eax, %cr4
|
||||
ret
|
||||
|
||||
enable_tsc:
|
||||
# allow userspace to use RDTSC
|
||||
movl %cr4, %ecx
|
||||
andl $0xFFFFFFFB, %ecx
|
||||
movl %ecx, %cr4
|
||||
ret
|
||||
|
||||
initialize_paging:
|
||||
# enable PAE
|
||||
movl %cr4, %ecx
|
||||
@@ -188,7 +218,7 @@ _start:
|
||||
movl %ebx, V2P(bootloader_info)
|
||||
|
||||
# load boot stack
|
||||
movl $V2P(boot_stack_top), %esp
|
||||
movl $V2P(g_boot_stack_top), %esp
|
||||
|
||||
# load boot GDT
|
||||
lgdt V2P(boot_gdtr)
|
||||
@@ -203,10 +233,11 @@ gdt_flush:
|
||||
# do processor initialization
|
||||
call check_requirements
|
||||
call enable_sse
|
||||
call enable_tsc
|
||||
call initialize_paging
|
||||
|
||||
# load higher half stack pointer
|
||||
movl $boot_stack_top, %esp
|
||||
movl $g_boot_stack_top, %esp
|
||||
|
||||
# jump to higher half
|
||||
leal higher_half, %ecx
|
||||
@@ -279,6 +310,7 @@ ap_protected_mode:
|
||||
movb $1, AP_V2P(ap_stack_loaded)
|
||||
|
||||
leal V2P(enable_sse), %ecx; call *%ecx
|
||||
leal V2P(enable_tsc), %ecx; call *%ecx
|
||||
leal V2P(initialize_paging), %ecx; call *%ecx
|
||||
|
||||
# load boot gdt and enter long mode
|
||||
|
||||
@@ -1,32 +1,33 @@
|
||||
.macro push_userspace
|
||||
pushw %gs
|
||||
pushw %fs
|
||||
pushw %es
|
||||
pushw %ds
|
||||
pushal
|
||||
.endm
|
||||
.macro maybe_load_kernel_segments, n
|
||||
testb $3, \n(%esp)
|
||||
jz 1f; jnp 1f
|
||||
|
||||
.macro load_kernel_segments
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
|
||||
movw $0x28, %ax
|
||||
movw %ax, %gs
|
||||
1:
|
||||
.endm
|
||||
|
||||
.macro pop_userspace
|
||||
popal
|
||||
popw %ds
|
||||
popw %es
|
||||
popw %fs
|
||||
popw %gs
|
||||
.macro maybe_load_userspace_segments, n
|
||||
testb $3, \n(%esp)
|
||||
jz 1f; jnp 1f
|
||||
|
||||
movw $(0x20 | 3), %bx
|
||||
movw %bx, %ds
|
||||
movw %bx, %es
|
||||
movw $(0x30 | 3), %bx
|
||||
movw %bx, %fs
|
||||
movw $(0x38 | 3), %bx
|
||||
movw %bx, %gs
|
||||
1:
|
||||
.endm
|
||||
|
||||
isr_stub:
|
||||
push_userspace
|
||||
load_kernel_segments
|
||||
pushal
|
||||
maybe_load_kernel_segments 44
|
||||
cld
|
||||
|
||||
movl %cr0, %eax; pushl %eax
|
||||
@@ -34,33 +35,39 @@ isr_stub:
|
||||
movl %cr3, %eax; pushl %eax
|
||||
movl %cr4, %eax; pushl %eax
|
||||
|
||||
movl %esp, %eax // register ptr
|
||||
leal 64(%esp), %ebx // interrupt stack ptr
|
||||
movl 60(%esp), %ecx // error code
|
||||
movl 56(%esp), %edx // isr number
|
||||
movl 48(%esp), %edi // isr number
|
||||
movl 52(%esp), %esi // error code
|
||||
leal 56(%esp), %edx // interrupt stack ptr
|
||||
movl %esp, %ecx // register ptr
|
||||
|
||||
# stack frame for stack trace
|
||||
leal 56(%esp), %eax
|
||||
pushl (%eax)
|
||||
pushl %ebp
|
||||
|
||||
movl %esp, %ebp
|
||||
andl $-16, %esp
|
||||
|
||||
pushl %eax
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
call cpp_isr_handler
|
||||
|
||||
movl %ebp, %esp
|
||||
addl $16, %esp
|
||||
addl $24, %esp
|
||||
|
||||
pop_userspace
|
||||
maybe_load_userspace_segments 44
|
||||
popal
|
||||
addl $8, %esp
|
||||
iret
|
||||
|
||||
irq_stub:
|
||||
push_userspace
|
||||
load_kernel_segments
|
||||
pushal
|
||||
maybe_load_kernel_segments 44
|
||||
cld
|
||||
|
||||
movl 40(%esp), %edi # interrupt number
|
||||
movl 32(%esp), %edi # interrupt number
|
||||
|
||||
movl %esp, %ebp
|
||||
andl $-16, %esp
|
||||
@@ -71,36 +78,15 @@ irq_stub:
|
||||
|
||||
movl %ebp, %esp
|
||||
|
||||
pop_userspace
|
||||
addl $8, %esp
|
||||
iret
|
||||
|
||||
.global asm_yield_handler
|
||||
asm_yield_handler:
|
||||
# This can only be called from kernel, so no segment saving is needed
|
||||
pushal
|
||||
cld
|
||||
|
||||
leal 32(%esp), %edi # interrupt stack ptr
|
||||
movl %esp, %esi # interrupt registers ptr
|
||||
|
||||
movl %esp, %ebp
|
||||
andl $-16, %esp
|
||||
|
||||
subl $8, %esp
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
call cpp_yield_handler
|
||||
|
||||
movl %ebp, %esp
|
||||
|
||||
maybe_load_userspace_segments 44
|
||||
popal
|
||||
addl $8, %esp
|
||||
iret
|
||||
|
||||
.global asm_ipi_handler
|
||||
asm_ipi_handler:
|
||||
push_userspace
|
||||
load_kernel_segments
|
||||
pushal
|
||||
maybe_load_kernel_segments 36
|
||||
cld
|
||||
|
||||
movl %esp, %ebp
|
||||
@@ -110,13 +96,14 @@ asm_ipi_handler:
|
||||
|
||||
movl %ebp, %esp
|
||||
|
||||
pop_userspace
|
||||
maybe_load_userspace_segments 36
|
||||
popal
|
||||
iret
|
||||
|
||||
.global asm_timer_handler
|
||||
asm_timer_handler:
|
||||
push_userspace
|
||||
load_kernel_segments
|
||||
pushal
|
||||
maybe_load_kernel_segments 36
|
||||
cld
|
||||
|
||||
movl %esp, %ebp
|
||||
@@ -126,7 +113,8 @@ asm_timer_handler:
|
||||
|
||||
movl %ebp, %esp
|
||||
|
||||
pop_userspace
|
||||
maybe_load_userspace_segments 36
|
||||
popal
|
||||
iret
|
||||
|
||||
.macro isr n
|
||||
|
||||
@@ -503,6 +503,7 @@ namespace Kernel
|
||||
{
|
||||
ASSERT(s_kernel);
|
||||
ASSERT(paddr);
|
||||
ASSERT(paddr % PAGE_SIZE == 0);
|
||||
|
||||
ASSERT(s_fast_page_lock.current_processor_has_lock());
|
||||
|
||||
@@ -520,7 +521,7 @@ namespace Kernel
|
||||
ASSERT(!(pt[pte] & Flags::Present));
|
||||
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
|
||||
|
||||
invalidate(fast_page(), false);
|
||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
||||
}
|
||||
|
||||
void PageTable::unmap_fast_page()
|
||||
@@ -543,7 +544,7 @@ namespace Kernel
|
||||
ASSERT(pt[pte] & Flags::Present);
|
||||
pt[pte] = 0;
|
||||
|
||||
invalidate(fast_page(), false);
|
||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
||||
}
|
||||
|
||||
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
|
||||
@@ -622,7 +623,8 @@ namespace Kernel
|
||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = 1
|
||||
.page_count = 1,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -657,8 +659,12 @@ namespace Kernel
|
||||
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
||||
|
||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
||||
|
||||
pt[pte] = 0;
|
||||
invalidate(vaddr, send_smp_message);
|
||||
|
||||
if (old_paddr != 0)
|
||||
invalidate(vaddr, send_smp_message);
|
||||
}
|
||||
|
||||
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
||||
@@ -675,7 +681,8 @@ namespace Kernel
|
||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = page_count
|
||||
.page_count = page_count,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -741,9 +748,12 @@ namespace Kernel
|
||||
if (!(flags & Flags::Present))
|
||||
uwr_flags &= ~Flags::Present;
|
||||
|
||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
||||
|
||||
pt[pte] = paddr | uwr_flags | extra_flags;
|
||||
|
||||
invalidate(vaddr, send_smp_message);
|
||||
if (old_paddr != 0)
|
||||
invalidate(vaddr, send_smp_message);
|
||||
}
|
||||
|
||||
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags, MemoryType memory_type)
|
||||
@@ -764,7 +774,8 @@ namespace Kernel
|
||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = page_count
|
||||
.page_count = page_count,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -813,13 +824,13 @@ namespace Kernel
|
||||
return page_data & s_page_addr_mask;
|
||||
}
|
||||
|
||||
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free)
|
||||
bool PageTable::reserve_page(vaddr_t vaddr, bool only_free, bool send_smp_message)
|
||||
{
|
||||
SpinLockGuard _(m_lock);
|
||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||
if (only_free && !is_page_free(vaddr))
|
||||
return false;
|
||||
map_page_at(0, vaddr, Flags::Reserved);
|
||||
map_page_at(0, vaddr, Flags::Reserved, MemoryType::Normal, send_smp_message);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -833,7 +844,15 @@ namespace Kernel
|
||||
if (only_free && !is_range_free(vaddr, bytes))
|
||||
return false;
|
||||
for (size_t offset = 0; offset < bytes; offset += PAGE_SIZE)
|
||||
reserve_page(vaddr + offset);
|
||||
reserve_page(vaddr + offset, true, false);
|
||||
Processor::broadcast_smp_message({
|
||||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = bytes / PAGE_SIZE,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -847,7 +866,7 @@ namespace Kernel
|
||||
last_address -= rem;
|
||||
|
||||
ASSERT(is_canonical(first_address));
|
||||
ASSERT(is_canonical(last_address));
|
||||
ASSERT(is_canonical(last_address - 1));
|
||||
const vaddr_t uc_vaddr_start = uncanonicalize(first_address);
|
||||
const vaddr_t uc_vaddr_end = uncanonicalize(last_address);
|
||||
|
||||
@@ -929,7 +948,7 @@ namespace Kernel
|
||||
last_address -= rem;
|
||||
|
||||
ASSERT(is_canonical(first_address));
|
||||
ASSERT(is_canonical(last_address));
|
||||
ASSERT(is_canonical(last_address - 1));
|
||||
|
||||
SpinLockGuard _(m_lock);
|
||||
|
||||
|
||||
@@ -2,55 +2,83 @@
|
||||
|
||||
// stack contains
|
||||
// return address
|
||||
// return stack
|
||||
// return rflags
|
||||
// siginfo_t
|
||||
// signal number
|
||||
// signal handler
|
||||
|
||||
.global signal_trampoline
|
||||
signal_trampoline:
|
||||
pushq %rax
|
||||
pushq %rbx
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
pushq %rbp
|
||||
pushq %rdi
|
||||
pushq %rsi
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r10
|
||||
pushq %r11
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r15 // gregs
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
pushq %r13
|
||||
pushq %r12
|
||||
pushq %r11
|
||||
pushq %r10
|
||||
pushq %r9
|
||||
pushq %r8
|
||||
pushq %rsi
|
||||
pushq %rdi
|
||||
pushq %rdx
|
||||
pushq %rcx
|
||||
pushq %rbx
|
||||
pushq %rax
|
||||
pushq %rbp
|
||||
|
||||
movq 128(%rsp), %rdi
|
||||
movq 120(%rsp), %rax
|
||||
// FIXME: populate these
|
||||
xorq %rax, %rax
|
||||
pushq %rax // stack
|
||||
pushq %rax
|
||||
pushq %rax
|
||||
pushq %rax // sigset
|
||||
pushq %rax // link
|
||||
|
||||
movq %rsp, %rdx // ucontext
|
||||
leaq 176(%rsp), %rsi // siginfo
|
||||
movq 168(%rsp), %rdi // signal number
|
||||
movq 160(%rsp), %rax // handler
|
||||
|
||||
// align stack to 16 bytes
|
||||
movq %rsp, %rbp
|
||||
andq $-16, %rsp
|
||||
|
||||
subq $512, %rsp
|
||||
fxsave64 (%rsp)
|
||||
|
||||
call *%rax
|
||||
|
||||
fxrstor64 (%rsp)
|
||||
addq $512, %rsp
|
||||
|
||||
// restore stack
|
||||
movq %rbp, %rsp
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
addq $40, %rsp
|
||||
|
||||
// restore registers
|
||||
popq %rbp
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rbx
|
||||
popq %rax
|
||||
popq %rbx
|
||||
popq %rcx
|
||||
popq %rdx
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
popq %r8
|
||||
popq %r9
|
||||
popq %r10
|
||||
popq %r11
|
||||
popq %r12
|
||||
popq %r13
|
||||
popq %r14
|
||||
popq %r15
|
||||
|
||||
addq $16, %rsp
|
||||
// skip handler, number, siginfo_t
|
||||
addq $72, %rsp
|
||||
|
||||
// return over red-zone
|
||||
// restore flags
|
||||
popfq
|
||||
|
||||
movq (%rsp), %rsp
|
||||
|
||||
// return over red-zone and siginfo_t
|
||||
ret $128
|
||||
|
||||
@@ -1,49 +1,26 @@
|
||||
// arguments in RAX, RBX, RCX, RDX, RSI, RDI
|
||||
// System V ABI: RDI, RSI, RDX, RCX, R8, R9
|
||||
.global asm_syscall_handler
|
||||
asm_syscall_handler:
|
||||
pushq %rbx
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
pushq %rdi
|
||||
pushq %rsi
|
||||
pushq %rbp
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r10
|
||||
swapgs
|
||||
|
||||
movq %rsp, %rax
|
||||
movq %gs:8, %rsp
|
||||
|
||||
pushq $(0x20 | 3)
|
||||
pushq %rax
|
||||
pushq %r11
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
cld
|
||||
pushq $(0x28 | 3)
|
||||
pushq %rcx
|
||||
subq $8, %rsp
|
||||
|
||||
movq %rsi, %r8
|
||||
movq %rdi, %r9
|
||||
movq %rax, %rdi
|
||||
movq %rbx, %rsi
|
||||
xchgq %rcx, %rdx
|
||||
leaq 112(%rsp), %rbx
|
||||
pushq %rbx
|
||||
movq %r10, %rcx
|
||||
call cpp_syscall_handler
|
||||
addq $8, %rsp
|
||||
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rbp
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rbx
|
||||
iretq
|
||||
movq 8(%rsp), %rcx
|
||||
movq 24(%rsp), %r11
|
||||
movq 32(%rsp), %rsp
|
||||
|
||||
swapgs
|
||||
sysretq
|
||||
|
||||
.global sys_fork_trampoline
|
||||
sys_fork_trampoline:
|
||||
@@ -56,7 +33,7 @@ sys_fork_trampoline:
|
||||
|
||||
call read_ip
|
||||
testq %rax, %rax
|
||||
je .reload_stack
|
||||
je .done
|
||||
|
||||
movq %rax, %rsi
|
||||
movq %rsp, %rdi
|
||||
@@ -70,9 +47,3 @@ sys_fork_trampoline:
|
||||
popq %rbp
|
||||
popq %rbx
|
||||
ret
|
||||
|
||||
.reload_stack:
|
||||
call get_thread_start_sp
|
||||
movq %rax, %rsp
|
||||
xorq %rax, %rax
|
||||
jmp .done
|
||||
|
||||
@@ -27,9 +27,9 @@ start_kernel_thread:
|
||||
|
||||
.global start_userspace_thread
|
||||
start_userspace_thread:
|
||||
call load_thread_sse
|
||||
|
||||
call get_thread_start_sp
|
||||
movq %rax, %rsp
|
||||
|
||||
swapgs
|
||||
|
||||
iretq
|
||||
|
||||
87
kernel/arch/x86_64/User.S
Normal file
87
kernel/arch/x86_64/User.S
Normal file
@@ -0,0 +1,87 @@
|
||||
# bool safe_user_memcpy(void*, const void*, size_t)
|
||||
.global safe_user_memcpy
|
||||
.global safe_user_memcpy_end
|
||||
.global safe_user_memcpy_fault
|
||||
safe_user_memcpy:
|
||||
xorq %rax, %rax
|
||||
movq %rdx, %rcx
|
||||
rep movsb
|
||||
incq %rax
|
||||
safe_user_memcpy_fault:
|
||||
ret
|
||||
safe_user_memcpy_end:
|
||||
|
||||
# bool safe_user_strncpy(void*, const void*, size_t)
|
||||
.global safe_user_strncpy
|
||||
.global safe_user_strncpy_end
|
||||
.global safe_user_strncpy_fault
|
||||
safe_user_strncpy:
|
||||
movq %rdx, %rcx
|
||||
testq %rcx, %rcx
|
||||
jz safe_user_strncpy_fault
|
||||
|
||||
.safe_user_strncpy_align_loop:
|
||||
testb $0x7, %sil
|
||||
jz .safe_user_strncpy_align_done
|
||||
|
||||
movb (%rsi), %al
|
||||
movb %al, (%rdi)
|
||||
testb %al, %al
|
||||
jz .safe_user_strncpy_done
|
||||
|
||||
incq %rdi
|
||||
incq %rsi
|
||||
decq %rcx
|
||||
jnz .safe_user_strncpy_align_loop
|
||||
jmp safe_user_strncpy_fault
|
||||
|
||||
.safe_user_strncpy_align_done:
|
||||
movq $0x0101010101010101, %r8
|
||||
movq $0x8080808080808080, %r9
|
||||
|
||||
.safe_user_strncpy_qword_loop:
|
||||
cmpq $8, %rcx
|
||||
jb .safe_user_strncpy_qword_done
|
||||
|
||||
movq (%rsi), %rax
|
||||
movq %rax, %r10
|
||||
movq %rax, %r11
|
||||
|
||||
# https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
|
||||
subq %r8, %r10
|
||||
notq %r11
|
||||
andq %r11, %r10
|
||||
andq %r9, %r10
|
||||
jnz .safe_user_strncpy_byte_loop
|
||||
|
||||
movq %rax, (%rdi)
|
||||
|
||||
addq $8, %rdi
|
||||
addq $8, %rsi
|
||||
subq $8, %rcx
|
||||
jnz .safe_user_strncpy_qword_loop
|
||||
jmp safe_user_strncpy_fault
|
||||
|
||||
.safe_user_strncpy_qword_done:
|
||||
testq %rcx, %rcx
|
||||
jz safe_user_strncpy_fault
|
||||
|
||||
.safe_user_strncpy_byte_loop:
|
||||
movb (%rsi), %al
|
||||
movb %al, (%rdi)
|
||||
testb %al, %al
|
||||
jz .safe_user_strncpy_done
|
||||
|
||||
incq %rdi
|
||||
incq %rsi
|
||||
decq %rcx
|
||||
jnz .safe_user_strncpy_byte_loop
|
||||
|
||||
safe_user_strncpy_fault:
|
||||
xorq %rax, %rax
|
||||
ret
|
||||
|
||||
.safe_user_strncpy_done:
|
||||
movb $1, %al
|
||||
ret
|
||||
safe_user_strncpy_end:
|
||||
29
kernel/arch/x86_64/Yield.S
Normal file
29
kernel/arch/x86_64/Yield.S
Normal file
@@ -0,0 +1,29 @@
|
||||
.global asm_yield_trampoline
|
||||
asm_yield_trampoline:
|
||||
leaq 8(%rsp), %rcx
|
||||
movq %rdi, %rsp
|
||||
|
||||
subq $8, %rsp
|
||||
pushq -8(%rcx)
|
||||
pushq %rcx
|
||||
pushq %rax
|
||||
pushq %rbx
|
||||
pushq %rbp
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
|
||||
movq %rsp, %rdi
|
||||
call scheduler_on_yield
|
||||
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %rbp
|
||||
popq %rbx
|
||||
popq %rax
|
||||
movq 8(%rsp), %rcx
|
||||
movq 0(%rsp), %rsp
|
||||
jmp *%rcx
|
||||
@@ -14,6 +14,23 @@
|
||||
# multiboot2 header
|
||||
.section .multiboot, "aw"
|
||||
.align 8
|
||||
multiboot_start:
|
||||
.long 0x1BADB002
|
||||
.long (1 << 2) # page align modules
|
||||
.long -(0x1BADB002 + (1 << 2))
|
||||
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.long 0
|
||||
.long FB_WIDTH
|
||||
.long FB_HEIGHT
|
||||
.long FB_BPP
|
||||
multiboot_end:
|
||||
.align 8
|
||||
multiboot2_start:
|
||||
.long 0xE85250D6
|
||||
.long 0
|
||||
@@ -36,6 +53,12 @@ multiboot2_start:
|
||||
.long 12
|
||||
.long V2P(_start)
|
||||
|
||||
# page align modules
|
||||
.align 8
|
||||
.short 6
|
||||
.short 0
|
||||
.long 8
|
||||
|
||||
.align 8
|
||||
.short 0
|
||||
.short 0
|
||||
@@ -53,9 +76,10 @@ bananboot_start:
|
||||
bananboot_end:
|
||||
|
||||
.section .bss, "aw", @nobits
|
||||
boot_stack_bottom:
|
||||
.skip 4096 * 64
|
||||
boot_stack_top:
|
||||
.global g_boot_stack_top
|
||||
g_boot_stack_bottom:
|
||||
.skip 4096 * 4
|
||||
g_boot_stack_top:
|
||||
|
||||
.global g_kernel_cmdline
|
||||
g_kernel_cmdline:
|
||||
@@ -155,6 +179,13 @@ enable_sse:
|
||||
movl %eax, %cr4
|
||||
ret
|
||||
|
||||
enable_tsc:
|
||||
# allow userspace to use RDTSC
|
||||
movl %cr4, %ecx
|
||||
andl $0xFFFFFFFB, %ecx
|
||||
movl %ecx, %cr4
|
||||
ret
|
||||
|
||||
initialize_paging:
|
||||
# enable PAE
|
||||
movl %cr4, %ecx
|
||||
@@ -187,10 +218,11 @@ _start:
|
||||
movl %eax, V2P(bootloader_magic)
|
||||
movl %ebx, V2P(bootloader_info)
|
||||
|
||||
movl $V2P(boot_stack_top), %esp
|
||||
movl $V2P(g_boot_stack_top), %esp
|
||||
|
||||
call check_requirements
|
||||
call enable_sse
|
||||
call enable_tsc
|
||||
call initialize_paging
|
||||
|
||||
# flush gdt and jump to 64 bit
|
||||
@@ -277,6 +309,7 @@ ap_protected_mode:
|
||||
movb $1, AP_V2P(ap_stack_loaded)
|
||||
|
||||
leal V2P(enable_sse), %ecx; call *%ecx
|
||||
leal V2P(enable_tsc), %ecx; call *%ecx
|
||||
leal V2P(initialize_paging), %ecx; call *%ecx
|
||||
|
||||
# load boot gdt and enter long mode
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
.macro pushaq
|
||||
.macro swapgs_if_necessary, n
|
||||
testb $3, \n(%rsp)
|
||||
jz 1f; jnp 1f
|
||||
swapgs
|
||||
1:
|
||||
.endm
|
||||
|
||||
.macro pushaq, n
|
||||
swapgs_if_necessary \n
|
||||
pushq %rax
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
@@ -16,7 +24,7 @@
|
||||
pushq %r15
|
||||
.endm
|
||||
|
||||
.macro popaq
|
||||
.macro popaq, n
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
@@ -32,10 +40,11 @@
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rax
|
||||
swapgs_if_necessary \n
|
||||
.endm
|
||||
|
||||
isr_stub:
|
||||
pushaq
|
||||
pushaq 24
|
||||
cld
|
||||
movq %cr0, %rax; pushq %rax
|
||||
movq %cr2, %rax; pushq %rax
|
||||
@@ -49,43 +58,33 @@ isr_stub:
|
||||
call cpp_isr_handler
|
||||
addq $32, %rsp
|
||||
|
||||
popaq
|
||||
popaq 24
|
||||
addq $16, %rsp
|
||||
iretq
|
||||
|
||||
irq_stub:
|
||||
pushaq
|
||||
pushaq 24
|
||||
cld
|
||||
movq 120(%rsp), %rdi # irq number
|
||||
call cpp_irq_handler
|
||||
popaq
|
||||
popaq 24
|
||||
addq $16, %rsp
|
||||
iretq
|
||||
|
||||
.global asm_yield_handler
|
||||
asm_yield_handler:
|
||||
pushaq
|
||||
cld
|
||||
leaq 120(%rsp), %rdi # interrupt stack ptr
|
||||
movq %rsp, %rsi # interrupt register ptr
|
||||
call cpp_yield_handler
|
||||
popaq
|
||||
iretq
|
||||
|
||||
.global asm_ipi_handler
|
||||
asm_ipi_handler:
|
||||
pushaq
|
||||
pushaq 8
|
||||
cld
|
||||
call cpp_ipi_handler
|
||||
popaq
|
||||
popaq 8
|
||||
iretq
|
||||
|
||||
.global asm_timer_handler
|
||||
asm_timer_handler:
|
||||
pushaq
|
||||
pushaq 8
|
||||
cld
|
||||
call cpp_timer_handler
|
||||
popaq
|
||||
popaq 8
|
||||
iretq
|
||||
|
||||
.macro isr n
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <BAN/Vector.h>
|
||||
#include <kernel/ACPI/AML/Namespace.h>
|
||||
#include <kernel/ACPI/EmbeddedController.h>
|
||||
#include <kernel/ACPI/Headers.h>
|
||||
#include <kernel/Memory/Types.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
@@ -35,8 +36,12 @@ namespace Kernel::ACPI
|
||||
BAN::ErrorOr<void> poweroff();
|
||||
BAN::ErrorOr<void> reset();
|
||||
|
||||
BAN::ErrorOr<void> register_gpe_handler(uint8_t gpe, void (*callback)(void*), void* argument);
|
||||
|
||||
void handle_irq() override;
|
||||
|
||||
BAN::Span<BAN::UniqPtr<EmbeddedController>> embedded_controllers() { return m_embedded_controllers.span(); }
|
||||
|
||||
private:
|
||||
ACPI() = default;
|
||||
BAN::ErrorOr<void> initialize_impl();
|
||||
@@ -50,6 +55,12 @@ namespace Kernel::ACPI
|
||||
|
||||
BAN::ErrorOr<void> route_interrupt_link_device(const AML::Scope& device, uint64_t& routed_irq_mask);
|
||||
|
||||
BAN::ErrorOr<void> initialize_embedded_controller(const AML::Scope& embedded_controller);
|
||||
BAN::ErrorOr<void> initialize_embedded_controllers();
|
||||
|
||||
BAN::Optional<GAS> find_gpe_block(size_t index);
|
||||
bool enable_gpe(uint8_t gpe);
|
||||
|
||||
private:
|
||||
paddr_t m_header_table_paddr = 0;
|
||||
vaddr_t m_header_table_vaddr = 0;
|
||||
@@ -68,8 +79,23 @@ namespace Kernel::ACPI
|
||||
|
||||
ThreadBlocker m_event_thread_blocker;
|
||||
|
||||
BAN::Vector<BAN::UniqPtr<EmbeddedController>> m_embedded_controllers;
|
||||
|
||||
struct GPEHandler
|
||||
{
|
||||
bool has_callback { false };
|
||||
union {
|
||||
AML::Reference* method;
|
||||
struct
|
||||
{
|
||||
void (*callback)(void*);
|
||||
void* argument;
|
||||
};
|
||||
};
|
||||
};
|
||||
bool m_has_any_gpes { false };
|
||||
AML::Scope m_gpe_scope;
|
||||
BAN::Array<AML::Reference*, 0xFF> m_gpe_methods { nullptr };
|
||||
BAN::Array<GPEHandler, 0xFF> m_gpe_methods;
|
||||
|
||||
bool m_hardware_reduced { false };
|
||||
AML::Namespace* m_namespace { nullptr };
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace Kernel::ACPI::AML
|
||||
BAN::ErrorOr<void> for_each_child(const Scope&, const BAN::Function<BAN::Iteration(const Scope&, Reference*)>&);
|
||||
|
||||
BAN::ErrorOr<BAN::Vector<Scope>> find_device_with_eisa_id(BAN::StringView eisa_id);
|
||||
BAN::ErrorOr<BAN::Vector<Scope>> find_device_with_eisa_id(BAN::Span<BAN::StringView> eisa_ids);
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<Scope> resolve_path(const Scope& scope, const NameString& name_string);
|
||||
|
||||
@@ -89,6 +89,9 @@ namespace Kernel::ACPI::AML
|
||||
GAS::AddressSpaceID address_space;
|
||||
uint64_t offset;
|
||||
uint64_t length;
|
||||
alignas(Scope) uint8_t scope_storage[sizeof(Scope)];
|
||||
Scope& scope() { return *reinterpret_cast<Scope*>(scope_storage); }
|
||||
const Scope& scope() const { return *reinterpret_cast<const Scope*>(scope_storage); }
|
||||
};
|
||||
|
||||
struct FieldUnit
|
||||
|
||||
69
kernel/include/kernel/ACPI/EmbeddedController.h
Normal file
69
kernel/include/kernel/ACPI/EmbeddedController.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Atomic.h>
|
||||
#include <BAN/UniqPtr.h>
|
||||
|
||||
#include <kernel/ACPI/AML/Scope.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/Thread.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
class EmbeddedController
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<EmbeddedController>> create(AML::Scope&& scope, uint16_t command_port, uint16_t data_port, BAN::Optional<uint8_t> gpe);
|
||||
~EmbeddedController();
|
||||
|
||||
BAN::ErrorOr<uint8_t> read_byte(uint8_t offset);
|
||||
BAN::ErrorOr<void> write_byte(uint8_t offset, uint8_t value);
|
||||
|
||||
const AML::Scope& scope() const { return m_scope; }
|
||||
|
||||
private:
|
||||
EmbeddedController(AML::Scope&& scope, uint16_t command_port, uint16_t data_port, bool has_gpe)
|
||||
: m_scope(BAN::move(scope))
|
||||
, m_command_port(command_port)
|
||||
, m_data_port(data_port)
|
||||
, m_has_gpe(has_gpe)
|
||||
{ }
|
||||
|
||||
private:
|
||||
void wait_status_bit(uint8_t bit, uint8_t value);
|
||||
|
||||
uint8_t read_one(uint16_t port);
|
||||
void write_one(uint16_t port, uint8_t value);
|
||||
|
||||
static void handle_gpe_wrapper(void*);
|
||||
void handle_gpe();
|
||||
|
||||
BAN::ErrorOr<void> call_query_method(uint8_t notification);
|
||||
|
||||
void thread_task();
|
||||
|
||||
struct Command
|
||||
{
|
||||
uint8_t command;
|
||||
BAN::Optional<uint8_t> data1;
|
||||
BAN::Optional<uint8_t> data2;
|
||||
uint8_t* response;
|
||||
BAN::Atomic<bool> done;
|
||||
};
|
||||
BAN::ErrorOr<void> send_command(Command& command);
|
||||
|
||||
private:
|
||||
const AML::Scope m_scope;
|
||||
const uint16_t m_command_port;
|
||||
const uint16_t m_data_port;
|
||||
const bool m_has_gpe;
|
||||
|
||||
Mutex m_mutex;
|
||||
ThreadBlocker m_thread_blocker;
|
||||
|
||||
BAN::Optional<Command*> m_queued_command;
|
||||
|
||||
Thread* m_thread { nullptr };
|
||||
};
|
||||
|
||||
}
|
||||
179
kernel/include/kernel/ACPI/Resource.h
Normal file
179
kernel/include/kernel/ACPI/Resource.h
Normal file
@@ -0,0 +1,179 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/ByteSpan.h>
|
||||
#include <BAN/Debug.h>
|
||||
#include <BAN/Optional.h>
|
||||
|
||||
namespace Kernel::ACPI
|
||||
{
|
||||
|
||||
struct ResourceData
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
IRQ,
|
||||
DMA,
|
||||
IOPort,
|
||||
FixedIOPort,
|
||||
FixedDMA,
|
||||
|
||||
// TODO: large stuff the stuff :)
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint16_t irq_mask;
|
||||
union {
|
||||
struct {
|
||||
uint8_t edge_triggered : 1;
|
||||
uint8_t : 2;
|
||||
uint8_t active_low : 1;
|
||||
uint8_t shared : 1;
|
||||
uint8_t wake_capable : 1;
|
||||
uint8_t : 2;
|
||||
};
|
||||
uint8_t raw;
|
||||
};
|
||||
} irq;
|
||||
struct {
|
||||
uint8_t channel_mask;
|
||||
union {
|
||||
struct {
|
||||
uint8_t type : 2; // 0: 8 bit, 1: 8 and 16 bit, 2: 16 bit only
|
||||
uint8_t bus_master : 1;
|
||||
uint8_t : 2;
|
||||
uint8_t channel_speed : 2; // 0: compatibility, 1: type A, 2: type B, 3: type F
|
||||
uint8_t : 1;
|
||||
};
|
||||
uint8_t raw;
|
||||
};
|
||||
} dma;
|
||||
struct {
|
||||
uint16_t range_min_base;
|
||||
uint16_t range_max_base;
|
||||
uint8_t base_alignment;
|
||||
uint8_t range_length;
|
||||
} io_port;
|
||||
struct {
|
||||
uint16_t range_base;
|
||||
uint8_t range_length;
|
||||
} fixed_io_port;
|
||||
struct {
|
||||
uint16_t request_line;
|
||||
uint16_t channel;
|
||||
uint8_t transfer_width; // 0: 8 bit, 1: 16 bit, 2: 32 bit, 3: 64 bit, 4: 128 bit
|
||||
} fixed_dma;
|
||||
} as;
|
||||
Type type;
|
||||
};
|
||||
|
||||
class ResourceParser
|
||||
{
|
||||
public:
|
||||
ResourceParser(BAN::ConstByteSpan buffer)
|
||||
: m_buffer(buffer)
|
||||
{}
|
||||
|
||||
BAN::Optional<ResourceData> get_next()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (m_buffer.empty())
|
||||
return {};
|
||||
|
||||
if (m_buffer[0] & 0x80)
|
||||
{
|
||||
dprintln("Skipping large resource 0x{2H}", m_buffer[0] & 0x7F);
|
||||
const uint16_t length = (m_buffer[2] << 8) | m_buffer[1];
|
||||
if (m_buffer.size() < static_cast<size_t>(3 + length))
|
||||
return {};
|
||||
m_buffer = m_buffer.slice(3 + length);
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint8_t length = m_buffer[0] & 0x07;
|
||||
if (m_buffer.size() < static_cast<size_t>(1 + length))
|
||||
return {};
|
||||
|
||||
BAN::Optional<ResourceData> result;
|
||||
switch ((m_buffer[0] >> 3) & 0x0F)
|
||||
{
|
||||
case 0x04:
|
||||
if (length < 2)
|
||||
break;
|
||||
result = ResourceData {
|
||||
.as = { .irq = {
|
||||
.irq_mask = static_cast<uint16_t>((m_buffer[2] << 8) | m_buffer[1]),
|
||||
.raw = (length >= 3) ? m_buffer[3] : static_cast<uint8_t>(1),
|
||||
}},
|
||||
.type = ResourceData::Type::IRQ,
|
||||
};
|
||||
break;
|
||||
case 0x05:
|
||||
if (length < 2)
|
||||
break;
|
||||
result = ResourceData {
|
||||
.as = { .dma = {
|
||||
.channel_mask = m_buffer[1],
|
||||
.raw = m_buffer[2],
|
||||
}},
|
||||
.type = ResourceData::Type::DMA,
|
||||
};
|
||||
break;
|
||||
case 0x08:
|
||||
if (length < 7)
|
||||
break;
|
||||
result = ResourceData {
|
||||
.as = { .io_port = {
|
||||
.range_min_base = static_cast<uint16_t>(((m_buffer[3] << 8) | m_buffer[2]) & ((m_buffer[1] & 1) ? 0xFFFF : 0x03FF)),
|
||||
.range_max_base = static_cast<uint16_t>(((m_buffer[5] << 8) | m_buffer[4]) & ((m_buffer[1] & 1) ? 0xFFFF : 0x03FF)),
|
||||
.base_alignment = m_buffer[6],
|
||||
.range_length = m_buffer[7],
|
||||
}},
|
||||
.type = ResourceData::Type::IOPort,
|
||||
};
|
||||
break;
|
||||
case 0x09:
|
||||
if (length < 3)
|
||||
break;
|
||||
result = ResourceData {
|
||||
.as = { .fixed_io_port = {
|
||||
.range_base = static_cast<uint16_t>(((m_buffer[2] << 8) | m_buffer[1]) & 0x03FF),
|
||||
.range_length = m_buffer[3],
|
||||
}},
|
||||
.type = ResourceData::Type::FixedIOPort,
|
||||
};
|
||||
break;
|
||||
case 0x0A:
|
||||
if (length < 5)
|
||||
break;
|
||||
result = ResourceData {
|
||||
.as = { .fixed_dma = {
|
||||
.request_line = static_cast<uint16_t>((m_buffer[2] << 8) | m_buffer[1]),
|
||||
.channel = static_cast<uint16_t>((m_buffer[4] << 8) | m_buffer[3]),
|
||||
.transfer_width = m_buffer[5],
|
||||
}},
|
||||
.type = ResourceData::Type::FixedDMA,
|
||||
};
|
||||
break;
|
||||
case 0x0F:
|
||||
// End tag
|
||||
return {};
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x0E:
|
||||
dprintln("Skipping short resource 0x{2H}", (m_buffer[0] >> 3) & 0x0F);
|
||||
break;
|
||||
}
|
||||
|
||||
m_buffer = m_buffer.slice(1 + length);
|
||||
if (result.has_value())
|
||||
return result.release_value();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BAN::ConstByteSpan m_buffer;
|
||||
};
|
||||
|
||||
}
|
||||
37
kernel/include/kernel/API/SharedPage.h
Normal file
37
kernel/include/kernel/API/SharedPage.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Kernel::API
|
||||
{
|
||||
|
||||
enum SharedPageFeature : uint32_t
|
||||
{
|
||||
SPF_GETTIME = 1 << 0,
|
||||
};
|
||||
|
||||
struct SharedPage
|
||||
{
|
||||
uint8_t __sequence[0x100];
|
||||
|
||||
uint32_t features;
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t shift;
|
||||
uint64_t mult;
|
||||
uint64_t realtime_seconds;
|
||||
} gettime_shared;
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t seq;
|
||||
uint64_t last_ns;
|
||||
uint64_t last_tsc;
|
||||
} gettime_local;
|
||||
} cpus[];
|
||||
};
|
||||
|
||||
}
|
||||
44
kernel/include/kernel/API/Syscall.h
Normal file
44
kernel/include/kernel/API/Syscall.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Attributes.h>
|
||||
#include <kernel/IDT.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
ALWAYS_INLINE long syscall(int syscall, uintptr_t arg1 = 0, uintptr_t arg2 = 0, uintptr_t arg3 = 0, uintptr_t arg4 = 0, uintptr_t arg5 = 0)
|
||||
{
|
||||
long ret;
|
||||
#if ARCH(x86_64)
|
||||
register uintptr_t r10 asm("r10") = arg3;
|
||||
register uintptr_t r8 asm( "r8") = arg4;
|
||||
register uintptr_t r9 asm( "r9") = arg5;
|
||||
asm volatile(
|
||||
"syscall"
|
||||
: "=a"(ret)
|
||||
, "+D"(syscall)
|
||||
, "+S"(arg1)
|
||||
, "+d"(arg2)
|
||||
, "+r"(r10)
|
||||
, "+r"(r8)
|
||||
, "+r"(r9)
|
||||
:: "rcx", "r11", "memory");
|
||||
#elif ARCH(i686)
|
||||
asm volatile(
|
||||
"int %[irq]"
|
||||
: "=a"(ret)
|
||||
: [irq]"i"(static_cast<int>(IRQ_SYSCALL)) // WTF GCC 15
|
||||
, "a"(syscall)
|
||||
, "b"(arg1)
|
||||
, "c"(arg2)
|
||||
, "d"(arg3)
|
||||
, "S"(arg4)
|
||||
, "D"(arg5)
|
||||
: "memory");
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
59
kernel/include/kernel/Audio/AC97/Controller.h
Normal file
59
kernel/include/kernel/Audio/AC97/Controller.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Audio/Controller.h>
|
||||
#include <kernel/Memory/DMARegion.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class AC97AudioController final : public AudioController, public Interruptable
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<void> create(PCI::Device& pci_device);
|
||||
|
||||
void handle_irq() override;
|
||||
|
||||
protected:
|
||||
void handle_new_data() override;
|
||||
|
||||
uint32_t get_channels() const override { return 2; }
|
||||
uint32_t get_sample_rate() const override { return 48000; }
|
||||
|
||||
uint32_t get_total_pins() const override { return 1; }
|
||||
uint32_t get_current_pin() const override { return 0; }
|
||||
BAN::ErrorOr<void> set_current_pin(uint32_t pin) override { if (pin != 0) return BAN::Error::from_errno(EINVAL); return {}; }
|
||||
|
||||
BAN::ErrorOr<void> set_volume_mdB(int32_t) override;
|
||||
|
||||
private:
|
||||
AC97AudioController(PCI::Device& pci_device)
|
||||
: m_pci_device(pci_device)
|
||||
{ }
|
||||
|
||||
uint32_t get_volume_data() const;
|
||||
|
||||
BAN::ErrorOr<void> initialize();
|
||||
BAN::ErrorOr<void> initialize_bld();
|
||||
BAN::ErrorOr<void> initialize_interrupts();
|
||||
|
||||
bool queue_samples_to_bld();
|
||||
|
||||
private:
|
||||
static constexpr size_t m_bdl_entries = 32;
|
||||
static constexpr size_t m_samples_per_entry = 0x1000;
|
||||
|
||||
// We only store samples in 2 BDL entries at a time to reduce the amount of samples queued.
|
||||
// This is to reduce latency as you cannot remove data already passed to the BDLs
|
||||
static constexpr size_t m_used_bdl_entries = 2;
|
||||
|
||||
PCI::Device& m_pci_device;
|
||||
BAN::UniqPtr<PCI::BarRegion> m_mixer;
|
||||
BAN::UniqPtr<PCI::BarRegion> m_bus_master;
|
||||
|
||||
BAN::UniqPtr<DMARegion> m_bdl_region;
|
||||
|
||||
uint32_t m_bdl_tail { 0 };
|
||||
uint32_t m_bdl_head { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
15
kernel/include/kernel/Audio/AC97/Definitions.h
Normal file
15
kernel/include/kernel/Audio/AC97/Definitions.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Kernel::AC97
|
||||
{
|
||||
|
||||
struct BufferDescriptorListEntry
|
||||
{
|
||||
uint32_t address;
|
||||
uint16_t samples;
|
||||
uint16_t flags; // bit 14: last entry, bit 15: IOC
|
||||
};
|
||||
|
||||
}
|
||||
58
kernel/include/kernel/Audio/Controller.h
Normal file
58
kernel/include/kernel/Audio/Controller.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Device/Device.h>
|
||||
#include <kernel/Memory/ByteRingBuffer.h>
|
||||
#include <kernel/PCI.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class AudioController : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<void> create(PCI::Device& pci_device);
|
||||
|
||||
dev_t rdev() const override { return m_rdev; }
|
||||
BAN::StringView name() const override { return m_name; }
|
||||
|
||||
protected:
|
||||
AudioController();
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
virtual void handle_new_data() = 0;
|
||||
|
||||
virtual uint32_t get_channels() const = 0;
|
||||
virtual uint32_t get_sample_rate() const = 0;
|
||||
|
||||
virtual uint32_t get_total_pins() const = 0;
|
||||
virtual uint32_t get_current_pin() const = 0;
|
||||
virtual BAN::ErrorOr<void> set_current_pin(uint32_t) = 0;
|
||||
|
||||
virtual BAN::ErrorOr<void> set_volume_mdB(int32_t) = 0;
|
||||
|
||||
bool can_read_impl() const override { return false; }
|
||||
bool can_write_impl() const override { SpinLockGuard _(m_spinlock); return !m_sample_data->full(); }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hungup_impl() const override { return false; }
|
||||
|
||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
|
||||
BAN::ErrorOr<long> ioctl_impl(int cmd, void* arg) override;
|
||||
|
||||
protected:
|
||||
ThreadBlocker m_sample_data_blocker;
|
||||
mutable SpinLock m_spinlock;
|
||||
|
||||
static constexpr size_t m_sample_data_capacity = 1 << 20;
|
||||
BAN::UniqPtr<ByteRingBuffer> m_sample_data;
|
||||
|
||||
snd_volume_info m_volume_info {};
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
char m_name[10] {};
|
||||
};
|
||||
|
||||
}
|
||||
80
kernel/include/kernel/Audio/HDAudio/AudioFunctionGroup.h
Normal file
80
kernel/include/kernel/Audio/HDAudio/AudioFunctionGroup.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Audio/Controller.h>
|
||||
#include <kernel/Audio/HDAudio/Controller.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class HDAudioController;
|
||||
|
||||
class HDAudioFunctionGroup final : public AudioController
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<HDAudioFunctionGroup>> create(BAN::RefPtr<HDAudioController>, uint8_t cid, HDAudio::AFGNode&&);
|
||||
|
||||
void on_stream_interrupt(uint8_t stream_index);
|
||||
|
||||
protected:
|
||||
// FIXME: allow setting these :D
|
||||
uint32_t get_channels() const override { return 2; }
|
||||
uint32_t get_sample_rate() const override { return 48000; }
|
||||
|
||||
uint32_t get_total_pins() const override;
|
||||
uint32_t get_current_pin() const override;
|
||||
BAN::ErrorOr<void> set_current_pin(uint32_t) override;
|
||||
|
||||
BAN::ErrorOr<void> set_volume_mdB(int32_t) override;
|
||||
|
||||
void handle_new_data() override;
|
||||
|
||||
private:
|
||||
HDAudioFunctionGroup(BAN::RefPtr<HDAudioController> controller, uint8_t cid, HDAudio::AFGNode&& afg_node)
|
||||
: m_controller(controller)
|
||||
, m_afg_node(BAN::move(afg_node))
|
||||
, m_cid(cid)
|
||||
{ }
|
||||
~HDAudioFunctionGroup();
|
||||
|
||||
BAN::ErrorOr<void> initialize();
|
||||
BAN::ErrorOr<void> initialize_stream();
|
||||
BAN::ErrorOr<void> initialize_output();
|
||||
|
||||
BAN::ErrorOr<void> enable_output_path(uint8_t index);
|
||||
BAN::ErrorOr<void> disable_output_path(uint8_t index);
|
||||
|
||||
void reset_stream();
|
||||
|
||||
BAN::ErrorOr<void> recurse_output_paths(const HDAudio::AFGWidget& widget, BAN::Vector<const HDAudio::AFGWidget*>& path);
|
||||
|
||||
uint16_t get_format_data() const;
|
||||
|
||||
size_t bdl_offset() const;
|
||||
|
||||
void queue_bdl_data();
|
||||
|
||||
private:
|
||||
// use 6 512 sample BDL entries
|
||||
// each entry is ~10.7 ms at 48 kHz
|
||||
// -> total buffered audio is 64 ms
|
||||
static constexpr size_t m_bdl_entry_sample_frames = 512;
|
||||
static constexpr size_t m_bdl_entry_count = 6;
|
||||
|
||||
BAN::RefPtr<HDAudioController> m_controller;
|
||||
const HDAudio::AFGNode m_afg_node;
|
||||
const uint8_t m_cid;
|
||||
|
||||
BAN::Vector<BAN::Vector<const HDAudio::AFGWidget*>> m_output_paths;
|
||||
BAN::Vector<const HDAudio::AFGWidget*> m_output_pins;
|
||||
size_t m_output_path_index { SIZE_MAX };
|
||||
|
||||
uint8_t m_stream_id { 0xFF };
|
||||
uint8_t m_stream_index { 0xFF };
|
||||
BAN::UniqPtr<DMARegion> m_bdl_region;
|
||||
|
||||
size_t m_bdl_head { 0 };
|
||||
size_t m_bdl_tail { 0 };
|
||||
bool m_stream_running { false };
|
||||
};
|
||||
|
||||
}
|
||||
77
kernel/include/kernel/Audio/HDAudio/Controller.h
Normal file
77
kernel/include/kernel/Audio/HDAudio/Controller.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Audio/Controller.h>
|
||||
#include <kernel/Audio/HDAudio/Definitions.h>
|
||||
#include <kernel/Memory/DMARegion.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class HDAudioController : public Interruptable, public BAN::RefCounted<HDAudioController>
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<void> create(PCI::Device& pci_device);
|
||||
|
||||
BAN::ErrorOr<uint32_t> send_command(HDAudio::CORBEntry);
|
||||
|
||||
uint8_t get_stream_index(HDAudio::StreamType type, uint8_t index) const;
|
||||
|
||||
BAN::ErrorOr<uint8_t> allocate_stream_id();
|
||||
void deallocate_stream_id(uint8_t id);
|
||||
|
||||
BAN::ErrorOr<uint8_t> allocate_stream(HDAudio::StreamType type, void* afg);
|
||||
void deallocate_stream(uint8_t index);
|
||||
|
||||
PCI::BarRegion& bar0() { return *m_bar0; }
|
||||
|
||||
bool is_64bit() const { return m_is64bit; }
|
||||
|
||||
void handle_irq() override;
|
||||
|
||||
private:
|
||||
HDAudioController(PCI::Device& pci_device)
|
||||
: m_pci_device(pci_device)
|
||||
{ }
|
||||
|
||||
BAN::ErrorOr<void> initialize();
|
||||
BAN::ErrorOr<void> initialize_ring_buffers();
|
||||
|
||||
BAN::ErrorOr<void> reset_controller();
|
||||
|
||||
BAN::ErrorOr<HDAudio::Codec> initialize_codec(uint8_t codec);
|
||||
BAN::ErrorOr<HDAudio::AFGNode> initialize_node(uint8_t codec, uint8_t node);
|
||||
BAN::ErrorOr<HDAudio::AFGWidget> initialize_widget(uint8_t codec, uint8_t node);
|
||||
|
||||
private:
|
||||
struct RingBuffer
|
||||
{
|
||||
vaddr_t vaddr;
|
||||
uint32_t index;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
private:
|
||||
PCI::Device& m_pci_device;
|
||||
BAN::UniqPtr<PCI::BarRegion> m_bar0;
|
||||
bool m_is64bit { false };
|
||||
|
||||
bool m_use_immediate_command { false };
|
||||
|
||||
uint8_t m_output_streams { 0 };
|
||||
uint8_t m_input_streams { 0 };
|
||||
uint8_t m_bidir_streams { 0 };
|
||||
void* m_allocated_streams[30] {};
|
||||
|
||||
// NOTE: stream ids are from 1 to 15
|
||||
uint16_t m_allocated_stream_ids { 0 };
|
||||
|
||||
Mutex m_command_mutex;
|
||||
SpinLock m_rb_lock;
|
||||
ThreadBlocker m_rb_blocker;
|
||||
|
||||
RingBuffer m_corb;
|
||||
RingBuffer m_rirb;
|
||||
BAN::UniqPtr<DMARegion> m_ring_buffer_region;
|
||||
};
|
||||
|
||||
}
|
||||
90
kernel/include/kernel/Audio/HDAudio/Definitions.h
Normal file
90
kernel/include/kernel/Audio/HDAudio/Definitions.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Vector.h>
|
||||
|
||||
namespace Kernel::HDAudio
|
||||
{
|
||||
|
||||
struct CORBEntry
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
uint32_t data : 8;
|
||||
uint32_t command : 12;
|
||||
uint32_t node_index : 8;
|
||||
uint32_t codec_address : 4;
|
||||
};
|
||||
uint32_t raw;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(CORBEntry) == sizeof(uint32_t));
|
||||
|
||||
struct BDLEntry
|
||||
{
|
||||
paddr_t address;
|
||||
uint32_t length;
|
||||
uint32_t ioc;
|
||||
};
|
||||
static_assert(sizeof(BDLEntry) == 16);
|
||||
|
||||
struct AFGWidget
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
OutputConverter,
|
||||
InputConverter,
|
||||
Mixer,
|
||||
Selector,
|
||||
PinComplex,
|
||||
Power,
|
||||
VolumeKnob,
|
||||
BeepGenerator,
|
||||
};
|
||||
|
||||
Type type;
|
||||
uint8_t id;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
bool input;
|
||||
bool output;
|
||||
bool display; // HDMI or DP
|
||||
uint32_t config;
|
||||
} pin_complex;
|
||||
};
|
||||
|
||||
struct Amplifier
|
||||
{
|
||||
uint8_t offset;
|
||||
uint8_t num_steps;
|
||||
uint8_t step_size;
|
||||
bool mute;
|
||||
};
|
||||
|
||||
BAN::Optional<Amplifier> output_amplifier;
|
||||
|
||||
BAN::Vector<uint16_t> connections;
|
||||
};
|
||||
|
||||
struct AFGNode
|
||||
{
|
||||
uint8_t id;
|
||||
BAN::Vector<AFGWidget> widgets;
|
||||
};
|
||||
|
||||
struct Codec
|
||||
{
|
||||
uint8_t id;
|
||||
BAN::Vector<AFGNode> nodes;
|
||||
};
|
||||
|
||||
enum class StreamType
|
||||
{
|
||||
Input,
|
||||
Output,
|
||||
Bidirectional,
|
||||
};
|
||||
|
||||
}
|
||||
50
kernel/include/kernel/Audio/HDAudio/Registers.h
Normal file
50
kernel/include/kernel/Audio/HDAudio/Registers.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Kernel::HDAudio
|
||||
{
|
||||
|
||||
enum Regs : uint8_t
|
||||
{
|
||||
GCAP = 0x00,
|
||||
VMIN = 0x02,
|
||||
VMAJ = 0x03,
|
||||
GCTL = 0x08,
|
||||
STATESTS = 0x0E,
|
||||
|
||||
INTCTL = 0x20,
|
||||
INTSTS = 0x24,
|
||||
|
||||
CORBLBASE = 0x40,
|
||||
CORBUBASE = 0x44,
|
||||
CORBWP = 0x48,
|
||||
CORBRP = 0x4A,
|
||||
CORBCTL = 0x4C,
|
||||
CORBSTS = 0x4D,
|
||||
CORBSIZE = 0x4E,
|
||||
|
||||
RIRBLBASE = 0x50,
|
||||
RIRBUBASE = 0x54,
|
||||
RIRBWP = 0x58,
|
||||
RINTCNT = 0x5A,
|
||||
RIRBCTL = 0x5C,
|
||||
RIRBSTS = 0x5D,
|
||||
RIRBSIZE = 0x5E,
|
||||
|
||||
ICOI = 0x60,
|
||||
ICII = 0x64,
|
||||
ICIS = 0x68,
|
||||
|
||||
SDCTL = 0x00,
|
||||
SDSTS = 0x03,
|
||||
SDLPIB = 0x04,
|
||||
SDCBL = 0x08,
|
||||
SDLVI = 0x0C,
|
||||
SDFIFOD = 0x10,
|
||||
SDFMT = 0x12,
|
||||
SDBDPL = 0x18,
|
||||
SDBDPU = 0x1C,
|
||||
};
|
||||
|
||||
}
|
||||
@@ -41,6 +41,12 @@ namespace Kernel
|
||||
Type type;
|
||||
};
|
||||
|
||||
struct BootModule
|
||||
{
|
||||
paddr_t start;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct BootInfo
|
||||
{
|
||||
BAN::String command_line;
|
||||
@@ -48,6 +54,7 @@ namespace Kernel
|
||||
RSDP rsdp {};
|
||||
paddr_t kernel_paddr {};
|
||||
|
||||
BAN::Vector<BootModule> modules;
|
||||
BAN::Vector<MemoryMapEntry> memory_map_entries;
|
||||
};
|
||||
|
||||
|
||||
@@ -81,5 +81,6 @@ namespace CPUID
|
||||
bool has_pge();
|
||||
bool has_pat();
|
||||
bool has_1gib_pages();
|
||||
bool has_invariant_tsc();
|
||||
|
||||
}
|
||||
|
||||
@@ -35,10 +35,8 @@ namespace Kernel
|
||||
|
||||
bool has_egid(gid_t) const;
|
||||
|
||||
BAN::ErrorOr<void> initialize_supplementary_groups();
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<BAN::String> find_username() const;
|
||||
BAN::Span<const gid_t> groups() const { return m_supplementary.span(); }
|
||||
BAN::ErrorOr<void> set_groups(BAN::Span<const gid_t> groups);
|
||||
|
||||
private:
|
||||
uid_t m_ruid, m_euid, m_suid;
|
||||
|
||||
@@ -70,10 +70,15 @@
|
||||
#define DEBUG_USB_MOUSE 0
|
||||
#define DEBUG_USB_MASS_STORAGE 0
|
||||
|
||||
#define DEBUG_HDAUDIO 0
|
||||
|
||||
|
||||
namespace Debug
|
||||
{
|
||||
void dump_stack_trace();
|
||||
void dump_stack_trace(uintptr_t ip, uintptr_t bp);
|
||||
void dump_qr_code();
|
||||
|
||||
void putchar(char);
|
||||
void print_prefix(const char*, int);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class DebugDevice : public CharacterDevice
|
||||
class DebugDevice final : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<DebugDevice>> create(mode_t, uid_t, gid_t);
|
||||
@@ -24,6 +24,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
@@ -16,7 +16,11 @@ namespace Kernel
|
||||
virtual bool is_partition() const { return false; }
|
||||
virtual bool is_storage_device() const { return false; }
|
||||
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) { (void)offset; (void)len; return BAN::Error::from_errno(EINVAL); }
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t, int status_flags)
|
||||
{
|
||||
(void)offset; (void)len; (void)status_flags;
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
virtual dev_t rdev() const override = 0;
|
||||
|
||||
|
||||
@@ -16,11 +16,14 @@ namespace Kernel
|
||||
Debug,
|
||||
Keyboard,
|
||||
Mouse,
|
||||
Joystick,
|
||||
SCSI,
|
||||
NVMeController,
|
||||
NVMeNamespace,
|
||||
Ethernet,
|
||||
Loopback,
|
||||
TmpFS,
|
||||
AudioController,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Kernel
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<FramebufferDevice>> create_from_boot_framebuffer();
|
||||
static BAN::RefPtr<FramebufferDevice> boot_framebuffer();
|
||||
~FramebufferDevice();
|
||||
|
||||
uint32_t width() const { return m_width; }
|
||||
@@ -17,6 +18,7 @@ namespace Kernel
|
||||
|
||||
uint32_t get_pixel(uint32_t x, uint32_t y) const;
|
||||
void set_pixel(uint32_t x, uint32_t y, uint32_t rgb);
|
||||
void fill(uint32_t rgb);
|
||||
|
||||
// positive rows -> empty pixels on bottom
|
||||
// negative rows -> empty pixels on top
|
||||
@@ -26,7 +28,7 @@ namespace Kernel
|
||||
void sync_pixels_linear(uint32_t first_pixel, uint32_t pixel_count);
|
||||
void sync_pixels_rectangle(uint32_t top_right_x, uint32_t top_right_y, uint32_t width, uint32_t height);
|
||||
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) override;
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t, int status_flags) override;
|
||||
|
||||
virtual dev_t rdev() const override { return m_rdev; }
|
||||
virtual BAN::StringView name() const override { return m_name.sv(); }
|
||||
@@ -38,6 +40,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
FramebufferDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev, paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class NullDevice : public CharacterDevice
|
||||
class NullDevice final : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<NullDevice>> create(mode_t, uid_t, gid_t);
|
||||
@@ -26,6 +26,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class RandomDevice : public CharacterDevice
|
||||
class RandomDevice final : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<RandomDevice>> create(mode_t, uid_t, gid_t);
|
||||
@@ -24,6 +24,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class ZeroDevice : public CharacterDevice
|
||||
class ZeroDevice final : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ZeroDevice>> create(mode_t, uid_t, gid_t);
|
||||
@@ -24,6 +24,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
@@ -20,6 +20,6 @@ namespace Kernel::ELF
|
||||
BAN::Vector<BAN::UniqPtr<MemoryRegion>> regions;
|
||||
};
|
||||
|
||||
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode>, const Credentials&, PageTable&);
|
||||
BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> root, BAN::RefPtr<Inode> inode, const Credentials&, PageTable&);
|
||||
|
||||
}
|
||||
|
||||
109
kernel/include/kernel/Epoll.h
Normal file
109
kernel/include/kernel/Epoll.h
Normal file
@@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Array.h>
|
||||
#include <BAN/CircularQueue.h>
|
||||
#include <BAN/HashMap.h>
|
||||
#include <BAN/HashSet.h>
|
||||
#include <kernel/FS/Inode.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class Epoll final : public Inode
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<Epoll>> create();
|
||||
~Epoll();
|
||||
|
||||
BAN::ErrorOr<void> ctl(int op, int fd, BAN::RefPtr<Inode> inode, epoll_event event);
|
||||
BAN::ErrorOr<size_t> wait(BAN::Span<epoll_event> events, uint64_t waketime_ns);
|
||||
|
||||
void notify(BAN::RefPtr<Inode> inode, uint32_t event);
|
||||
|
||||
private:
|
||||
Epoll() = default;
|
||||
|
||||
public:
|
||||
ino_t ino() const override { return 0; }
|
||||
Mode mode() const override { return { Mode::IRUSR | Mode::IWUSR }; }
|
||||
nlink_t nlink() const override { return 0; }
|
||||
uid_t uid() const override { return 0; }
|
||||
gid_t gid() const override { return 0; }
|
||||
off_t size() const override { return 0; }
|
||||
timespec atime() const override { return {}; }
|
||||
timespec mtime() const override { return {}; }
|
||||
timespec ctime() const override { return {}; }
|
||||
blksize_t blksize() const override { return PAGE_SIZE; }
|
||||
blkcnt_t blocks() const override { return 0; }
|
||||
dev_t dev() const override { return 0; }
|
||||
dev_t rdev() const override { return 0; }
|
||||
|
||||
bool is_epoll() const override { return true; }
|
||||
|
||||
const FileSystem* filesystem() const override { return nullptr; }
|
||||
|
||||
bool can_read_impl() const override { return false; }
|
||||
bool can_write_impl() const override { return false; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hungup_impl() const override { return false; }
|
||||
|
||||
BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
||||
|
||||
private:
|
||||
struct InodeRefPtrHash
|
||||
{
|
||||
BAN::hash_t operator()(const BAN::RefPtr<Inode>& inode)
|
||||
{
|
||||
return BAN::hash<const Inode*>()(inode.ptr());
|
||||
}
|
||||
};
|
||||
|
||||
struct ListenEventList
|
||||
{
|
||||
BAN::Array<epoll_event, OPEN_MAX> events;
|
||||
uint32_t bitmap[(OPEN_MAX + 31) / 32] {};
|
||||
|
||||
bool has_fd(int fd) const
|
||||
{
|
||||
// For some reason having (fd < 0 || ...) makes GCC 15.1.0
|
||||
// think bitmap access can be out of bounds...
|
||||
if (static_cast<size_t>(fd) >= events.size())
|
||||
return false;
|
||||
return bitmap[fd / 32] & (1u << (fd % 32));
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
for (auto val : bitmap)
|
||||
if (val != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void add_fd(int fd, epoll_event event)
|
||||
{
|
||||
ASSERT(!has_fd(fd));
|
||||
bitmap[fd / 32] |= (1u << (fd % 32));
|
||||
events[fd] = event;
|
||||
}
|
||||
|
||||
void remove_fd(int fd)
|
||||
{
|
||||
ASSERT(has_fd(fd));
|
||||
bitmap[fd / 32] &= ~(1u << (fd % 32));
|
||||
events[fd] = {};
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
ThreadBlocker m_thread_blocker;
|
||||
SpinLock m_ready_lock;
|
||||
BAN::HashMap<BAN::RefPtr<Inode>, uint32_t, InodeRefPtrHash> m_ready_events;
|
||||
BAN::HashMap<BAN::RefPtr<Inode>, uint32_t, InodeRefPtrHash> m_processing_events;
|
||||
BAN::HashMap<BAN::RefPtr<Inode>, ListenEventList, InodeRefPtrHash> m_listening_events;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -22,6 +22,7 @@ namespace Kernel
|
||||
|
||||
void add_inode(BAN::StringView path, BAN::RefPtr<TmpInode>);
|
||||
|
||||
void initiate_disk_cache_drop();
|
||||
void initiate_sync(bool should_block);
|
||||
|
||||
private:
|
||||
@@ -37,6 +38,10 @@ namespace Kernel
|
||||
ThreadBlocker m_sync_done;
|
||||
ThreadBlocker m_sync_thread_blocker;
|
||||
volatile bool m_should_sync { false };
|
||||
|
||||
SpinLock m_disk_cache_lock;
|
||||
ThreadBlocker m_disk_cache_thread_blocker;
|
||||
BAN::Atomic<bool> m_should_drop_disk_cache { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
52
kernel/include/kernel/FS/EventFD.h
Normal file
52
kernel/include/kernel/FS/EventFD.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/FS/Inode.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class EventFD final : public Inode
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(uint64_t initval, bool semaphore);
|
||||
|
||||
ino_t ino() const override { return 0; }
|
||||
Mode mode() const override { return { Mode::IFCHR | Mode::IRUSR | Mode::IWUSR }; }
|
||||
nlink_t nlink() const override { return ref_count(); }
|
||||
uid_t uid() const override { return 0; }
|
||||
gid_t gid() const override { return 0; }
|
||||
off_t size() const override { return 0; }
|
||||
timespec atime() const override { return {}; }
|
||||
timespec mtime() const override { return {}; }
|
||||
timespec ctime() const override { return {}; }
|
||||
blksize_t blksize() const override { return 8; }
|
||||
blkcnt_t blocks() const override { return 0; }
|
||||
dev_t dev() const override { return 0; }
|
||||
dev_t rdev() const override { return 0; }
|
||||
|
||||
const FileSystem* filesystem() const override { return nullptr; }
|
||||
|
||||
protected:
|
||||
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
||||
|
||||
bool can_read_impl() const override { return m_value > 0; }
|
||||
bool can_write_impl() const override { return m_value < UINT64_MAX - 1; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
EventFD(uint64_t initval, bool is_semaphore)
|
||||
: m_is_semaphore(is_semaphore)
|
||||
, m_value(initval)
|
||||
{ }
|
||||
|
||||
private:
|
||||
const bool m_is_semaphore;
|
||||
uint64_t m_value;
|
||||
|
||||
ThreadBlocker m_thread_blocker;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -26,18 +26,32 @@ namespace Kernel
|
||||
class BlockBufferWrapper
|
||||
{
|
||||
BAN_NON_COPYABLE(BlockBufferWrapper);
|
||||
BAN_NON_MOVABLE(BlockBufferWrapper);
|
||||
|
||||
public:
|
||||
BlockBufferWrapper(BAN::Span<uint8_t> buffer, bool& used)
|
||||
BlockBufferWrapper(BAN::Span<uint8_t> buffer, void (*callback)(void*, const uint8_t*), void* argument)
|
||||
: m_buffer(buffer)
|
||||
, m_used(used)
|
||||
{
|
||||
ASSERT(m_used);
|
||||
}
|
||||
, m_callback(callback)
|
||||
, m_argument(argument)
|
||||
{ }
|
||||
BlockBufferWrapper(BlockBufferWrapper&& other) { *this = BAN::move(other); }
|
||||
~BlockBufferWrapper()
|
||||
{
|
||||
m_used = false;
|
||||
if (m_callback == nullptr)
|
||||
return;
|
||||
m_callback(m_argument, m_buffer.data());
|
||||
}
|
||||
|
||||
BlockBufferWrapper& operator=(BlockBufferWrapper&& other)
|
||||
{
|
||||
this->m_buffer = other.m_buffer;
|
||||
this->m_callback = other.m_callback;
|
||||
this->m_argument = other.m_argument;
|
||||
|
||||
other.m_buffer = {};
|
||||
other.m_callback = nullptr;
|
||||
other.m_argument = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t size() const { return m_buffer.size(); }
|
||||
@@ -53,7 +67,8 @@ namespace Kernel
|
||||
|
||||
private:
|
||||
BAN::Span<uint8_t> m_buffer;
|
||||
bool& m_used;
|
||||
void (*m_callback)(void*, const uint8_t*);
|
||||
void* m_argument;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -62,8 +77,6 @@ namespace Kernel
|
||||
|
||||
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
||||
|
||||
virtual dev_t dev() const override { return m_block_device->rdev(); };
|
||||
|
||||
private:
|
||||
Ext2FS(BAN::RefPtr<BlockDevice> block_device)
|
||||
: m_block_device(block_device)
|
||||
@@ -81,7 +94,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<void> sync_superblock();
|
||||
BAN::ErrorOr<void> sync_block(uint32_t block);
|
||||
|
||||
BlockBufferWrapper get_block_buffer();
|
||||
BAN::ErrorOr<BlockBufferWrapper> get_block_buffer();
|
||||
|
||||
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
|
||||
BAN::ErrorOr<void> release_block(uint32_t block);
|
||||
@@ -104,10 +117,13 @@ namespace Kernel
|
||||
{
|
||||
public:
|
||||
BlockBufferManager() = default;
|
||||
BlockBufferWrapper get_buffer();
|
||||
BAN::ErrorOr<BlockBufferWrapper> get_buffer();
|
||||
|
||||
BAN::ErrorOr<void> initialize(size_t block_size);
|
||||
|
||||
private:
|
||||
void destroy_callback(const uint8_t* buffer_ptr);
|
||||
|
||||
private:
|
||||
struct BlockBuffer
|
||||
{
|
||||
@@ -115,8 +131,20 @@ namespace Kernel
|
||||
bool used { false };
|
||||
};
|
||||
|
||||
struct ThreadInfo
|
||||
{
|
||||
pid_t tid { 0 };
|
||||
size_t buffers { 0 };
|
||||
};
|
||||
|
||||
private:
|
||||
BAN::Array<BlockBuffer, 10> m_buffers;
|
||||
static constexpr size_t max_threads = 8;
|
||||
static constexpr size_t max_buffers_per_thread = 6;
|
||||
|
||||
Mutex m_buffer_mutex;
|
||||
ThreadBlocker m_buffer_blocker;
|
||||
BAN::Array<BlockBuffer, max_threads * max_buffers_per_thread> m_buffers;
|
||||
BAN::Array<ThreadInfo, max_threads> m_thread_infos;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override;
|
||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override;
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
|
||||
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||
@@ -46,29 +47,32 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) override;
|
||||
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
|
||||
virtual BAN::ErrorOr<void> fsync_impl() override;
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
// Returns maximum number of data blocks in use
|
||||
// NOTE: the inode might have more blocks than what this suggests if it has been shrinked
|
||||
uint32_t max_used_data_block_count() const { return size() / blksize(); }
|
||||
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block(uint32_t block, uint32_t index, uint32_t depth);
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index(uint32_t data_block_index);
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block(uint32_t& block, uint32_t index, uint32_t depth, bool allocate);
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index(uint32_t data_block_index, bool allocate);
|
||||
|
||||
BAN::ErrorOr<void> link_inode_to_directory(Ext2Inode&, BAN::StringView name);
|
||||
BAN::ErrorOr<void> remove_inode_from_directory(BAN::StringView name, bool cleanup_directory);
|
||||
BAN::ErrorOr<bool> is_directory_empty();
|
||||
|
||||
BAN::ErrorOr<void> cleanup_indirect_block(uint32_t block, uint32_t depth);
|
||||
BAN::ErrorOr<void> cleanup_default_links();
|
||||
BAN::ErrorOr<void> cleanup_data_blocks();
|
||||
BAN::ErrorOr<void> cleanup_from_fs();
|
||||
|
||||
BAN::ErrorOr<uint32_t> allocate_new_block_to_indirect_block(uint32_t& block, uint32_t index, uint32_t depth);
|
||||
BAN::ErrorOr<uint32_t> allocate_new_block(uint32_t data_block_index);
|
||||
BAN::ErrorOr<void> sync();
|
||||
|
||||
uint32_t block_group() const;
|
||||
@@ -81,6 +85,26 @@ namespace Kernel
|
||||
{}
|
||||
static BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> create(Ext2FS&, uint32_t);
|
||||
|
||||
private:
|
||||
struct ScopedSync
|
||||
{
|
||||
ScopedSync(Ext2Inode& inode)
|
||||
: inode(inode)
|
||||
, inode_info(inode.m_inode)
|
||||
{ }
|
||||
|
||||
~ScopedSync()
|
||||
{
|
||||
if (memcmp(&inode.m_inode, &inode_info, sizeof(Ext2::Inode)) == 0)
|
||||
return;
|
||||
if (auto ret = inode.sync(); ret.is_error())
|
||||
dwarnln("failed to sync inode: {}", ret.error());
|
||||
}
|
||||
|
||||
Ext2Inode& inode;
|
||||
Ext2::Inode inode_info;
|
||||
};
|
||||
|
||||
private:
|
||||
Ext2FS& m_fs;
|
||||
Ext2::Inode m_inode;
|
||||
|
||||
@@ -37,8 +37,6 @@ namespace Kernel
|
||||
|
||||
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
||||
|
||||
virtual dev_t dev() const override { return m_block_device->rdev(); };
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<FATInode>> open_inode(BAN::RefPtr<FATInode> parent, const FAT::DirectoryEntry& entry, uint32_t cluster_index, uint32_t entry_index);
|
||||
BAN::ErrorOr<void> inode_read_cluster(BAN::RefPtr<FATInode>, size_t index, BAN::ByteSpan buffer);
|
||||
blksize_t inode_block_size(BAN::RefPtr<const FATInode>) const;
|
||||
|
||||
@@ -44,11 +44,13 @@ namespace Kernel
|
||||
//virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
//virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||
//virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
//virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
|
||||
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
FATInode(FATFS& fs, const FAT::DirectoryEntry& entry, ino_t ino, uint32_t block_count)
|
||||
|
||||
@@ -26,8 +26,6 @@ namespace Kernel
|
||||
static BAN::ErrorOr<BAN::RefPtr<FileSystem>> from_block_device(BAN::RefPtr<BlockDevice>);
|
||||
|
||||
virtual BAN::RefPtr<Inode> root_inode() = 0;
|
||||
|
||||
virtual dev_t dev() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/ByteSpan.h>
|
||||
#include <BAN/LinkedList.h>
|
||||
#include <BAN/RefPtr.h>
|
||||
#include <BAN/String.h>
|
||||
#include <BAN/StringView.h>
|
||||
@@ -19,10 +20,9 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class FileSystem;
|
||||
|
||||
class FileBackedRegion;
|
||||
class SharedFileData;
|
||||
class FileSystem;
|
||||
struct SharedFileData;
|
||||
|
||||
class Inode : public BAN::RefCounted<Inode>
|
||||
{
|
||||
@@ -85,6 +85,7 @@ namespace Kernel
|
||||
virtual dev_t rdev() const = 0;
|
||||
|
||||
virtual bool is_device() const { return false; }
|
||||
virtual bool is_epoll() const { return false; }
|
||||
virtual bool is_pipe() const { return false; }
|
||||
virtual bool is_tty() const { return false; }
|
||||
|
||||
@@ -96,6 +97,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t);
|
||||
BAN::ErrorOr<void> create_directory(BAN::StringView, mode_t, uid_t, gid_t);
|
||||
BAN::ErrorOr<void> link_inode(BAN::StringView, BAN::RefPtr<Inode>);
|
||||
BAN::ErrorOr<void> rename_inode(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView);
|
||||
BAN::ErrorOr<void> unlink(BAN::StringView);
|
||||
|
||||
// Link API
|
||||
@@ -107,9 +109,12 @@ namespace Kernel
|
||||
BAN::ErrorOr<void> bind(const sockaddr* address, socklen_t address_len);
|
||||
BAN::ErrorOr<void> connect(const sockaddr* address, socklen_t address_len);
|
||||
BAN::ErrorOr<void> listen(int backlog);
|
||||
BAN::ErrorOr<size_t> sendto(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len);
|
||||
BAN::ErrorOr<size_t> recvfrom(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len);
|
||||
BAN::ErrorOr<size_t> sendmsg(const msghdr& message, int flags);
|
||||
BAN::ErrorOr<size_t> recvmsg(msghdr& message, int flags);
|
||||
BAN::ErrorOr<void> getsockname(sockaddr* address, socklen_t* address_len);
|
||||
BAN::ErrorOr<void> getpeername(sockaddr* address, socklen_t* address_len);
|
||||
BAN::ErrorOr<void> getsockopt(int level, int option, void* value, socklen_t* value_len);
|
||||
BAN::ErrorOr<void> setsockopt(int level, int option, const void* value, socklen_t value_len);
|
||||
|
||||
// General API
|
||||
BAN::ErrorOr<size_t> read(off_t, BAN::ByteSpan buffer);
|
||||
@@ -117,23 +122,33 @@ namespace Kernel
|
||||
BAN::ErrorOr<void> truncate(size_t);
|
||||
BAN::ErrorOr<void> chmod(mode_t);
|
||||
BAN::ErrorOr<void> chown(uid_t, gid_t);
|
||||
BAN::ErrorOr<void> utimens(const timespec[2]);
|
||||
BAN::ErrorOr<void> fsync();
|
||||
|
||||
// Select/Non blocking API
|
||||
bool can_read() const;
|
||||
bool can_write() const;
|
||||
bool has_error() const;
|
||||
bool has_hungup() const;
|
||||
|
||||
BAN::ErrorOr<long> ioctl(int request, void* arg);
|
||||
|
||||
BAN::ErrorOr<void> add_epoll(class Epoll*);
|
||||
void del_epoll(class Epoll*);
|
||||
void epoll_notify(uint32_t event);
|
||||
|
||||
virtual void on_close(int status_flags) { (void)status_flags; }
|
||||
virtual void on_clone(int status_flags) { (void)status_flags; }
|
||||
|
||||
protected:
|
||||
// Directory API
|
||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
// Link API
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
|
||||
@@ -144,9 +159,12 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> listen_impl(int) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr&, int) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr&, int) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> getsockname_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
// General API
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
@@ -154,12 +172,14 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> fsync_impl() = 0;
|
||||
|
||||
// Select/Non blocking API
|
||||
virtual bool can_read_impl() const = 0;
|
||||
virtual bool can_write_impl() const = 0;
|
||||
virtual bool has_error_impl() const = 0;
|
||||
virtual bool has_hungup_impl() const = 0;
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int, void*) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
@@ -168,9 +188,12 @@ namespace Kernel
|
||||
|
||||
private:
|
||||
BAN::WeakPtr<SharedFileData> m_shared_region;
|
||||
SpinLock m_epoll_lock;
|
||||
BAN::LinkedList<class Epoll*> m_epolls;
|
||||
friend class Epoll;
|
||||
friend class FileBackedRegion;
|
||||
friend class OpenFileDescriptorSet;
|
||||
friend class SharedFileData;
|
||||
friend struct SharedFileData;
|
||||
friend class TTY;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <BAN/Array.h>
|
||||
#include <kernel/FS/Inode.h>
|
||||
#include <kernel/Memory/ByteRingBuffer.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
|
||||
namespace Kernel
|
||||
@@ -13,8 +14,9 @@ namespace Kernel
|
||||
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(const Credentials&);
|
||||
|
||||
virtual bool is_pipe() const override { return true; }
|
||||
void clone_writing();
|
||||
void close_writing();
|
||||
|
||||
void on_close(int status_flags) override;
|
||||
void on_clone(int status_flags) override;
|
||||
|
||||
virtual ino_t ino() const override { return 0; } // FIXME
|
||||
virtual Mode mode() const override { return { Mode::IFIFO | Mode::IRUSR | Mode::IWUSR }; }
|
||||
@@ -37,9 +39,10 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
||||
|
||||
virtual bool can_read_impl() const override { return m_buffer_size > 0; }
|
||||
virtual bool can_read_impl() const override { return !m_buffer->empty(); }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return m_reading_count == 0; }
|
||||
virtual bool has_hungup_impl() const override { return m_writing_count == 0; }
|
||||
|
||||
private:
|
||||
Pipe(const Credentials&);
|
||||
@@ -52,11 +55,10 @@ namespace Kernel
|
||||
timespec m_ctime {};
|
||||
ThreadBlocker m_thread_blocker;
|
||||
|
||||
BAN::Array<uint8_t, PAGE_SIZE> m_buffer;
|
||||
BAN::Atomic<size_t> m_buffer_size { 0 };
|
||||
size_t m_buffer_tail { 0 };
|
||||
BAN::UniqPtr<ByteRingBuffer> m_buffer;
|
||||
|
||||
BAN::Atomic<uint32_t> m_writing_count { 1 };
|
||||
BAN::Atomic<uint32_t> m_reading_count { 1 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
ProcROProcessInode(Process&, size_t (Process::*)(off_t, BAN::ByteSpan) const, TmpFileSystem&, const TmpInodeInfo&);
|
||||
@@ -56,6 +57,31 @@ namespace Kernel
|
||||
size_t (Process::*m_callback)(off_t, BAN::ByteSpan) const;
|
||||
};
|
||||
|
||||
class ProcSymlinkProcessInode final : public TmpInode
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcSymlinkProcessInode>> create_new(Process& process, BAN::ErrorOr<BAN::String> (Process::*callback)() const, TmpFileSystem&, mode_t);
|
||||
~ProcSymlinkProcessInode() = default;
|
||||
|
||||
virtual uid_t uid() const override { return m_process.credentials().ruid(); }
|
||||
virtual gid_t gid() const override { return m_process.credentials().rgid(); }
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
ProcSymlinkProcessInode(Process& process, BAN::ErrorOr<BAN::String> (Process::*)() const, TmpFileSystem&, const TmpInodeInfo&);
|
||||
|
||||
private:
|
||||
Process& m_process;
|
||||
BAN::ErrorOr<BAN::String> (Process::*m_callback)() const;
|
||||
};
|
||||
|
||||
class ProcROInode final : public TmpInode
|
||||
{
|
||||
public:
|
||||
@@ -72,6 +98,7 @@ namespace Kernel
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, const TmpInodeInfo&);
|
||||
@@ -80,4 +107,57 @@ namespace Kernel
|
||||
size_t (*m_callback)(off_t, BAN::ByteSpan);
|
||||
};
|
||||
|
||||
class ProcSymlinkInode final : public TmpInode
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> create_new(BAN::ErrorOr<BAN::String> (*)(void*), void (*)(void*), void* data, TmpFileSystem&, mode_t, uid_t, gid_t);
|
||||
~ProcSymlinkInode();
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
ProcSymlinkInode(BAN::ErrorOr<BAN::String> (*callback)(void*), void (*destructor)(void*), void* data, TmpFileSystem&, const TmpInodeInfo&);
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<BAN::String> (*m_callback)(void*);
|
||||
void (*m_destructor)(void*);
|
||||
void* m_data;
|
||||
};
|
||||
|
||||
class ProcFDDirectoryInode final : public TmpInode
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcFDDirectoryInode>> create_new(Process&, TmpFileSystem&, mode_t);
|
||||
~ProcFDDirectoryInode() = default;
|
||||
|
||||
virtual uid_t uid() const override { return m_process.credentials().ruid(); }
|
||||
virtual gid_t gid() const override { return m_process.credentials().rgid(); }
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
|
||||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override;
|
||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override { return BAN::Error::from_errno(EPERM); }
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override { return BAN::Error::from_errno(EPERM); }
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override { return BAN::Error::from_errno(EPERM); }
|
||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override { return BAN::Error::from_errno(EPERM); }
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override { return BAN::Error::from_errno(EPERM); }
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
ProcFDDirectoryInode(Process&, TmpFileSystem&, const TmpInodeInfo&);
|
||||
|
||||
private:
|
||||
Process& m_process;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -51,8 +51,6 @@ namespace Kernel
|
||||
: m_info(info)
|
||||
{}
|
||||
|
||||
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan buffer) override { return recvfrom_impl(buffer, nullptr, nullptr); }
|
||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return sendto_impl(buffer, nullptr, 0); }
|
||||
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Kernel
|
||||
// 1x singly indirect
|
||||
// 1x doubly indirect
|
||||
// 1x triply indirect
|
||||
BAN::Array<paddr_t, 5> block;
|
||||
BAN::Array<size_t, 5> block;
|
||||
static constexpr size_t direct_block_count = 2;
|
||||
#elif ARCH(i686)
|
||||
uint32_t __padding;
|
||||
@@ -36,8 +36,8 @@ namespace Kernel
|
||||
// 1x singly indirect
|
||||
// 1x doubly indirect
|
||||
// 1x triply indirect
|
||||
BAN::Array<paddr_t, 8> block;
|
||||
static constexpr size_t direct_block_count = 5;
|
||||
BAN::Array<size_t, 16> block;
|
||||
static constexpr size_t direct_block_count = 13;
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Kernel
|
||||
|
||||
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
||||
|
||||
virtual dev_t dev() const override { return m_rdev; }
|
||||
dev_t rdev() const { return m_rdev; }
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<TmpInode>> open_inode(ino_t ino);
|
||||
|
||||
@@ -118,16 +118,8 @@ namespace Kernel
|
||||
|
||||
private:
|
||||
InodeLocation find_inode(ino_t ino);
|
||||
|
||||
paddr_t find_block(size_t index);
|
||||
|
||||
template<TmpFuncs::for_each_indirect_paddr_allocating_callback F>
|
||||
BAN::ErrorOr<void> for_each_indirect_paddr_allocating(PageInfo page_info, F callback, size_t depth);
|
||||
template<TmpFuncs::for_each_indirect_paddr_allocating_callback F>
|
||||
BAN::ErrorOr<BAN::Iteration> for_each_indirect_paddr_allocating_internal(PageInfo page_info, F callback, size_t depth);
|
||||
|
||||
paddr_t find_indirect(PageInfo root, size_t index, size_t depth);
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
@@ -146,14 +138,14 @@ namespace Kernel
|
||||
static constexpr size_t max_data_pages =
|
||||
(PAGE_SIZE / sizeof(PageInfo)) *
|
||||
(PAGE_SIZE / sizeof(PageInfo)) *
|
||||
(PAGE_SIZE / sizeof(PageInfo));
|
||||
(PAGE_SIZE / sizeof(PageInfo) - 1);
|
||||
|
||||
// We store inodes in pages with double indirection.
|
||||
// With 64-bit pointers we can store 512^2 pages of inodes
|
||||
// which should be enough for now.
|
||||
// In future this should be dynamically calculated based on maximum
|
||||
// number of pages for this file system.
|
||||
PageInfo m_inode_pages;
|
||||
PageInfo m_inode_pages {};
|
||||
static constexpr size_t first_inode = 1;
|
||||
static constexpr size_t max_inodes =
|
||||
(PAGE_SIZE / sizeof(PageInfo)) *
|
||||
|
||||
@@ -47,14 +47,22 @@ namespace Kernel
|
||||
protected:
|
||||
TmpInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) override;
|
||||
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
|
||||
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
||||
|
||||
void sync();
|
||||
void free_all_blocks();
|
||||
virtual BAN::ErrorOr<void> prepare_unlink() { return {}; };
|
||||
|
||||
void free_all_blocks();
|
||||
void free_indirect_blocks(size_t block, uint32_t depth);
|
||||
|
||||
BAN::Optional<size_t> block_index(size_t data_block_index);
|
||||
BAN::Optional<size_t> block_index_from_indirect(size_t block, size_t index, uint32_t depth);
|
||||
|
||||
BAN::ErrorOr<size_t> block_index_with_allocation(size_t data_block_index);
|
||||
BAN::ErrorOr<size_t> block_index_from_indirect_with_allocation(size_t& block, size_t index, uint32_t depth);
|
||||
|
||||
protected:
|
||||
TmpFileSystem& m_fs;
|
||||
@@ -75,11 +83,11 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
TmpFileInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
@@ -97,11 +105,11 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return BAN::Error::from_errno(ENODEV); }
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(ENODEV); }
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(ENODEV); }
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
TmpSocketInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
@@ -115,14 +123,14 @@ namespace Kernel
|
||||
static BAN::ErrorOr<BAN::RefPtr<TmpSymlinkInode>> create_new(TmpFileSystem&, mode_t, uid_t, gid_t, BAN::StringView target);
|
||||
~TmpSymlinkInode();
|
||||
|
||||
BAN::ErrorOr<void> set_link_target(BAN::StringView);
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||
BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||
BAN::ErrorOr<void> set_link_target_impl(BAN::StringView) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
TmpSymlinkInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
@@ -148,16 +156,21 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override final;
|
||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override final;
|
||||
virtual BAN::ErrorOr<void> rename_inode_impl(BAN::RefPtr<Inode>, BAN::StringView, BAN::StringView) override final;
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
template<TmpFuncs::for_each_valid_entry_callback F>
|
||||
void for_each_valid_entry(F callback);
|
||||
|
||||
BAN::ErrorOr<void> unlink_inode(BAN::StringView, bool cleanup);
|
||||
|
||||
friend class TmpInode;
|
||||
};
|
||||
|
||||
|
||||
12
kernel/include/kernel/FS/USTARModule.h
Normal file
12
kernel/include/kernel/FS/USTARModule.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/BootInfo.h>
|
||||
#include <kernel/FS/FileSystem.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
bool is_ustar_boot_module(const BootModule&);
|
||||
BAN::ErrorOr<void> unpack_boot_module_into_filesystem(BAN::RefPtr<FileSystem>, const BootModule&);
|
||||
|
||||
}
|
||||
@@ -29,9 +29,6 @@ namespace Kernel
|
||||
|
||||
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_fs->root_inode(); }
|
||||
|
||||
// FIXME:
|
||||
virtual dev_t dev() const override { return 0; }
|
||||
|
||||
BAN::ErrorOr<void> mount(const Credentials&, BAN::StringView, BAN::StringView);
|
||||
BAN::ErrorOr<void> mount(const Credentials&, BAN::RefPtr<FileSystem>, BAN::StringView);
|
||||
|
||||
@@ -74,13 +71,13 @@ namespace Kernel
|
||||
|
||||
File root_file()
|
||||
{
|
||||
return File(root_inode(), "/"_sv);
|
||||
return File { root_inode(), "/"_sv };
|
||||
}
|
||||
|
||||
BAN::ErrorOr<File> file_from_relative_path(const File& parent, const Credentials&, BAN::StringView, int);
|
||||
BAN::ErrorOr<File> file_from_absolute_path(const Credentials& credentials, BAN::StringView path, int flags)
|
||||
BAN::ErrorOr<File> file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials&, BAN::StringView, int);
|
||||
BAN::ErrorOr<File> file_from_absolute_path(BAN::RefPtr<Inode> root_inode, const Credentials& credentials, BAN::StringView path, int flags)
|
||||
{
|
||||
return file_from_relative_path(root_file(), credentials, path, flags);
|
||||
return file_from_relative_path(root_inode, File { root_inode, "/"_sv }, credentials, path, flags);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -129,7 +129,8 @@ namespace Kernel
|
||||
}
|
||||
|
||||
#if ARCH(i686)
|
||||
void set_tls(uintptr_t addr);
|
||||
void set_fsbase(uintptr_t addr);
|
||||
void set_gsbase(uintptr_t addr);
|
||||
#endif
|
||||
|
||||
private:
|
||||
@@ -150,11 +151,11 @@ namespace Kernel
|
||||
|
||||
private:
|
||||
#if ARCH(x86_64)
|
||||
BAN::Array<SegmentDescriptor, 7> m_gdt; // null, kernel code, kernel data, user code, user data, tss low, tss high
|
||||
static constexpr uint16_t m_tss_offset = 0x28;
|
||||
BAN::Array<SegmentDescriptor, 8> m_gdt; // null, kernel code, kernel data, user code (32 bit), user data, user code (64 bit), tss low, tss high
|
||||
static constexpr uint16_t m_tss_offset = 0x30;
|
||||
#elif ARCH(i686)
|
||||
BAN::Array<SegmentDescriptor, 8> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, tls, tss
|
||||
static constexpr uint16_t m_tss_offset = 0x38;
|
||||
BAN::Array<SegmentDescriptor, 9> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, fsbase, gsbase, tss
|
||||
static constexpr uint16_t m_tss_offset = 0x40;
|
||||
#endif
|
||||
TaskStateSegment m_tss;
|
||||
const GDTR m_gdtr {
|
||||
|
||||
@@ -18,10 +18,12 @@ namespace Kernel
|
||||
|
||||
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
|
||||
constexpr uint8_t IRQ_MSI_BASE = 0x80;
|
||||
constexpr uint8_t IRQ_MSI_END = 0xF0;
|
||||
#if ARCH(i686)
|
||||
constexpr uint8_t IRQ_SYSCALL = 0xF0;
|
||||
constexpr uint8_t IRQ_YIELD = 0xF1;
|
||||
constexpr uint8_t IRQ_IPI = 0xF2;
|
||||
constexpr uint8_t IRQ_TIMER = 0xF3;
|
||||
#endif
|
||||
constexpr uint8_t IRQ_IPI = 0xF1;
|
||||
constexpr uint8_t IRQ_TIMER = 0xF2;
|
||||
|
||||
#if ARCH(x86_64)
|
||||
struct GateDescriptor
|
||||
@@ -75,7 +77,7 @@ namespace Kernel
|
||||
private:
|
||||
IDT() = default;
|
||||
|
||||
void register_interrupt_handler(uint8_t index, void (*handler)());
|
||||
void register_interrupt_handler(uint8_t index, void (*handler)(), uint8_t ist = 0);
|
||||
void register_syscall_handler(uint8_t index, void (*handler)());
|
||||
|
||||
private:
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Kernel
|
||||
{
|
||||
Mouse,
|
||||
Keyboard,
|
||||
Joystick,
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -31,7 +32,7 @@ namespace Kernel
|
||||
bool can_read_impl() const override { SpinLockGuard _(m_event_lock); return m_event_count > 0; }
|
||||
bool can_write_impl() const override { return false; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
|
||||
bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<size_t> read_non_block(BAN::ByteSpan);
|
||||
@@ -64,7 +65,7 @@ namespace Kernel
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<KeyboardDevice>> create(mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
void notify() { m_thread_blocker.unblock(); }
|
||||
void notify();
|
||||
|
||||
private:
|
||||
KeyboardDevice(mode_t mode, uid_t uid, gid_t gid);
|
||||
@@ -73,6 +74,7 @@ namespace Kernel
|
||||
bool can_read_impl() const override;
|
||||
bool can_write_impl() const override { return false; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hungup_impl() const override { return false; }
|
||||
|
||||
BAN::StringView name() const final override { return m_name; }
|
||||
dev_t rdev() const final override { return m_rdev; }
|
||||
@@ -90,7 +92,7 @@ namespace Kernel
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<MouseDevice>> create(mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
void notify() { m_thread_blocker.unblock(); }
|
||||
void notify();
|
||||
|
||||
private:
|
||||
MouseDevice(mode_t mode, uid_t uid, gid_t gid);
|
||||
@@ -99,6 +101,7 @@ namespace Kernel
|
||||
bool can_read_impl() const override;
|
||||
bool can_write_impl() const override { return false; }
|
||||
bool has_error_impl() const override { return false; }
|
||||
bool has_hungup_impl() const override { return false; }
|
||||
|
||||
BAN::StringView name() const final override { return m_name; }
|
||||
dev_t rdev() const final override { return m_rdev; }
|
||||
|
||||
@@ -14,6 +14,15 @@ namespace Kernel::Input
|
||||
|
||||
class PS2Controller
|
||||
{
|
||||
public:
|
||||
enum class DeviceType
|
||||
{
|
||||
None,
|
||||
Unknown,
|
||||
Keyboard,
|
||||
Mouse,
|
||||
};
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<void> initialize(uint8_t scancode_set);
|
||||
static PS2Controller& get();
|
||||
@@ -24,10 +33,14 @@ namespace Kernel::Input
|
||||
// Returns true, if byte is used as command, if returns false, byte is meant to device
|
||||
bool handle_command_byte(PS2Device*, uint8_t);
|
||||
|
||||
uint8_t data_port() const { return m_data_port; }
|
||||
|
||||
private:
|
||||
PS2Controller() = default;
|
||||
BAN::ErrorOr<void> initialize_impl(uint8_t scancode_set);
|
||||
BAN::ErrorOr<void> initialize_device(uint8_t, uint8_t scancode_set);
|
||||
BAN::ErrorOr<DeviceType> identify_device(uint8_t);
|
||||
|
||||
void device_initialize_task(void*);
|
||||
|
||||
BAN::ErrorOr<uint8_t> read_byte();
|
||||
BAN::ErrorOr<void> send_byte(uint16_t port, uint8_t byte);
|
||||
@@ -59,6 +72,9 @@ namespace Kernel::Input
|
||||
};
|
||||
|
||||
private:
|
||||
uint16_t m_command_port { PS2::IOPort::COMMAND };
|
||||
uint16_t m_data_port { PS2::IOPort::DATA };
|
||||
|
||||
BAN::RefPtr<PS2Device> m_devices[2];
|
||||
|
||||
Mutex m_mutex;
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Kernel::Input
|
||||
|
||||
protected:
|
||||
PS2Device(PS2Controller&, InputDevice::Type type);
|
||||
virtual ~PS2Device();
|
||||
|
||||
protected:
|
||||
PS2Controller& m_controller;
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace Kernel
|
||||
uintptr_t r10;
|
||||
uintptr_t r9;
|
||||
uintptr_t r8;
|
||||
|
||||
uintptr_t rdi;
|
||||
uintptr_t rsi;
|
||||
uintptr_t rbp;
|
||||
@@ -36,6 +35,18 @@ namespace Kernel
|
||||
uintptr_t rcx;
|
||||
uintptr_t rax;
|
||||
};
|
||||
struct YieldRegisters
|
||||
{
|
||||
uintptr_t r15;
|
||||
uintptr_t r14;
|
||||
uintptr_t r13;
|
||||
uintptr_t r12;
|
||||
uintptr_t rbp;
|
||||
uintptr_t rbx;
|
||||
uintptr_t ret;
|
||||
uintptr_t sp;
|
||||
uintptr_t ip;
|
||||
};
|
||||
#elif ARCH(i686)
|
||||
struct InterruptRegisters
|
||||
{
|
||||
@@ -48,6 +59,16 @@ namespace Kernel
|
||||
uintptr_t ecx;
|
||||
uintptr_t eax;
|
||||
};
|
||||
struct YieldRegisters
|
||||
{
|
||||
uintptr_t ebp;
|
||||
uintptr_t edi;
|
||||
uintptr_t esi;
|
||||
uintptr_t ebx;
|
||||
uintptr_t ret;
|
||||
uintptr_t sp;
|
||||
uintptr_t ip;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -29,30 +29,4 @@ namespace Kernel
|
||||
Lock& m_lock;
|
||||
};
|
||||
|
||||
template<typename Lock>
|
||||
class LockFreeGuard
|
||||
{
|
||||
BAN_NON_COPYABLE(LockFreeGuard);
|
||||
BAN_NON_MOVABLE(LockFreeGuard);
|
||||
|
||||
public:
|
||||
LockFreeGuard(Lock& lock)
|
||||
: m_lock(lock)
|
||||
, m_depth(lock.lock_depth())
|
||||
{
|
||||
for (uint32_t i = 0; i < m_depth; i++)
|
||||
m_lock.unlock();
|
||||
}
|
||||
|
||||
~LockFreeGuard()
|
||||
{
|
||||
for (uint32_t i = 0; i < m_depth; i++)
|
||||
m_lock.lock();
|
||||
}
|
||||
|
||||
private:
|
||||
Lock& m_lock;
|
||||
const uint32_t m_depth;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,19 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class Mutex
|
||||
class BaseMutex
|
||||
{
|
||||
public:
|
||||
virtual void lock() = 0;
|
||||
virtual bool try_lock() = 0;
|
||||
virtual void unlock() = 0;
|
||||
|
||||
virtual pid_t locker() const = 0;
|
||||
virtual bool is_locked() const = 0;
|
||||
virtual uint32_t lock_depth() const = 0;
|
||||
};
|
||||
|
||||
class Mutex : public BaseMutex
|
||||
{
|
||||
BAN_NON_COPYABLE(Mutex);
|
||||
BAN_NON_MOVABLE(Mutex);
|
||||
@@ -17,13 +29,14 @@ namespace Kernel
|
||||
public:
|
||||
Mutex() = default;
|
||||
|
||||
void lock()
|
||||
void lock() override
|
||||
{
|
||||
const auto tid = Thread::current_tid();
|
||||
if (tid == m_locker)
|
||||
ASSERT(m_lock_depth > 0);
|
||||
else
|
||||
{
|
||||
ASSERT(!tid || !Thread::current().has_spinlock());
|
||||
pid_t expected = -1;
|
||||
while (!m_locker.compare_exchange(expected, tid))
|
||||
{
|
||||
@@ -37,7 +50,7 @@ namespace Kernel
|
||||
m_lock_depth++;
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
bool try_lock() override
|
||||
{
|
||||
const auto tid = Thread::current_tid();
|
||||
if (tid == m_locker)
|
||||
@@ -55,7 +68,7 @@ namespace Kernel
|
||||
return true;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
void unlock() override
|
||||
{
|
||||
const auto tid = Thread::current_tid();
|
||||
ASSERT(m_locker == tid);
|
||||
@@ -68,16 +81,16 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
pid_t locker() const { return m_locker; }
|
||||
bool is_locked() const { return m_locker != -1; }
|
||||
uint32_t lock_depth() const { return m_lock_depth; }
|
||||
pid_t locker() const override { return m_locker; }
|
||||
bool is_locked() const override { return m_locker != -1; }
|
||||
uint32_t lock_depth() const override { return m_lock_depth; }
|
||||
|
||||
private:
|
||||
BAN::Atomic<pid_t> m_locker { -1 };
|
||||
uint32_t m_lock_depth { 0 };
|
||||
};
|
||||
|
||||
class PriorityMutex
|
||||
class PriorityMutex : public BaseMutex
|
||||
{
|
||||
BAN_NON_COPYABLE(PriorityMutex);
|
||||
BAN_NON_MOVABLE(PriorityMutex);
|
||||
@@ -85,13 +98,15 @@ namespace Kernel
|
||||
public:
|
||||
PriorityMutex() = default;
|
||||
|
||||
void lock()
|
||||
void lock() override
|
||||
{
|
||||
const auto tid = Thread::current_tid();
|
||||
|
||||
if (tid == m_locker)
|
||||
ASSERT(m_lock_depth > 0);
|
||||
else
|
||||
{
|
||||
ASSERT(!tid || !Thread::current().has_spinlock());
|
||||
bool has_priority = tid ? !Thread::current().is_userspace() : true;
|
||||
if (has_priority)
|
||||
m_queue_length++;
|
||||
@@ -108,9 +123,10 @@ namespace Kernel
|
||||
m_lock_depth++;
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
bool try_lock() override
|
||||
{
|
||||
const auto tid = Thread::current_tid();
|
||||
|
||||
if (tid == m_locker)
|
||||
ASSERT(m_lock_depth > 0);
|
||||
else
|
||||
@@ -129,7 +145,7 @@ namespace Kernel
|
||||
return true;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
void unlock() override
|
||||
{
|
||||
const auto tid = Thread::current_tid();
|
||||
ASSERT(m_locker == tid);
|
||||
@@ -145,9 +161,9 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
pid_t locker() const { return m_locker; }
|
||||
bool is_locked() const { return m_locker != -1; }
|
||||
uint32_t lock_depth() const { return m_lock_depth; }
|
||||
pid_t locker() const override { return m_locker; }
|
||||
bool is_locked() const override { return m_locker != -1; }
|
||||
uint32_t lock_depth() const override { return m_lock_depth; }
|
||||
|
||||
private:
|
||||
BAN::Atomic<pid_t> m_locker { -1 };
|
||||
|
||||
97
kernel/include/kernel/Lock/RWLock.h
Normal file
97
kernel/include/kernel/Lock/RWLock.h
Normal file
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class RWLock
|
||||
{
|
||||
BAN_NON_COPYABLE(RWLock);
|
||||
BAN_NON_MOVABLE(RWLock);
|
||||
public:
|
||||
RWLock() = default;
|
||||
|
||||
void rd_lock()
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
while (m_writers_waiting > 0 || m_writer_active)
|
||||
m_thread_blocker.block_indefinite(&m_mutex);
|
||||
m_readers_active++;
|
||||
}
|
||||
|
||||
void rd_unlock()
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
if (--m_readers_active == 0)
|
||||
m_thread_blocker.unblock();
|
||||
}
|
||||
|
||||
void wr_lock()
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
m_writers_waiting++;
|
||||
while (m_readers_active > 0 || m_writer_active)
|
||||
m_thread_blocker.block_indefinite(&m_mutex);
|
||||
m_writers_waiting--;
|
||||
m_writer_active = true;
|
||||
}
|
||||
|
||||
|
||||
void wr_unlock()
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
m_writer_active = false;
|
||||
m_thread_blocker.unblock();
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex m_mutex;
|
||||
ThreadBlocker m_thread_blocker;
|
||||
uint32_t m_readers_active { 0 };
|
||||
uint32_t m_writers_waiting { 0 };
|
||||
bool m_writer_active { false };
|
||||
};
|
||||
|
||||
class RWLockRDGuard
|
||||
{
|
||||
BAN_NON_COPYABLE(RWLockRDGuard);
|
||||
BAN_NON_MOVABLE(RWLockRDGuard);
|
||||
public:
|
||||
RWLockRDGuard(RWLock& lock)
|
||||
: m_lock(lock)
|
||||
{
|
||||
m_lock.rd_lock();
|
||||
}
|
||||
|
||||
~RWLockRDGuard()
|
||||
{
|
||||
m_lock.rd_unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
RWLock& m_lock;
|
||||
};
|
||||
|
||||
class RWLockWRGuard
|
||||
{
|
||||
BAN_NON_COPYABLE(RWLockWRGuard);
|
||||
BAN_NON_MOVABLE(RWLockWRGuard);
|
||||
public:
|
||||
RWLockWRGuard(RWLock& lock)
|
||||
: m_lock(lock)
|
||||
{
|
||||
m_lock.wr_lock();
|
||||
}
|
||||
|
||||
~RWLockWRGuard()
|
||||
{
|
||||
m_lock.wr_unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
RWLock& m_lock;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -18,42 +18,13 @@ namespace Kernel
|
||||
public:
|
||||
SpinLock() = default;
|
||||
|
||||
InterruptState lock()
|
||||
{
|
||||
auto state = Processor::get_interrupt_state();
|
||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||
InterruptState lock();
|
||||
|
||||
auto id = Processor::current_id().as_u32();
|
||||
ASSERT(m_locker.load(BAN::MemoryOrder::memory_order_relaxed) != id);
|
||||
bool try_lock_interrupts_disabled();
|
||||
|
||||
auto expected = PROCESSOR_NONE.as_u32();
|
||||
while (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acquire))
|
||||
{
|
||||
Processor::pause();
|
||||
expected = PROCESSOR_NONE.as_u32();
|
||||
}
|
||||
void unlock(InterruptState state);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
bool try_lock_interrupts_disabled()
|
||||
{
|
||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||
|
||||
auto id = Processor::current_id().as_u32();
|
||||
ASSERT(m_locker.load(BAN::MemoryOrder::memory_order_relaxed) != id);
|
||||
|
||||
auto expected = PROCESSOR_NONE.as_u32();
|
||||
return m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acquire);
|
||||
}
|
||||
|
||||
void unlock(InterruptState state)
|
||||
{
|
||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||
ASSERT(current_processor_has_lock());
|
||||
m_locker.store(PROCESSOR_NONE.as_u32(), BAN::MemoryOrder::memory_order_release);
|
||||
Processor::set_interrupt_state(state);
|
||||
}
|
||||
uint32_t lock_depth() const { return current_processor_has_lock(); }
|
||||
|
||||
bool current_processor_has_lock() const
|
||||
{
|
||||
@@ -72,36 +43,13 @@ namespace Kernel
|
||||
public:
|
||||
RecursiveSpinLock() = default;
|
||||
|
||||
InterruptState lock()
|
||||
{
|
||||
auto state = Processor::get_interrupt_state();
|
||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||
InterruptState lock();
|
||||
|
||||
auto id = Processor::current_id().as_u32();
|
||||
bool try_lock_interrupts_disabled();
|
||||
|
||||
ProcessorID::value_type expected = PROCESSOR_NONE.as_u32();
|
||||
while (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acq_rel))
|
||||
{
|
||||
if (expected == id)
|
||||
break;
|
||||
Processor::pause();
|
||||
expected = PROCESSOR_NONE.as_u32();
|
||||
}
|
||||
void unlock(InterruptState state);
|
||||
|
||||
m_lock_depth++;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void unlock(InterruptState state)
|
||||
{
|
||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||
ASSERT(current_processor_has_lock());
|
||||
ASSERT(m_lock_depth > 0);
|
||||
if (--m_lock_depth == 0)
|
||||
m_locker.store(PROCESSOR_NONE.as_u32(), BAN::MemoryOrder::memory_order_release);
|
||||
Processor::set_interrupt_state(state);
|
||||
}
|
||||
uint32_t lock_depth() const { return m_lock_depth; }
|
||||
|
||||
bool current_processor_has_lock() const
|
||||
{
|
||||
@@ -113,6 +61,9 @@ namespace Kernel
|
||||
uint32_t m_lock_depth { 0 };
|
||||
};
|
||||
|
||||
template<typename Lock>
|
||||
class SpinLockGuardAsMutex;
|
||||
|
||||
template<typename Lock>
|
||||
class SpinLockGuard
|
||||
{
|
||||
@@ -134,6 +85,7 @@ namespace Kernel
|
||||
private:
|
||||
Lock& m_lock;
|
||||
InterruptState m_state;
|
||||
friend class SpinLockGuardAsMutex<Lock>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
64
kernel/include/kernel/Lock/SpinLockAsMutex.h
Normal file
64
kernel/include/kernel/Lock/SpinLockAsMutex.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
// FIXME: These classes are HACKS to allow passing spinlock
|
||||
// to unblock functions. Write a better API that either
|
||||
// allows passing spinlocks or do something cleaner that
|
||||
// whatever shit this is
|
||||
|
||||
template<typename Lock>
|
||||
class SpinLockAsMutex : public BaseMutex
|
||||
{
|
||||
public:
|
||||
SpinLockAsMutex(Lock& lock, InterruptState state)
|
||||
: m_lock(lock)
|
||||
, m_lock_depth(lock.lock_depth())
|
||||
, m_state(state)
|
||||
, m_locker(Thread::current_tid())
|
||||
{
|
||||
ASSERT(m_lock.current_processor_has_lock());
|
||||
}
|
||||
|
||||
void lock() override
|
||||
{
|
||||
m_lock.lock();
|
||||
m_lock_depth++;
|
||||
}
|
||||
|
||||
bool try_lock() override
|
||||
{
|
||||
lock();
|
||||
return true;
|
||||
}
|
||||
|
||||
void unlock() override
|
||||
{
|
||||
m_lock.unlock(--m_lock_depth ? InterruptState::Disabled : m_state);
|
||||
}
|
||||
|
||||
pid_t locker() const override { return is_locked() ? m_locker : -1; }
|
||||
bool is_locked() const override { return m_lock_depth; }
|
||||
uint32_t lock_depth() const override { return m_lock_depth; }
|
||||
|
||||
private:
|
||||
SpinLock& m_lock;
|
||||
uint32_t m_lock_depth { 0 };
|
||||
InterruptState m_state;
|
||||
const pid_t m_locker;
|
||||
};
|
||||
|
||||
template<typename Lock>
|
||||
class SpinLockGuardAsMutex : public SpinLockAsMutex<Lock>
|
||||
{
|
||||
public:
|
||||
SpinLockGuardAsMutex(SpinLockGuard<Lock>& guard)
|
||||
: SpinLockAsMutex<Lock>(guard.m_lock, guard.m_state)
|
||||
{}
|
||||
};
|
||||
|
||||
}
|
||||
76
kernel/include/kernel/Memory/ByteRingBuffer.h
Normal file
76
kernel/include/kernel/Memory/ByteRingBuffer.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/ByteSpan.h>
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <BAN/Vector.h>
|
||||
|
||||
#include <kernel/Memory/Types.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class ByteRingBuffer
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<ByteRingBuffer>> create(size_t size);
|
||||
~ByteRingBuffer();
|
||||
|
||||
void push(BAN::ConstByteSpan data)
|
||||
{
|
||||
ASSERT(data.size() + m_size <= m_capacity);
|
||||
uint8_t* buffer_head = reinterpret_cast<uint8_t*>(m_vaddr) + (m_tail + m_size) % m_capacity;
|
||||
memcpy(buffer_head, data.data(), data.size());
|
||||
m_size += data.size();
|
||||
}
|
||||
|
||||
void pop(size_t size)
|
||||
{
|
||||
ASSERT(size <= m_size);
|
||||
m_tail = (m_tail + size) % m_capacity;
|
||||
m_size -= size;
|
||||
}
|
||||
|
||||
void pop_back(size_t size)
|
||||
{
|
||||
ASSERT(size <= m_size);
|
||||
m_size -= size;
|
||||
}
|
||||
|
||||
BAN::ConstByteSpan get_data() const
|
||||
{
|
||||
const uint8_t* base = reinterpret_cast<const uint8_t*>(m_vaddr);
|
||||
return { base + m_tail, m_size };
|
||||
}
|
||||
|
||||
uint8_t front() const
|
||||
{
|
||||
ASSERT(!empty());
|
||||
return reinterpret_cast<const uint8_t*>(m_vaddr)[m_tail];
|
||||
}
|
||||
|
||||
uint8_t back() const
|
||||
{
|
||||
ASSERT(!empty());
|
||||
return reinterpret_cast<const uint8_t*>(m_vaddr)[m_tail + m_size];
|
||||
}
|
||||
|
||||
bool empty() const { return m_size == 0; }
|
||||
bool full() const { return m_size == m_capacity; }
|
||||
size_t free() const { return m_capacity - m_size; }
|
||||
size_t size() const { return m_size; }
|
||||
size_t capacity() const { return m_capacity; }
|
||||
|
||||
private:
|
||||
ByteRingBuffer(size_t capacity)
|
||||
: m_capacity(capacity)
|
||||
{ }
|
||||
|
||||
private:
|
||||
size_t m_size { 0 };
|
||||
size_t m_tail { 0 };
|
||||
const size_t m_capacity;
|
||||
|
||||
vaddr_t m_vaddr { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
@@ -27,18 +27,19 @@ namespace Kernel
|
||||
BAN_NON_MOVABLE(FileBackedRegion);
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t);
|
||||
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t, int status_flags);
|
||||
~FileBackedRegion();
|
||||
|
||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
|
||||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
|
||||
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
|
||||
private:
|
||||
FileBackedRegion(BAN::RefPtr<Inode>, PageTable&, off_t offset, ssize_t size, Type flags, PageTable::flags_t page_flags);
|
||||
FileBackedRegion(BAN::RefPtr<Inode>, PageTable&, off_t offset, ssize_t size, Type type, PageTable::flags_t flags, int status_flags);
|
||||
|
||||
private:
|
||||
BAN::RefPtr<Inode> m_inode;
|
||||
|
||||
@@ -11,22 +11,23 @@ namespace Kernel
|
||||
BAN_NON_MOVABLE(MemoryBackedRegion);
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t);
|
||||
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t, int status_flags);
|
||||
~MemoryBackedRegion();
|
||||
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
|
||||
|
||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||
|
||||
// Copy data from buffer into this region
|
||||
// This can fail if no memory is mapped and no free memory was available
|
||||
BAN::ErrorOr<void> copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size);
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
|
||||
private:
|
||||
MemoryBackedRegion(PageTable&, size_t size, Type, PageTable::flags_t);
|
||||
MemoryBackedRegion(PageTable&, size_t size, Type, PageTable::flags_t, int status_flags);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/Memory/PageTable.h>
|
||||
#include <kernel/Memory/Types.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <kernel/ThreadBlocker.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -33,15 +33,25 @@ namespace Kernel
|
||||
bool contains(vaddr_t address) const;
|
||||
bool contains_fully(vaddr_t address, size_t size) const;
|
||||
bool overlaps(vaddr_t address, size_t size) const;
|
||||
bool is_contained_by(vaddr_t address, size_t size) const;
|
||||
|
||||
bool writable() const { return m_flags & PageTable::Flags::ReadWrite; }
|
||||
|
||||
size_t size() const { return m_size; }
|
||||
vaddr_t vaddr() const { return m_vaddr; }
|
||||
|
||||
int status_flags() const { return m_status_flags; }
|
||||
Type type() const { return m_type; }
|
||||
PageTable::flags_t flags() const { return m_flags; }
|
||||
|
||||
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
|
||||
size_t physical_page_count() const { return m_physical_page_count; }
|
||||
|
||||
void pin();
|
||||
void unpin();
|
||||
void wait_not_pinned();
|
||||
|
||||
BAN::ErrorOr<void> mprotect(PageTable::flags_t);
|
||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0;
|
||||
|
||||
// Returns error if no memory was available
|
||||
@@ -50,20 +60,26 @@ namespace Kernel
|
||||
BAN::ErrorOr<bool> allocate_page_containing(vaddr_t address, bool wants_write);
|
||||
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) = 0;
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) = 0;
|
||||
|
||||
protected:
|
||||
MemoryRegion(PageTable&, size_t size, Type type, PageTable::flags_t flags);
|
||||
MemoryRegion(PageTable&, size_t size, Type type, PageTable::flags_t flags, int status_flags);
|
||||
BAN::ErrorOr<void> initialize(AddressRange);
|
||||
|
||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t address, bool wants_write) = 0;
|
||||
|
||||
protected:
|
||||
PageTable& m_page_table;
|
||||
const size_t m_size;
|
||||
size_t m_size { 0 };
|
||||
const Type m_type;
|
||||
const PageTable::flags_t m_flags;
|
||||
PageTable::flags_t m_flags;
|
||||
const int m_status_flags;
|
||||
vaddr_t m_vaddr { 0 };
|
||||
size_t m_physical_page_count { 0 };
|
||||
|
||||
Mutex m_pinned_mutex;
|
||||
BAN::Atomic<size_t> m_pinned_count { 0 };
|
||||
ThreadBlocker m_pinned_blocker;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace Kernel
|
||||
bool is_page_free(vaddr_t) const;
|
||||
bool is_range_free(vaddr_t, size_t bytes) const;
|
||||
|
||||
bool reserve_page(vaddr_t, bool only_free = true);
|
||||
bool reserve_page(vaddr_t, bool only_free = true, bool send_smp_message = true);
|
||||
bool reserve_range(vaddr_t, size_t bytes, bool only_free = true);
|
||||
|
||||
vaddr_t reserve_free_page(vaddr_t first_address, vaddr_t last_address = UINTPTR_MAX);
|
||||
@@ -133,7 +133,7 @@ namespace Kernel
|
||||
void map_kernel_memory();
|
||||
void prepare_fast_page();
|
||||
|
||||
static void invalidate(vaddr_t, bool send_smp_message);
|
||||
void invalidate(vaddr_t, bool send_smp_message);
|
||||
|
||||
static void map_fast_page(paddr_t);
|
||||
static void unmap_fast_page();
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/Memory/MemoryRegion.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
@@ -55,15 +57,17 @@ namespace Kernel
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> create(BAN::RefPtr<SharedMemoryObjectManager::Object>, PageTable&, AddressRange);
|
||||
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> split(size_t offset) override;
|
||||
|
||||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
|
||||
private:
|
||||
SharedMemoryObject(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table)
|
||||
: MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags)
|
||||
: MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags, O_EXEC | O_RDWR)
|
||||
, m_object(object)
|
||||
{ }
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#if ARCH(x86_64)
|
||||
#define KERNEL_OFFSET 0xFFFFFFFF80000000
|
||||
#define USERSPACE_END 0xFFFF800000000000
|
||||
#define USERSPACE_END 0x800000000000
|
||||
#elif ARCH(i686)
|
||||
#define KERNEL_OFFSET 0xC0000000
|
||||
#define USERSPACE_END 0xC0000000
|
||||
@@ -12,6 +12,7 @@
|
||||
#error
|
||||
#endif
|
||||
|
||||
#undef PAGE_SIZE
|
||||
#define PAGE_SIZE ((uintptr_t)4096)
|
||||
#define PAGE_SIZE_SHIFT 12
|
||||
#define PAGE_ADDR_MASK (~(uintptr_t)0xFFF)
|
||||
|
||||
@@ -15,21 +15,21 @@ namespace Kernel
|
||||
|
||||
public:
|
||||
// Create virtual range to fixed virtual address
|
||||
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr(PageTable&, vaddr_t, size_t, PageTable::flags_t flags, bool preallocate_pages);
|
||||
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr(PageTable&, vaddr_t, size_t, PageTable::flags_t flags, bool preallocate_pages, bool add_guard_pages);
|
||||
// Create virtual range to virtual address range
|
||||
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr_range(PageTable&, vaddr_t vaddr_start, vaddr_t vaddr_end, size_t, PageTable::flags_t flags, bool preallocate_pages);
|
||||
static BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> create_to_vaddr_range(PageTable&, vaddr_t vaddr_start, vaddr_t vaddr_end, size_t, PageTable::flags_t flags, bool preallocate_pages, bool add_guard_pages);
|
||||
~VirtualRange();
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> clone(PageTable&);
|
||||
|
||||
vaddr_t vaddr() const { return m_vaddr; }
|
||||
size_t size() const { return m_size; }
|
||||
vaddr_t vaddr() const { return m_vaddr + (m_has_guard_pages ? PAGE_SIZE : 0); }
|
||||
size_t size() const { return m_size - (m_has_guard_pages ? 2 * PAGE_SIZE : 0); }
|
||||
PageTable::flags_t flags() const { return m_flags; }
|
||||
|
||||
paddr_t paddr_of(vaddr_t vaddr) const
|
||||
{
|
||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||
const size_t index = (vaddr - m_vaddr) / PAGE_SIZE;
|
||||
const size_t index = (vaddr - this->vaddr()) / PAGE_SIZE;
|
||||
ASSERT(index < m_paddrs.size());
|
||||
const paddr_t paddr = m_paddrs[index];
|
||||
ASSERT(paddr);
|
||||
@@ -38,15 +38,16 @@ namespace Kernel
|
||||
|
||||
bool contains(vaddr_t address) const { return vaddr() <= address && address < vaddr() + size(); }
|
||||
|
||||
BAN::ErrorOr<void> allocate_page_for_demand_paging(vaddr_t address);
|
||||
BAN::ErrorOr<bool> allocate_page_for_demand_paging(vaddr_t address);
|
||||
|
||||
private:
|
||||
VirtualRange(PageTable&, bool preallocated, vaddr_t, size_t, PageTable::flags_t);
|
||||
VirtualRange(PageTable&, bool preallocated, bool has_guard_pages, vaddr_t, size_t, PageTable::flags_t);
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
private:
|
||||
PageTable& m_page_table;
|
||||
const bool m_preallocated;
|
||||
const bool m_has_guard_pages;
|
||||
const vaddr_t m_vaddr;
|
||||
const size_t m_size;
|
||||
const PageTable::flags_t m_flags;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user