Thought I'd reply since I figured out the issue. In HIL, the simulated servo driver,
pwm_out_sim, is started alongside the physical servo driver,
px4fmu. This causes the device name
pwm_output0 (the primary servo channel) to be registered by the simulated driver instead of the physical one. Under normal, non-HIL use, the device name
pwm_output0 is occupied by the physical driver. Under HIL, the physical driver is still started, but it's registered under
pwm_output1, which means it misses all messages, including primary servo commands.
To fix this, I edited the init script (rcS) to not start
pwm_out_sim in HIL. Of course, for this to work, you must also set
armed->lockdown = false, or comment out lines that say
armed->lockdown = true.
It's a little irritating that this wasn't documented - setting lockdown to false is not enough to disable lockdown, you have to disable
pwm_out_sim. And the physical driver didn't throw any warnings, messages, etc. to indicate that it in fact was not registered under the primary servo device name. It took me over a month to figure this out.
Anyway, hope this helps someone.