{"id":13408553,"url":"https://github.com/docandrew/CuBit","last_synced_at":"2025-03-14T13:31:37.647Z","repository":{"id":41540539,"uuid":"245561816","full_name":"docandrew/CuBit","owner":"docandrew","description":"General-purpose, formally-verified, 64-bit operating system in SPARK/Ada for x86-64","archived":false,"fork":false,"pushed_at":"2021-05-14T04:47:20.000Z","size":1408,"stargazers_count":78,"open_issues_count":4,"forks_count":4,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-07-31T20:31:14.278Z","etag":null,"topics":["ada","os","spark","x86-64"],"latest_commit_sha":null,"homepage":null,"language":"Ada","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/docandrew.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-07T03:33:34.000Z","updated_at":"2024-07-22T11:09:59.000Z","dependencies_parsed_at":"2022-09-02T16:49:18.900Z","dependency_job_id":null,"html_url":"https://github.com/docandrew/CuBit","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/docandrew%2FCuBit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/docandrew%2FCuBit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/docandrew%2FCuBit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/docandrew%2FCuBit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/docandrew","download_url":"https://codeload.github.com/docandrew/CuBit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243584316,"owners_count":20314733,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ada","os","spark","x86-64"],"created_at":"2024-07-30T20:00:53.607Z","updated_at":"2025-03-14T13:31:37.136Z","avatar_url":"https://github.com/docandrew.png","language":"Ada","funding_links":[],"categories":["OS and Kernels"],"sub_categories":["Continuous Integration"],"readme":"![Build](https://github.com/docandrew/CuBit/workflows/CuBit%20CI/badge.svg)\n\nIntroduction\n============\nCuBitOS is a multi-processor, 64-bit, (partially) formally-verified, \ngeneral-purpose operating system, currently for the x86-64 architecture.\n\nCuBit is written in the SPARK dialect of Ada.\n\nCuBit is very much a WORK-IN-PROGRESS! Having said that, please give it a spin.\nContributors welcome!\n\nBuild Instructions\n==================\n\nRequirements\n------------\n* yasm assembler\n* GNAT CE 2020 with `gprbuild`, `gnat`, etc. in your `$PATH`\n* gcc/ld/GNU make/GNU binutils\n\nTo create bootable .ISO, you'll also need:\n* grub-mkrescue\n* xorriso\n* grub-pc-bin\n\nBuilding\n========\nDependencies: You'll need the GNAT 2020 Compiler, and if you want to build\nthe live-CD, you'll need the *xorriso* and *grub-mkrescue* tools, and possibly\n*grub-pc-bin* depending on which emulator/virtualization environment you\nare using. These are\nprobably provided in your distro's package manager. This can be built in Linux\nand on Windows using WSL.\n\n    git clone https://github.com/docandrew/CuBit.git\n    make\n\nThis will build CuBit and create a Live-CD .iso file. The ISO can be mounted\nand run in VirtualBox, Bochs, or QEMU.\n\nDocumentation (work in progress):\n---------------------------------\n\n|  Task                                |   Command   |\n|--------------------------------------|-------------|\n| Create documentation (in build/docs) | `make docs` |\n| Run provers                          | `make prove`|\n| Build html documentation             | `make html` |\n\nContributor Notes\n=================\nAda is case-insensitive (which is kind of nice,\nhonestly), but it makes all exported symbols lower-case, so anything in .asm\nfiles that references that symbol needs to use the lower-cased version, OR\nspecify the External_Name for the symbol in an aspect.\n\nEnumerated types containing \"holes\" cause GNAT to insert run-time checks for\nvalid values when assigning these. I couldn't find a pragma to disable these\nchecks. Eventually we'll write exception handler functions that can either\nperform the checks or cause a kernel panic, but for now, fill the holes with\nobvious values like BAD_1, BAD_2, etc.\n\nPlease ensure proofs are run (using `make prove`) before submitting Pull\nRequests. Be very cautious about Pragma Annotate to disable warnings.\n`gnatprove` will give some spurious warnings like `statement has no effect`\nor `unused assignment` that are clearly incorrect, but please double-check\nthese.\n\nVariant records appear to insert some extra cruft in the underlying record,\neven if pragma Pack is used. Do not use these as \"overlays\" on top of existing\nmemory, for example the ACPI tables. You'll have alignment issues with some of\nthe fields and end up with junk data. The same is true even for non-variant\nrecords that use discriminants.\n\nSome things that might be confusing:\n====================================\n\nThe MAX_PHYS_ constants\n-----------------------\n* MAX_PHYS_ALLOC - set in config.ads, this is the max physical memory that CuBit\n  supports. There only limit here is practical, since the boot mem allocator is\n  set up to create bitmaps for all of this memory (128 GiB), which takes up a fair\n  amount of space. (We may consider just setting aside a small linear-mapped heap \n  section for kernel use and build a better allocator so this limit is not a factor\n  anymore.)\n\n* MAX_PHYS_ADDRESS - the maximum _theoretical_ physical memory that our hardware\n  supports (if we use linear mapping). In the case of x86-64, we have canonical \n  48-bit virtual addresses, so if we want all of physical memory to be mapped in\n  virtual memory, we're left with about 280TB, which we need to split to use in\n  the higher-half, so 128TiB. Note that Intel is looking at 56-bit addressing with\n  a five-level page table, so this number may change soon for x86-64.\n\n* MAX_PHYS_ADDRESSABLE - the top physical memory address _on our system_ that we\n  detect at runtime. We linear-map memory areas up to this point\n  (starting at 0xFFFF_8000_0000_0000).\n\n* MAX_PHYS_USABLE - the top usable RAM address _on our system_. There may be\n  holes inside this, so we can't blindly allocate memory from beneath this\n  limit, but a physical allocator would be expected to handle addresses up to\n  this point.\n\n\"Bootstrap\" vs \"Boot\" vs \"Kernel\"\n---------------------------------\nSome of the structures used, like the GDT and Page Tables, have to be set up in\n`boot.asm` before switching to long mode. These are referred to as the\n\"bootstrap\" GDT and Page Tables, respectively. There's also the \"boot\"\nphysical memory allocator. Later on, we re-map\nthe entirety of physical memory into the higher-half of the kernel along with\na new GDT in `segment.adb`. These are called the \"kernel page tables\" and\n\"kernel GDT.\"\n\nThe bootstrap page tables identity-map the first 1G of memory, and then map\nit again into the higher-half, starting at 0xFFFF_8000_0000_0000. So the P2V\nand V2P (physical-to-virtual, virtual-to-physical) work by simple addition and\nsubtraction because you can access the physical memory at, for example, \n0x0000_0000_DEAD_BEEF at the virtual addresses 0x0000_0000_DEAD_BEEF and also\n0xFFFF_8000_DEAD_BEEF.\n\nWhen we switch to the kernel map, we can no longer address memory using direct\nphysical addresses. Instead, a specific physical address must be accessed using\nthe linear-mapped address at 0xFFFF_8000_0000_0000. We linear-map all physical\nmemory in 0xFFFF_8000_0000_0000 to 0xFFFF_8FFF_FFFF_FFFF.\n\n\nCuBit Memory Map\n----------------\nNote that due to the x86-64 ABI, the kernel must be linked in the top 2GiB of\nmemory when using mcmodel=kernel. Therefore, our page tables also\nneed a mapping for 0xFFFF_FFFF_8XXX_XXXX -\u003e 0x0000_0000_0XXX_XXXX.\n\nCan I Help?\n===========\nYes! I've tried to make the code very friendly to those unfamiliar with\nCuBitOS, Ada or SPARK. Please try it out on a VM and let me know what you\nthink. Negative feedback and constructive criticism are useful too.\n\nIt's heavily-documented, and contributors are welcome!\n\nThings that I could really use help with:\n-----------------------------------------\n\n* Drivers\n* Drivers\n* Adding more contracts and SPARK verification conditions\n* Porting apps or writing new ones\n* Testing, especially developing an automated test framework\n* Drivers\n* A proper CI/CD pipeline. As the time to prove CuBitOS grows, being able to have\n  this done automatically or overnight would be great.\n* Articles, documentation.\n* Did I mention Drivers?\n\nOther avenues for exploration\n-----------------------------\nCuBitOS may be a good starting point for academic research. SPARK has an\nescape hatch to perform proofs in Coq, so for the more mathematically-minded\ncontributors that want a good challenge, see what you can prove about CuBitOS!\n\nSPARK uses the Why3 framework and Z3 SMT solver. Good, fast SMT solvers\nare always an area of interest, and CuBitOS might be a good way to benchmark\nthem for other real-world uses.\n\nAncillary Ideas / Research Interest:\n------------------------------------\n* GPU-accelerated SMT solving\n* FPGA-accelerated SMT solver\n* SMT proofs as part of a CI/CD pipeline\n\nCoding Conventions\n==================\n\n| Code element                                   | Convention               |\n|------------------------------------------------|--------------------------|\n|Ada keywords (type, for, loop, etc.)            | all lowercase            |\n|Types (MultibootStruct, PageTableEntry, etc.)   | Capitalized CamelCase    |\n|Package names                                   | Capitalized CamelCase    |\n|Variables, functions (kmain, toHexString, etc.) | uncapitalized camelCase  |\n|Constants (LT_GRAY, KERN_BASE, etc.)            | ALL CAPS                 |\n|Filenames                                       | all lower or snake_case  |\n\nNOTE: if interfacing to an external component, say Multiboot, then\nvariable names should use the same convention as that component's API.\nFor instance, the Multiboot info struct has fields like mem_lower, etc.\n\nWe'll use those names verbatim here for ease of documentation reference.\nThis is not a hard-and-fast rule. If the API names are overly-terse,\nconfusing, use a strange Hungarian notation, or are otherwise flat-out\ndumb, then feel free to rename them in the Ada code.\n\nAvoid overly-terse abbreviations. Common terms like \"kern\" for \"kernel\",\nor \"mem\" for memory, are OK if there's no ambiguity. \"VM\" for virtual\nmemory can be confused with \"virtual machine\", so prefer \"virtmem\" or just\nspell it out completely. Acronyms should only be used if they are widely\nused or a convention of the underlying hardware, like ACPI, \n\nPlease convert tabs to _four_ spaces.\n\nCommits should be LF line endings.\n\nAvoid \"use\" clauses unless otherwise necessary for operators, and then,\nlimit their use to specific subprograms where needed or use the \"use type\"\nclause. This forces the package of a type to be explicitly spelled out,\nand so the package can be easily referenced and jumped to in an editor.\nExceptions to this rule are: \n* Textmode or printing, logging functions.\n* The following standard library packages: System; Interfaces;\nSystem.Storage_Elements;\n\nUse the term \"frame\" when referring to physical memory, and \"page\" when\ndiscussing virtual memory.\n\nPlease use descriptive names for variables, types, etc. We don't lack for\nhard drive space to store the source code, so use longer\nnames (within reason) if they help to foster understanding of the code.\n\nTry to keep lines less than 80 chars wide for the most part, but if\nit negatively affects readability to break a line, then it's OK to bust the\n80-wide limit. End of line comments can go past 80 if it hurts the flow of the\ncode to put them on their own line.\n\nIf SPARK Mode is disabled on a subprogram body, please add a comment why. This\nmay be perfectly valid, i.e. inline asm. However, try and restructure the code\nto enable SPARK Mode - ESPECIALLY subprogram specifications. Sometimes this can\nbe a little painful, i.e. changing functions to procedures with multiple \"out\"\nparams.\n\nCelebrate whitespace. Let the code breathe. Use two newlines after each\nsubprogram body. One newline after a subprogram body is appropriate if the\nsubprograms are minor variations of one another, i.e. overloaded arguments,\nand they are closely grouped together for clarifying their relationship.\n\nUse lots of comments, in gnatdoc format. This is obviously an area where\nopinions differ, but I believe that treating the OS like a library with\nthorough documentation encourages correctness and makes it friendlier to\nnew contributors. This also makes it easier to auto-generate documentation,\nrather than maintain documentation separately. We all know a good API when\nwe see one.\n\n\"But the code will change and the comments will be out of date!\" \n\nSo... uh... just update the comments!\n\nNotes, Cautions, Warnings\n-------------------------\nBorrowing a page from aircraft operator manuals:\n\n* NOTE - Denotes information that is considered important to emphasize\n\n* CAUTION - Denotes information that, if not considered, may result in system\n  crashes or incorrect operation.\n\n* WARNING - Denotes information that, if not considered, may result in loss\n  of user data or damage to the underlying hardware.\n\nData Sizes/Types:\n-----------------\n\n|   Term used         |    Size   |\n|---------------------|-----------|\n|Nibble               |   4 bits  |\n|Byte                 |   8 bits  |\n|Word                 |   16 bits |\n|Dword (double-word)  |   32 bits |\n|Qword (quad-word)    |   64 bits |\n\nThis is included here to avoid the confusion used when describing interfaces\nor hardware components where \"Word\" may mean something other than 16 bits. We\nalways mean 16-bits in the CuBit code when using \"word\" in comments, etc.\n\nGenerally speaking, we'll explicitly state the length of a data type using\nthe Ada Interfaces package, i.e. Unsigned_8, Unsigned_32, etc. The terms above\nmay be used in comments rather than spelling out \"32-bit value\", for instance.\n\nSPARK-isms\n----------\nSPARK functions are not allowed to have any side-effects, so many times,\na procedure is used instead, and an out parameter for the result is required,\nrather than just returning the result. It's a bit painful to assign temporaries\nfor all the procedure results.\n\nPotential Pitfalls for Contributors\n===================================\n\nDuplicated Constants\n--------------------\nDefinitions of constants can't be (easily) shared between the Ada code and\nassembly files, so some of them are duplicated. I've tried to get all the\nconstants used by the assembly files in cubit.inc, along with a note of where\nit might be duplicated in Ada code. Please make sure that if you change any of\nthese values, that they are changed in both places. If you introduce your own\nconstant that's shared between assembly and Ada code - make sure they USE THE\nSAME NAME!\n\nStack \u0026 Secondary Stack Implementation\n--------------------------------------\nCuBit divides the static stack area into per-CPU chunks, each of which\nis split into the primary and secondary stacks for that CPU. The primary\nstack grows down, the secondary stack grows up. The primary stack pointer is\nset for the main CPU in boot.asm, and set for each additional CPU when they\nboot up in boot_ap.asm.\n```\n       STACK_TOP    +-----------------------+\n                    |                       |\n                    | CPU 0 Primary Stack   |\n                    |                       |\n                    +-----------------------+\n                    | CPU 0 Secondary Stack |\n                    +-----------------------+\n                    |                       |\n                    | CPU 1 Primary Stack   |\n                    |                       |\n                    +-----------------------+\n                    | CPU 1 Secondary Stack |\n                    +-----------------------+\n                    |           .           |\n                    |           .           |\n                    |           .           |\n                    +-----------------------+\n                    |                       |\n                    | CPU N Primary Stack   |\n                    |                       |\n                    +-----------------------+\n                    | CPU N Secondary Stack |\n    STACK_BOTTOM    +-----------------------+\n```\nThe secondary stack SS_Init call is made during each CPU boot-up. Secondary\nstack overflows should be detected at runtime, however use caution. During\nsyscalls and interrupts, the process' kernel stack may be in use, which does\nNOT have a secondary stack.\n\nLimitations\n===========\n* Only a single ATA/IDE disk controller is supported\n* Many, many others...\n\nKnown or Suspected Bugs\n=======================\n* Timer calibration and the busy time.sleep procedure are off a bit on \n  VirtualBox and QEMU, about 1s fast every 20s or so. On Bochs they are _way_\n  off.\n* Likely many, many others...\n\nTODOs.\n======\n* `X` means finished\n* `-` means in progress\n\nTODO: Kernel Features\n---------------------\n```\n[ ] There are a lot of potential circular dependencies for just \"proof stuff\",\n    i.e. preconditions where we don't want to call a blockingSleep until \n    interrupts are enabled -\u003e don't want to enable interrupts until the\n    interrupt vector is loaded -\u003e interrupt vector will update the value that\n    blockingSleep depends on. It might make sense to keep a big \"state\"\n    .ads file with nothing but Ghost variables used in SPARK proofs. It would\n    not have any dependencies itself, but could be included by everything else\n    to update their states. Downside is that it might grow huge and unwieldy,\n    and sorta breaks encapsulation. Might make proofs take a long time too.\n\n[X] Put the stack at a more sensible location\n    [X] Per-CPU Stacks\n    [X] Secondary Stacks\n[X] Print out full register dump with exceptions\n[-] Make type-safe more of the address/number conversions I'm doing.\n[-] Error-handling. Need to formalize the mechanism, could get very messy with MP.\n    [X] Exceptions (Last chance handler)\n    [ ] Broadcast panic to other CPUs\n[ ] Figure out a keyboard scancode -\u003e key array scheme with a future eye towards \n    internationalization. Maybe just use SDL's keyboard handling scheme and let them sort it out.\n[X] Physical memory allocator\n    [X] Boot-mem allocator using bitmaps\n    [X] Boot phys memory allocator\n        [X] Keep track of free space as we allocate/free\n    [X] Buddy allocator\n[X] Virtual memory mapper\n    [X] Mark 0 page as not present\n    [X] Re-map kernel pages with appropriate NXE bits, etc. depending on region.\n[-] Virtual memory allocator\n    [-] Demand paging.\n[-] Processes / Threads\n    [ ] Kernel Tasks\n    [X] Usermode\n    [-] Scheduler\n    [ ] Implement killing processes.\n    [ ] Suspend\n    [ ] Sleep / Wakeup\n[-] ACPI tables\n    [X] Find RSDT/XSDT\n    [X] Sane code for parsing these.\n    [-] APIC\n    [ ] HPET\n    [ ] MCFG - PCI express\n    [ ] SSDT?\n[-] I/O APIC\n[-] Multiprocessing\n    [ ] MP Tables (necessary?)\n    [-] LAPIC\n    [ ] X2APIC\n[ ] Hardware\n    [X] MSRs\n    [-] Full CPUID detection\n    [-] Disk drivers\n        [ ] MBR/GPT Partition Table\n    [-] PCI bus\n        [-] Hard Drives\n            [-] ATA\n            [-] AHCI\n    [ ] PCI express\n        [ ] Enhanced Configuration Access Mechanism (ECAM) via MCFG tables\n        [ ] NVMe\n    [ ] Sound\n    [ ] Video Drivers\n        [-] VESA Modes\n[-] Filesystem / VFS Layer\n    [ ] Develop FS-agnostic set of VFS hooks to syscalls\n    [ ] Develop Drive-agnostic set of VFS hooks to hardware\n    [-] Ext2\n[ ] Networking\n    [ ] Interface driver\n    [ ] TCP/IP Stack - RecordFlux should help here.\n[ ] Security\n    [ ] ASLR / KASLR\n    [ ] Disable certain branch speculation behavior (see x86.MSR)\n        [ ] if processor supports IBRS in ARCH_CAPABILITIES\n    [-] KPTI\n        [ ] Disable KPTI if ARCH_CAPABILITIES MSR indicates not susceptible to RDCL\n    [ ] Sensible Kernel-Mode-Setting / Framebuffer / Compositor arrangement\n[ ] Wow Factor / Eye Candy\n    [ ] Sweet GRUB splash screen w/ logo\n[-] Syscalls\n    [X] SYSCALL/SYSRET working\n[ ] Microkernel Concepts?\n    [ ] User-mode drivers?\n    [ ] IPC?\n[-] More formal proofs of kernel correctness\n    [ ] Preventing race conditions - may not be feasible outside of\n        Ravenscar profile, which doesn't really apply to us.\n[-] Implement more of the Ada standard library, especially for Tasks.\n```\n\nTODO: Usermode/Shell\n--------------------\n```\n[-] Init model - should this look like UNIX? Something else?\n[ ] Security Model\n    [-] Codify it\n    [ ] Prove it\n    [ ] Implement it\n[-] IMGUI framework\n```\n\nTODO: Engineering\n-----------------\n```\n[-] Make all package names Uppercase\n[-] Rename all setupXYZ to just setup, since package name is already there.\n[X] New Makefile\n[-] Use gnatdoc format in comments\n    [ ] Edit gnatdoc format so NOTE, CAUTION, WARNING shows up as different\n        colors.\n    [ ] Edit gnatdoc format to ignore the leading and trailing horizontal rules\n[-] Work out a CI/CD pipeline\n    [ ] Proof Step\n    [ ] Unit Testing\n    [X] Build\n    [ ] Integration/Functional Testing\n    [X] Generate Documentation\n    [-] Build installers, isos, etc.\n[ ] Write unit tests\n[ ] Fuzzing\n[ ] Integration tests that run in the OS.\n```\nArchitecture Ideas\n------------------\n* Use system RTC/HPET timers for real-time tasks, perhaps dedicate a CPU\n  scheduler (or more than one) to exclusively run real-time events when\n  they are desired?\n\nDocumentation (work in progress):\n---------------------------------\n\n|  Task                                |   Command   |\n|--------------------------------------|-------------|\n| Create documentation (in build/docs) | `make docs` |\n| Run provers                          | `make prove`|\n| Build html documentation             | `make html` |\n\nTesting \u0026 Debugging Tips\n========================\n\nYou can create an Ext2 disk image and read it in CuBit with these commands,\nshown here for a 128MB disk:\n\n    dd if=/dev/zero of=vhd.img bs=1M count=128\n    mkfs -t ext2 -b 4096 vhd.img\n    mkdir vhd\n    mount -t auto -o loop vhd.img vhd\n\nNow you have an empty filesystem in `vhd/` that you can add files to, mess\naround with permissions, etc. When you're done, unmount the image. Note that\nCuBit's Ext2 implementation currently supports only 4K block sizes.\n\n    umount vhd\n\nNow you have a disk image that you can convert to the VirtualBox format with:\n\n    VBoxManage convertfromraw --format VDI vhd.img vhd.vdi\n\nYou can add the new disk under Storage -\u003e IDE controller in your VM settings.\nYou'll probably want to use the ICH6 chipset. CuBit currently uses the\nancient PIO method for ATA I/O. If you create a disk image and add it to the\nIDE controller with a different chipset, reads will probably fail.\n\nNote that CuBit just reads the Ext2 superblock currently, but progress is\nbeing made with basic filesystem support.\n\nPlease experiment with different amounts of RAM, number of CPUs, etc.\n\nVirtualBox is a good tool for testing, however QEMU is nice when you need to\nuse GDB to track down certain issues. Note that CuBit makes use of some\nfairly recent CPU features, so you'll want to tell QEMU to use a newer\nchipset and CPU. The `-machine q35` and `-cpu Broadwell` options seem to\nwork well.\n\nQEMU command w/o debugger:\n\n    qemu-system-x86_64 -machine q35 -cpu Broadwell -m 64M -cdrom path/to/cubit_kernel.iso\n\nGDB Tips:\n\nRegister add'l info: `rt`\nRegisters: `rg64`\nStack trace: `k`\n\nTo use QEMU to debug:\n\n    qemu-system-x86_64 -machine q35 -cpu Broadwell -s -S -m 4G -cdrom path\\to\\cubit_kernel.iso -serial stdio\n\nQEMU will start in a paused state while it waits for the debugger. \n\nThen run GDB:\n`gdb cubit_kernel` (note: no \".iso\" here, we want the kernel object file itself,\nwhich contains debugging symbols)\n\nTo connect to QEMU: `target remote localhost:1234`\nUse `(gdb) c` to continue.\n\nFrom here, normal gdb commands work, like `break`, `x`, etc.\n\nNote that Hyper-V does not appear to boot the .ISO presently. Other\nvirtualization or emulation platforms are recommended.\n\nInstalling rflx (WIP - not used yet but in planning phase)\n----------------------------------------------------------\n```\ngit clone https://github.com/Componolit/RecordFlux\ninstall \u003e= Python 3.6\ninstall pip\ninstall virtualenv if Python 3 not the default\nsource bin/activate\npython setup.py build\npython setup.py install\nNow the rflx script at bin/rflx should work.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdocandrew%2FCuBit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdocandrew%2FCuBit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdocandrew%2FCuBit/lists"}