The whole loop mechanism is based around having a filtered $posts array. So looking in The Loop documentation on multiple loops it gives a PHP explanation for the standard loop code you use:
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
<!-- do stuff ... -->
<?php endwhile; ?>
<?php endif; ?>
The have_posts() and the_post() are convenience wrappers around the global $wp_query object, which is where all of the action is. The $wp_query is called in the blog header and fed query arguments coming in through GET and PATH_INFO. The $wp_query takes the arguments and builds and executes a DB query that results in an array of posts. This array is stored in the object and also returned back to the blog header where it is stuffed into the global $posts array (for backward compatibility with old post loops).
The have_posts() simply calls into $wp_query->have_posts() which checks a loop counter to see if there are any posts left in the post array. And the_post() calls $wp_query->the_post() which advances the loop counter and sets up the global $post variable as well as all of the global post data. Once we have exhausted the loop, have_posts() will return false and we are done.
So the global $posts is connected to the have_posts function. For that to work properly it can only contain the paginated list of posts. Also note that the $posts array is only there for backwards compatibility so its best not to access it directly anyway.
So it looks like you'll have to either set up your own pagination or create a separate object with all posts.
I'd suggest the latter.