KDF with low-entropy salts
That's a reasonable solution if you can't use a random salt. If you personalize your hash function for your application, then the salt is globally unique for each user. (e.g. use sitename||username as salt) The only salt reuse happening is that older passwords of the same user have the same salt. But that's a very minor issue.

I disagree with Polynomial who wants unpredictable salts. Unpredictability is not necessary for most protocols involving password hashing. Global uniqueness or at least rareness is the decisive property.

To combine sitename and username I'd simply go with concatenating them. Your HMAC suggestion is certainly fine too. Your xor variant gives me a bit of a bad feeling, but is probably fine too.