Switching taks in 64 bit mode.

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
antoni
Member
Member
Posts: 61
Joined: Sun May 24, 2020 9:11 am
Location: /dev/null

Switching taks in 64 bit mode.

Post by antoni »

In order to switch tasks, I need to load new stack pointer, instruction pointer and PML4 pointer AT ONCE. I also need to restore process registers etc., but this can be done without involving any features designed to deal with task switching.

In protected mode it's easy (I think). You just fill TSS with these values. In long mode, however, TSS only holds stack pointers for each ring + interrupt stack table? I wonder how this works. How is it possible to load new rsp, rip and cr3 at oce in 64 bit mode?
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Switching taks in 64 bit mode.

Post by iansjack »

Why do you need to load them AT ONCE?
User avatar
pvc
Member
Member
Posts: 201
Joined: Mon Jan 15, 2018 2:27 pm

Re: Switching taks in 64 bit mode.

Post by pvc »

You don't have to load all of these at exactly the same time. You only have to make sure to do that inside one ISR. You update CR3 manually before returning from the ISR. Then you update RSP in assembler part of your ISR. All other general purpose registers are (presumably) reloaded by the rest of assembler part of your ISR. And finally, RFLAGS and RIP are reloaded by IRET instruction.

For this all to happen without crashing, you need at least your ISR code and both stacks mapped in both address spaces. Usually whole kernel space is common to all processes so this is not a problem.
Exact sequence may be different for your project, but general idea is something like presented above.
antoni
Member
Member
Posts: 61
Joined: Sun May 24, 2020 9:11 am
Location: /dev/null

Re: Switching taks in 64 bit mode.

Post by antoni »

When I load programs, I set the virtual addresses of each segment as it's written in the header. These are some random (from kernel's point of view) addresses and may conflict with addresses in the kernel address space. That's why I make a new address space disjoint with kernel address space.

But here comes the problem - after loading new cr3 I can't execute any more instructions from kernel. Also, after jumping to entry point I can no longer do anything either, of course. In particular, usually even the rip is outside that address space, so even if I copied a little program doing what I want to that address space, I wouldn't have a way to jump to it.
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Switching taks in 64 bit mode.

Post by iansjack »

The conventional way of doing this is to reserve part of memory for the kernel and a separate part for the user program (all programs normally use the same virtual addresses, which are mapped to different physical addresses). The kernel address space is mapped the same in the page tables for all tasks, so the problems you mention don't arise.
Post Reply