First of all let me tell you that you are absolutely right that, if lock variable is initially true then it will never go forward. It blocks all the three process there only.
If you notice then test-set looks like a function, but it's not a function, it's an instruction. Check this,
So, Now question is that what is the meaning of having TestAndSet as instruction? The advantage of having TestAndSet, as instruction is that, When it executes then it executes completely, It never get preempted in between.
Now Consider Lock = False
P1 will go for enter, P1 is going for execution, it gets value false in rv, it sets lock as True, and return false. Due to the false, condition is failed, hence P1 goes for executing critical section.
Now suppose while P1 is in critical section, P2 goes for execution, its gets Lock value true in rv, assigning true in lock and return true, condition is true, it will wait there only.
Similar for P3.
Hence Mutual exclusion preserved.