Good question. I'd expect, in 32-bit code, "jmp far [mem]" to expect dword offset, word selector. Adding the "word" specifier ("o16 jmp far [mem]" should do the same thing) would expect word offset, word selector (Nasm adds a 66h "operand size override prefix").
This memory arrangement is known to other assemblers as an "fword". In 16-bit code, this would be 32 bits (16:16), and in 32-bit code, 48 bits (32:16). Nasm, being an innocent little assembler, doesn't know no "fword".
I ASSumed 32-bit code (still do), and ASSumed you knew what the memory layout for "jmp far [mem]" looked like. I really have no idea what loading a TSS does. If the offset is "don't care", what offset *do* we end up at? Gotta execute the next instruction at *some* offset, I would think(?). Not something we do from "userland" code, and I haven't gotten far enough into "initializing an OS" to have encountered it.
Since the offset is "don't care"(?), perhaps "mov cs, [mem]" would work? Nasm assembles it, and it works as expected for other segregs - not something we'd "ordinarily" do with cs. Maybe "mov ax, selector"/"mov cs, ax" would work also? Switching cs "on the fly", without also specifying a new offset, is "usually" a bad idea (thus the notion that a far jump is the way to reload cs), but maybe it works with a TSS... dunno.
Glad to hear you got it working, anyway. Maybe you'll post an "example" for us at some point - always looking for examples!
Best,
Frank