This is with respect to user-level threads where the kernel only knows about the process as a whole, and threads are created and maintained in the user space. Each thread has its PC, registers, stack and thread control block. To my knowledge, updating PC (or any system register) or access of the code segment can only be done in the kernel mode (since it has to be protected from outside access). If this is true, how can user-level threads maintain (or update) their state information (PC, other registers, thread control block, etc.) at the user level instead of the kernel level?
To put it in short, could anyone please explain what actually happens under the hood, and how thread-level context switches are realised at the user level?