[NSWI004] [Teachers at NSWI004] Bug report
Vojtech Horky
horky at d3s.mff.cuni.cz
Wed Dec 16 13:23:51 CET 2020
Hello.
Dne 16. 12. 20 v 0:50 Jura Pelc napsal(a):
>
> Hello,
>
> after nontrivial time spent scanning your assembly code, I figured out
> that during a context switch the entryHi register is not loaded nor
> stored in contexts.
> With your implementation of context.S, tests were failing, caused by
> thread_kill call in global_exception_handler because memory was access
> with an ASID unset.
>
> I coincide it as a bug since context switch should preserve the entire
> context_t structure but entryHi nor CONTEXT_CP0_ENTRYHI_OFFSET was not
> used anywhere in SAVE_REGISTERS nor LOAD_REGISTERS.
>
> I made the following changes, I want someone to concur with my findings.
Actually, for a normal (cooperative) context switch, you probably do not
need to preserve (or touch at all) the CP0 registers. They are mostly
related to exception handling and thus are not needed in cooperative
scheduling.
And in preemptive scenario, their values could not be preserved as they
were just overwritten by the exception.
Hence, for context.S we do not save these registers at all.
However, as you pointed out, you need to set ASIDs that are stored in
EntryHi. We forgot to mention (sorry) that there is cp0_set_asid() that
sets current ASID. We expect you to call this function just before
thread_switch_to (consider that you would also need something like
as_switch_to function for switching between address spaces).
The reason for this split is also that address spaces are not bound with
a single thread, but rather with a process (subtree of threads). Thus it
does not make that much sense to keep ASID together with thread context.
Furthermore, the ASID may become invalid over time and needs to be
checked (and perhaps recycled) whenever switching between address spaces.
Looking at the code again, we do not save EntryHi even into eh_context_t
during an exception (but it is trivial to add it). We somehow assumed
that you would use badvaddr instead of getting VPN2 from EntryHi so we
saved only the most important registers.
Perhaps we should have made context_t and eh_context_t with only the
really-required registers to emphasize this.
Hope this makes sense.
Cheers,
- VH
> ```
> diff --git a/kernel/src/proc/context.S b/kernel/src/proc/context.S
> index 3da3a0c..a43ddef 100644
> --- a/kernel/src/proc/context.S
> +++ b/kernel/src/proc/context.S
> @@ -42,6 +42,8 @@ cpu_switch_context:
> mflo $t1
> sw $t0, CONTEXT_HI_OFFSET($a0)
> sw $t1, CONTEXT_LO_OFFSET($a0)
> + mfc0 $t0, $10
> + sw $t0, CONTEXT_CP0_ENTRYHI_OFFSET($a0)
>
> /*
> * Save the CP0 Status register and disable interrupts (by
> @@ -71,6 +73,8 @@ cpu_switch_context:
> lw $t1, CONTEXT_LO_OFFSET($a1)
> mthi $t0
> mtlo $t1
> + lw $t0, CONTEXT_CP0_ENTRYHI_OFFSET($a1)
> + mtc0 $t0, $10
>
> move $k0, $a1
> LOAD_REGISTERS $k0
> ```
>
>
> --
> S pozdravem Jiří Pelc
> Matematicko-fyzikální fakulta
> Univerzita Karlova
>
More information about the NSWI004
mailing list