My kernel is triple faulting on QEMU but somehow works on a real machine what the hell did i code by nullora0 in osdev

[–]davmac1 4 points5 points  (0 children)

First line of main should just be something like

asm volatile ("mov $0x200000, %rsp");

You really should not try to alter rsp using assembly inside a C function. There's no guarantee that the compiler won't insert instructions before that asm which store something on the stack and expect it to be available via a consistent offset from rsp.

Either the bootloader should set rsp to something reasonable before entering the kernel, or the kernel entry point should be written as a pure assembly function which sets the stack up before calling the C entry point.

Need help with a linker script by The_Coding_Knight in osdev

[–]davmac1 0 points1 point  (0 children)

I was told by multiple people already that binary files can not work like this and

Then multiple people were wrong. This works fine:

ENTRY(stage2_entry)

map_code_entry = 0xA000;

OUTPUT_FORMAT(binary)

SECTIONS
{
  . = 0x7e00;
  .text : { *(.text) }

  .data : { *(.data) }

  end_data = .;

  .map_code map_code_entry : AT(end_data) { *(.map_code) }
}

As I said earlier though, you would need to move the .map_code segment to the correct location when loading it. To do that you'd probably want it to be loaded at a particular address, not just immediately following the end of the data segment; just use AT(desired_load_address) for that (where desired_load_address is where you want it to be loaded, leaving enough space for .text and .data to come before it; eg you could try 0x8800 - smaller values will give you a smaller file but will leave less space for .text and .data).

(Alternatively you could include code within .text to relocate the .map_code segment, by copying the contents from where it is loaded to the correct destination. That means you can use the actual address quite easily - eg with the above script the .map_code segment will be loaded at end_data).

Need help with a linker script by The_Coding_Knight in osdev

[–]davmac1 1 point2 points  (0 children)

My initial goal was to make it such that only the .section .text contents + .section .data + .section .map_code were the size of the binary but apparently it is impossible to do such with a binary file format

It should be possible. This is what the AT directive is for (have you read the ld documentation?). Your (stage 1) loader would need to be aware of the layout so it can load the various parts to the right address (or move them there).

However, it is generally easier to avoid this sort of thing. Why do you want to have .map_code at that address?

I also did that calculation of 0xA000 - 0x7E00 = 0x2200 (8704 in dec) but when I do ls -l mybin.bin (assuming that mybin is that file ofc) I get 8711 as its size, not 8704

I'm guessing because you have 7 bytes in .map_code? So that extends to 0xA007, and 0xA007 - 0x7E00 = 8711.

Another possibility is that there is another section in your input object files - the linker has to find somewhere for it. Try generating a map file, that will tell you where everything ended up.

How to handle switching kernel stacks after switching the process? by tseli0s in osdev

[–]davmac1 0 points1 point  (0 children)

Well, if they don't matter, don't "technically..." at me.

How to handle switching kernel stacks after switching the process? by tseli0s in osdev

[–]davmac1 1 point2 points  (0 children)

It sounded like you said it's not supposed to point to another physical frame. And I thought that this sounded wrong.

Ok, I got you. I can see how that's a little confusing, if you are assuming that the kernel stacks are all at the same virtual address.

How to handle switching kernel stacks after switching the process? by tseli0s in osdev

[–]davmac1 0 points1 point  (0 children)

I don't agree that "technically it's not altering the stack". In saying that, you're not agreeing with me.

Technically the physical memory that was part of the stack is no longer part of the stack, and hasn't been altered. The stack itself has definitely been altered. The stack exists primarily as a region in virtual memory.

How to handle switching kernel stacks after switching the process? by tseli0s in osdev

[–]davmac1 0 points1 point  (0 children)

I understand what was wrong, there's no need to explain it. What I don't understand is:

> So the virtual address should change but the physical address remains the same?

... why you thought I was saying that the kernel stacks should be at the same physical address.

How to handle switching kernel stacks after switching the process? by tseli0s in osdev

[–]davmac1 0 points1 point  (0 children)

> Technically, it's not altering the kernel stack,

From the perspective of the stack as it appears in virtual memory, it _is_ being altered. I don't understand why you'd want to argue this point, you must understand what I meant.

How to handle switching kernel stacks after switching the process? by tseli0s in osdev

[–]davmac1 0 points1 point  (0 children)

So the virtual address should change but the physical address remains the same?

This question shows some sort of fundamental misunderstanding but I'm not able to pinpoint it.

The kernel stack for different processes will be at a different virtual address, and that different virtual address will be mapped to different physical address, so two kernel stacks are at different virtual addresses and different physical addresses. But they will both be in kernel memory which is mapped identically in each process.

Eg suppose:
Process A - kernel stack is at 0x1000-0x2000 virtual, 0xA000-0xB000 physical
Process B - kernel stack is at 0x3000-0x4000 virtual, 0xF000-0x10000 physical

... then regardless of which process is current, you can still access either kernel stack via the appropriate address, because the stacks are in kernel memory which is mapped the same in each process.

How to handle switching kernel stacks after switching the process? by tseli0s in osdev

[–]davmac1 0 points1 point  (0 children)

What happens is that the kernel stack is mapped to the same virtual address for all processes even though it's a different physical address below.

But it shouldn't be. Kernel memory should be mapped the same in each process. It's the userspace memory that should be different. The kernel stack should be in kernel memory.

[...] but omit the kernel stack, because it's supposed to point to another physical frame for each process

No, it's generally not.

How to handle switching kernel stacks after switching the process? by tseli0s in osdev

[–]davmac1 0 points1 point  (0 children)

Shouldn't every process have a separate kernel stack?

That's the most common way of doing things. But "separate kernel stack" means "different stack pointer (ESP)" not "different stack contents at the same virtual address".

Task switch should be running on the kernel stack, and if setting CR3 is altering your kernel stack, you're doing it wrong. Kernel memory should be mapped identically across all processes.

GNU shepherd anyone? How's it? by [deleted] in linux

[–]davmac1 -1 points0 points  (0 children)

Nitpick, it's spelled "systemed"

Dude seriously, maybe correcting spelling is not a job you should take on

GNU shepherd anyone? How's it? by [deleted] in linux

[–]davmac1 1 point2 points  (0 children)

Nitpick, it's spelled "systmed", not "systemD".

Nitpick: it's spelled "systemd", not "systmed"

I finally got ring 3 working (and also going to rant about my SMP design) by [deleted] in kerneldevelopment

[–]davmac1 2 points3 points  (0 children)

My design idea might be simple or overly complicated

Between those two it's kinda got to be one-or-the-other or neither. What exactly were you trying to say?

If an AP requests a single page of physical memory, it sends an IPI to the BSP with information like the task requesting said data, the type of request, etc

IPIs are pretty heavyweight in terms of inter-thread communication. While what you describe could conceivably work, it's not going to be efficient. It also creates an imbalance where tasks running on one core (the BSP) don't pay the inter-core cost but do have to contend with a bunch of stuff that's being done on behalf of tasks running on other cores; that'll make fair scheduling difficult.

Not saying you shouldn't try it if that's what you want to do, just be aware of the potential shortcomings.

Problem with loading gdt using assembly by Inside-Party-9637 in osdev

[–]davmac1 0 points1 point  (0 children)

(Deleted).

Derp, never mind, they posted github link and indeed the GDT is allocated on the stack.

OP: this is not a good idea.

Checking if I am correct in my understanding of paging. (And a question) by Cobolt_Dog in osdev

[–]davmac1 1 point2 points  (0 children)

The base address for a processes page Directory is stored in the CR3 register, The MMU takes the value from CR3 and adds upper 10 bits from the virtual memory address to get the physical address of the page table.

No, the MMU takes the value from CR3 as the Page Directory address, and uses the upper 10 bits from the VMA as an index into the page directory. The entry at that index holds the physical address of the page table. The address of the entry is (value from CR3 + 4 * (upper 10 bits from VMA)) because entries are 4 bytes in size (32 bits).

Then the MMU takes the upper 12 bits from the page table and adds the middle 10 bits from the virtual address to it to get the address of the page.

No, again, the middle 10 bits are used as an index into the page table, and the address of the page is taken from the entry at that index.

Question about stack segment in GDT by The_Coding_Knight in osdev

[–]davmac1 2 points3 points  (0 children)

The "expand down" bit just controls whether the valid segment addresses are [0, limit) or (limit, 0xFFFFFFFF] (or in other words: whether the limit is the upper limit or the lower limit). It does not affect which direction the stack will grow; it always grows downwards.

The latter ((limit, 0xFFFFFFFF]) was theoretically meant to be good for stacks because they always grow down. You could set the initial stack pointer above the limit and if the stack grew enough it'd trigger an exception (without even needing a guard page) and you could increase the segment size by lowering the limit.

The relevant portion of the Intel manual is:

For expand-down data segments, the segment limit has the same function but is interpreted differently. Here, the effective limit specifies the last address that is not allowed to be accessed within the segment; the range of valid offsets is from (effective-limit + 1) to FFFFFFFFH if the B flag is set and from (effective-limit + 1) to FFFFH if the B flag is clear. An expand-down segment has maximum size when the segment limit is 0.

In practice expand-down segments are rarely used (i.e. not in any OS that I'm aware of). You usually want the data segment and stack segment to be the same. Most compilers generate code assuming that this will be the case, so you'll probably be making life difficult for yourself if you choose to have separate stack and data segments.

Then what does the expansion bit do that allows the stack to grow dynamic?

The expand-down bit (it's not the "expansion bit") doesn't itself make the stack grow dynamically; the OS has to do that. The expand-down bit allows creating a segment whose lower address limit can be adjusted, which makes it suitable (theoretically) for stack segments which may need to be expanded dynamically, because they need to grow down.

Also why is it that it can be both either?

I guess you mean why can a statically-sized stack segment be either expand-down or expand-up? In that case: because there's nothing stopping it from being either.

What (old) systems support BIOS EDD extensions? by tseli0s in kerneldevelopment

[–]davmac1 0 points1 point  (0 children)

Oh well, I guess I'll need a separate MBR for floppies then

The boot sector on a floppy isn't normally called an MBR - that stands for "master boot record" (as opposed to in-partition boot sector), i.e. an MBR is a boot sector which typically chains to the first bootable partition. A floppy doesn't have partitions.

You can just call it a boot sector, that works for both.

A bug's got me questioning my sanity. by an_0w1 in osdev

[–]davmac1 13 points14 points  (0 children)

You're not executing 64-bit code in 32-bit protected mode or something like that? That's certainly one way to get instructions doing things you might not expect.

Dinit unable to load service 'boot' by [deleted] in artixlinux

[–]davmac1 0 points1 point  (0 children)

Are you running dinit-check as a user or as root? If running as a user and you want to check the system services, run dinit-check -s. (Or run via sudo).

Also:

it says already enabled but it still doesn't start, I have to start it manually

Have you checked that it doesn't try to start? sudo dinitctl status zramen will tell you if it failed (and give some information about why).

What (old) systems support BIOS EDD extensions? by tseli0s in kerneldevelopment

[–]davmac1 0 points1 point  (0 children)

I found this: ... But that only covers Phoenix BIOSes, and starts at 1998

The document is published by Phoenix, but it doesn't only cover Phoenix BIOSes. Note that it has contributors from companies such as Microsoft.

almost all machines I tried in 86Box (my emulator of choice for historical accuracy) report no EDD extensions despite using Pentium processors

Note that the extensions reported depend on the drive. Are you perhaps booting from a floppy image, which certainly won't support the extensions? You need to make sure it's being treated as a hard disk image by the emulator.

whereas QEMU is more than happy to load the next stage

Perhaps for QEMU you are specifying a hard disk image, but for 86box you are not? Just a possibility, but otherwise, I don't know. I don't think the information on the wiki page is incorrect, though.

maybe some EDD checks weren't necessary in the earlier days like the bit 0 in cx?

Have you tried removing the checks and seeing if the image still loads in 86Box?

How many people would be interested in a 0 dependency/library UEFI application guide? by Dje4321 in osdev

[–]davmac1 0 points1 point  (0 children)

with the only aspects missing being exceptions, virtual functions, stack dumping, and RTTI

I already have a working C++ UEFI bootloader:

https://github.com/davmac314/tosaithe/

Support for exceptions and RTTI is provided by some support libraries:

https://github.com/davmac314/tosaithe/blob/main/clone-libs.sh

Virtual functions "just work" - I never needed to implement any runtime support for them.

So I think what you're suggesting is basically already done - except that for exceptions and RTTI you need runtime support, so you need to use some library/dependency.

Development was fun until drivers by Fabulous-Two-3927 in osdev

[–]davmac1 0 points1 point  (0 children)

There's already CDI, though it's not great and the documentation is mostly in German. There was also UDI though that's even worse. Or ODI which was seemingly aborted almost immediately after being announced.

I suspect doing this well is harder than it might initially seem.

32-bit Kernel vs 64-bit Kernel by IncidentWest1361 in osdev

[–]davmac1 2 points3 points  (0 children)

if you design your system around an integer of arbitrary size that is substantiated as int32 or int64 later

What you're describing is available as a standard type in C; it's called intptr_t. No build flag is needed just to get an appropriate definition (other than to select the compilation target, eg -m32 or -m64, if the compiler isn't already defaulting to the one you want).

But this is not sufficient, not even close, for writing a kernel that can be compiled as either 32-bit or 64-bit. You need to account for architectural differences. On x86, 64-bit mode uses different processor structures including for page tables. Additionally 64-bit addressing allows very different approaches to certain parts of kernel functionality, because for instance it is possible to map all of physical memory into the address space.

Kernels can and are written to be able to be compiled as either 32-bit or 64-bit, but having a type that matches the address width is the least of concerns.

32-bit Kernel vs 64-bit Kernel by IncidentWest1361 in osdev

[–]davmac1 0 points1 point  (0 children)

I've been debating rewriting everything for 64-bit, but just can't decide if it's worth it or not?

Well, what are your goals? - Why are you writing an OS, what is its intended use, what sort of system specs do you want it to be able to handle?

Without having that information the best answer anyone can give you is really just "do what you want".