things are slightly more complicated, SWAPGS instruction is used just before transfer from ring0 to ring3 (win x64 uses 2 instructions for that: IRETQ, SYSRETQ) and as early instruction when entering ring0 from ring3 (interrupt, SYSCALL instruction), the SWAPGS instruction just swaps GS bases of ring0 and ring3
you can use kernel debugger and locate the SwapContext procedure (symbols required, procedure is not exported) to see what the OS is doing, this procedure can be also found using hypervisor (I had such task quite ago, decided that hypervisor is the easiest way to locate the proc on any PC when symbols are not available which includes PCs of common users, PCs with feature versions of win x64)
the SwapContext proc has more input params, the 3 most interesting (win x64) are:
RBX = current PRCB
RDI = address of previous thread (leaving context)
RSI = address of next thread (entering context)
the answer for the initial post in this thread is:
the GS base of ring0 is obtained from RBX and is written into MSR C0000101
the GS base of ring3 is obtained from RSI and is written into MSR C0000102 and will be accessible (instructions with GS prefix) after executing SWAPGS instruction
the FS base points somewhere but is not loaded in SwapContext (I was not intereseted in FS base, it was useless for my task)
note that SwapContext is called not only in case of scheduling new thread to run, it is also called as a result of procedures like ...AttachProcess / ...DetachProcess (that complicated my task a lot, had to indetify only context switches for scheduling new thread to run and exclude clones of AttachProcess which are used quite frequently for things like synchronization events, calls of ring3 debugger accessing memory of another ring3 process)
hypervisor-based solutions developer (Intel, AMD)