Since USB HCI initialization contains hand-off from BIOS to OS, yes, you really only need to initialize them. And you need to initialize all of the ones you find. Thankfully, for the most part, these days you only have to initialize XHCI, since no other HCIs exist in modern PCs.zap8600 wrote:So do I need to make a USB controller driver? If I only need to initialize them, then do I use the 1.0, 2.0, or 3.0 controller(s)?
How to make a GDT?
Re: How to make a GDT?
Carpe diem!
Re: How to make a GDT?
Thanks. I'll try to figure out how to initialize XHCI.nullplan wrote: Since USB HCI initialization contains hand-off from BIOS to OS, yes, you really only need to initialize them. And you need to initialize all of the ones you find. Thankfully, for the most part, these days you only have to initialize XHCI, since no other HCIs exist in modern PCs.
I plan on changing my OS to a x86_64 OS. I will use the BOOTBOOT protocol because it has support for booting the kernel from an initial ramdisk, and it can work with multiple platforms (I would like to have my OS run on x86_64 PCs (UEFI & BIOS) and aarch64 (Raspberry Pi 4)). How would I set up the GDT from x86_64, and what is the equivalent of the GDT and IDT in aarch64 (Raspberry Pi 4). How would I enable paging in x86_64 and aarch64?
Re: How to make a GDT?
That is a good idea. Changing from x86 to x86_64 is a change of architecture, and that can be difficult as you start out. So if you start at x86_64, you have less changeover pain.zap8600 wrote:I plan on changing my OS to a x86_64 OS
The AMD64 GDT is basically the same structure as the i386 one. The only differences are that the system call instructions prescribe a certain order of segments, and that you need two segments wherever you actually specify a nonzero base address (the upper segment containing only the high 32-bits of the base address). But I've only ever needed that for the TSS. The TSS looks different in 64-bit mode, and yes, you still need one if you ever plan to switch to user mode. Consult the Intel SDM vol. 3A or AMD APM vol. 2 for more information (depending on taste, really, they basically contain the same information).zap8600 wrote:How would I set up the GDT from x86_64, and what is the equivalent of the GDT and IDT in aarch64 (Raspberry Pi 4). How would I enable paging in x86_64 and aarch64?
You enable paging on AMD64 the same way you do on i386. In fact, you have no choice but to enable paging, since the instruction that enables paging is the instruction that switches to long mode. The page table format is the same as the PAE format (please consult the SDM or APM for details). Only now the third layer is actually a full layer, not just four entries, and there is a fourth layer of page tables. Otherwise, it is pretty similar, just a nice, hierarchical page table system. Switching CR3 requires the page that the instruction is on to be on the same physical page before and after the switch, so that requirement hasn't changed. Most OSes achieve that by mapping the kernel the same way in all address spaces.
As for AArch64, GDT and IDT are entirely x86-specific concepts and simply don't exist on any other architectures. They are an outgrowth of the 8086's interrupt handling mechanism and the 80286's overloading of the segment registers, respectively, and no other architecture has these chips in its lineage. I am unfamiliar with AArch64 specifically, but I do know ARM8 had its interrupt table at a fixed address in memory (no idea if that was virtual or physical memory, and there were ARM8 chips that didn't have paging at all, making the distinction moot). I do know that most RISC CPUs have only a single exception for "external interrupt", and if you want to know more specifically what interrupt occurred, you need to ask the interrupt controller. In any case, I suggest you get some documentation on AArch64 interrupt handling if the topic interests you. But I would counsel against putting two architectures on your plate from the start. Get your OS going on one arch, then the other.
Carpe diem!
Re: How to make a GDT?
That is good to know.nullplan wrote: That is a good idea. Changing from x86 to x86_64 is a change of architecture, and that can be difficult as you start out. So if you start at x86_64, you have less changeover pain.
So if I understood correctly, I don't need to learn something new (which usually takes me from a couple of months to a year or two).nullplan wrote: The AMD64 GDT is basically the same structure as the i386 one. The only differences are that the system call instructions prescribe a certain order of segments, and that you need two segments wherever you actually specify a nonzero base address (the upper segment containing only the high 32-bits of the base address). But I've only ever needed that for the TSS. The TSS looks different in 64-bit mode, and yes, you still need one if you ever plan to switch to user mode. Consult the Intel SDM vol. 3A or AMD APM vol. 2 for more information (depending on taste, really, they basically contain the same information).
I don't think I need to do this since I'm using BOOTBOOT, which automatically loads the kernel into higher half and supports x86_64 kernels. I'm not sure how BOOTBOOT sets up paging though (if it even does).nullplan wrote: You enable paging on AMD64 the same way you do on i386. In fact, you have no choice but to enable paging, since the instruction that enables paging is the instruction that switches to long mode. The page table format is the same as the PAE format (please consult the SDM or APM for details). Only now the third layer is actually a full layer, not just four entries, and there is a fourth layer of page tables. Otherwise, it is pretty similar, just a nice, hierarchical page table system. Switching CR3 requires the page that the instruction is on to be on the same physical page before and after the switch, so that requirement hasn't changed. Most OSes achieve that by mapping the kernel the same way in all address spaces.
Will do. Thanks.nullplan wrote: As for AArch64, GDT and IDT are entirely x86-specific concepts and simply don't exist on any other architectures. They are an outgrowth of the 8086's interrupt handling mechanism and the 80286's overloading of the segment registers, respectively, and no other architecture has these chips in its lineage. I am unfamiliar with AArch64 specifically, but I do know ARM8 had its interrupt table at a fixed address in memory (no idea if that was virtual or physical memory, and there were ARM8 chips that didn't have paging at all, making the distinction moot). I do know that most RISC CPUs have only a single exception for "external interrupt", and if you want to know more specifically what interrupt occurred, you need to ask the interrupt controller. In any case, I suggest you get some documentation on AArch64 interrupt handling if the topic interests you. But I would counsel against putting two architectures on your plate from the start. Get your OS going on one arch, then the other.
Re: How to make a GDT?
Just to mention, X64 GDT **must** have base and limit fields set to 0, otherwise it will triple fault on real hardware and Hypervisors.
Re: How to make a GDT?
Citation needed. According to the Intel SDM, base is treated as if it is 0 See below:devc1 wrote:Just to mention, X64 GDT **must** have base and limit fields set to 0, otherwise it will triple fault on real hardware and Hypervisors.
The limit is treated as infinity. Note that FS and GS are exceptions; the base of their descriptors is used by the CPU. Note that it also provides MSRs so that we can set all 64 bits of the hidden GS.base and FS.base, instead of the 32 bit window the descriptor exposes. But even for FS and GS, the limit is ignored.Intel SDM wrote:The processor treats the segment base of CS, DS, ES, SS as zero
EDIT: fix error about limit being treated as 0, clarify about FS and GS.
Last edited by nexos on Wed Oct 12, 2022 4:03 pm, edited 1 time in total.
Re: How to make a GDT?
Yes, Intel SDM and AMD APM both say that the base and limit fields are ignored, the base is treated as zero and the limit as infinity (since it is impossible to give more than a 4GB limit). However, a later extensions allows specifying a segment limit within the highest 4GB of address space, which e.g. the Xen hypervisor uses to hide their code at the top of address space. Since it is also possible that some emulator may be less than perfect, you should specify the base as zero and the limit as 4GB for the normal segments. It doesn't really cost you anything, anyway.nexos wrote:Citation needed. According to the Intel SDM, base and limit are treated as if they are 0.
All of this only holds for normal segments, and system segments, like the TSS, must have nonzero base and weird limit, anyway, in order to be useful.
Carpe diem!
-
- Member
- Posts: 510
- Joined: Wed Mar 09, 2011 3:55 am
Re: How to make a GDT?
With respect to the IDT specifically, I'd argue that that's not so much of an outgrowth of Intel segmentation: the 8086 had segments, but a fixed IVT. The VAX was entirely a flat-address-space machine, but had a register that set the base address for a System Control Block, which contained interrupt and exception vectors. And I'd say it's generally good practice in designing a CPU architecture to expose things like that in registers so the OS can put them where it wants them, rather than baking addresses into the microcode.nullplan wrote:
As for AArch64, GDT and IDT are entirely x86-specific concepts and simply don't exist on any other architectures. They are an outgrowth of the 8086's interrupt handling mechanism and the 80286's overloading of the segment registers, respectively, and no other architecture has these chips in its lineage. I am unfamiliar with AArch64 specifically, but I do know ARM8 had its interrupt table at a fixed address in memory (no idea if that was virtual or physical memory, and there were ARM8 chips that didn't have paging at all, making the distinction moot). I do know that most RISC CPUs have only a single exception for "external interrupt", and if you want to know more specifically what interrupt occurred, you need to ask the interrupt controller. In any case, I suggest you get some documentation on AArch64 interrupt handling if the topic interests you. But I would counsel against putting two architectures on your plate from the start. Get your OS going on one arch, then the other.
Re: How to make a GDT?
Does anyone know if the BOOTBOOT protocol allows you to setup the GDT and paging by yourself?
Re: How to make a GDT?
Any boot loader lets you set up your own GDT, IDT, and paging tables.
Re: How to make a GDT?
Can you setup the GDT, the IDT, and paging after the x86_64 kernel starts running?iansjack wrote: Any boot loader lets you set up your own GDT, IDT, and paging tables.
Re: How to make a GDT?
You need a GDT and paging to be in long mode. But there’s nothing to stop you then creating new ones to your own specification. It’s highly unlikely that you would permanently use those provided by the boot loader.
Re: How to make a GDT?
So I can setup paging and the GDT from the kernel? How would I do that?iansjack wrote: You need a GDT and paging to be in long mode. But there’s nothing to stop you then creating new ones to your own specification. It’s highly unlikely that you would permanently use those provided by the boot loader.
Re: How to make a GDT?
Exactly the same way that you would in a boot loader. Create the tables, load the appropriate registers, and do a long jump.
Re: How to make a GDT?
Can BOOTBOOT load x86 code? If I understand correctly, BOOTBOOT will need to load the x86 part of the kernel, then the GDT and paging will be setup. Then everything needed to enter long mode will be setup. Once the code enters long mode, the main kernel code can be ran. Or should I just make my own bootloader? If I should, then I would like it to boot from UEFI.iansjack wrote: Exactly the same way that you would in a boot loader. Create the tables, load the appropriate registers, and do a long jump.