With the normall call/return model, the implicit continuation in a normal call stack can only be accessed via return. Green threads do allow accessing the continuation at specific yield points (although most green thread implementations do not expose it to the user) but because the yield point are much fewer than every single call, a whole stack can be allocated and used in one go. There aren't in fact many issues with interoperability as foregin functions or even os calls can be accommodated on this stack.
Async is a tradeoff, basically the programmer is responsible of marking functions that are to be CPS transformed and that need their stack frame reified. This way no full stack is needed nor there are the performance and interoperability issues of full CPS. You end up with the blue/red functions issue though.
Note that you don't get the continuation in hand for the async-everywhere advocated by GP, only blocking operations get the continuation, and most of those are implemented by the runtime.
Continuation passing style means passing along your continuation to your callee, and is the implementation of the async model. But normal calls do pass their continuation: the return address, pushed on the stack, is the continuation function, and the stack itself is the scope, and together they are a closure. Make the stack a first class value that can be switched, and you get to continuations - and that's what the runtime gets with green threads.
It means much harder interop because you can't have native frames on your stack. But you have the same problem with async.