diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -3,3 +3,5 @@
 This package allows Haskell users to easily acquire entropy for use in
 critical security applications by calling out to either windows crypto api,
 unix/linux's `/dev/urandom`, or the RDRAND instruction.
+
+This package supports Windows, {li,u}nix, QNX, and has preliminary support for HaLVM.
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -29,7 +29,7 @@
 cArgs = ["-DHAVE_RDRAND"]
 
 cArgsHC :: [String]
-cArgsHC = map ("-optc" ++) cArgs
+cArgsHC = cArgs ++ map ("-optc" ++) cArgs
 
 canUseRDRAND :: FilePath -> IO Bool
 canUseRDRAND cc = do
diff --git a/System/Entropy.hs b/System/Entropy.hs
--- a/System/Entropy.hs
+++ b/System/Entropy.hs
@@ -4,216 +4,35 @@
  Stability: beta
  Portability: portable
 
- Obtain entropy from system sources.
- Currently, windows and *nix systems with a @/dev/urandom@ are supported.
--}
-
-module System.Entropy
-	( getEntropy
-	, CryptHandle
-	, openHandle
-	, hGetEntropy
-	, closeHandle
-	) where
-
-import Control.Monad (liftM)
-import Data.ByteString as B
-import System.IO.Error (mkIOError, eofErrorType, ioeSetErrorString)
-import Foreign (allocaBytes)
+ Obtain entropy from system sources or x86 RDRAND when available.
 
-#if defined(isWindows)
-{- C example for windows rng - taken from a blog, can't recall which one but thank you!
-        #include <Windows.h>
-        #include <Wincrypt.h>
-        ...
-        //
-        // DISCLAIMER: Don't forget to check your error codes!!
-        // I am not checking as to make the example simple...
-        //
-        HCRYPTPROV hCryptCtx = NULL;
-        BYTE randomArray[128];
+ Currently supporting:
 
-        CryptAcquireContext(&hCryptCtx, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
-        CryptGenRandom(hCryptCtx, 128, randomArray);
-        CryptReleaseContext(hCryptCtx, 0);
+    - Windows via CryptoAPO
+    - *nix systems via @\/dev\/urandom@
+    - QNX
+    - Xen only when RDRAND is available.
 -}
 
-import Data.ByteString.Internal as BI
-import Data.Int (Int32)
-import Data.Word (Word32, Word8)
-import Foreign.C.String (CString, withCString)
-import Foreign.C.Types
-import Foreign.Ptr (Ptr, nullPtr, castPtr)
-import Foreign.Marshal.Alloc (alloca)
-import Foreign.Marshal.Utils (toBool)
-import Foreign.Storable (peek)
-
-#ifdef HAVE_RDRAND
-foreign import ccall unsafe "cpu_has_rdrand"
-   c_cpu_has_rdrand :: IO CInt
-
-foreign import ccall unsafe "get_rand_bytes"
-  c_get_rand_bytes :: Ptr CUChar -> CSize -> IO CInt
-
-cpuHasRdRand :: IO Bool
-cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
-#endif
-
-data CryptHandle
-    = CH Word32
-#ifdef HAVE_RDRAND
-    | UseRdRand
-#endif
-
--- Define the constants we need from WinCrypt.h 
-msDefProv :: String
-msDefProv = "Microsoft Base Cryptographic Provider v1.0"
-provRSAFull :: Word32
-provRSAFull = fromIntegral 1
-cryptVerifyContext :: Word32
-cryptVerifyContext = fromIntegral 0xF0000000
-
--- Declare the required CryptoAPI imports 
-foreign import stdcall unsafe "CryptAcquireContextA"
-   c_cryptAcquireCtx :: Ptr Word32 -> CString -> CString -> Word32 -> Word32 -> IO Int32
-foreign import stdcall unsafe "CryptGenRandom"
-   c_cryptGenRandom :: Word32 -> Word32 -> Ptr Word8 -> IO Int32
-foreign import stdcall unsafe "CryptReleaseContext"
-   c_cryptReleaseCtx :: Word32 -> Word32 -> IO Int32
-
-cryptAcquireCtx :: IO Word32
-cryptAcquireCtx = 
-   alloca $ \handlePtr -> 
-      withCString msDefProv $ \provName -> do
-         stat <- c_cryptAcquireCtx handlePtr nullPtr provName (fromIntegral 1) (fromIntegral cryptVerifyContext)
-         if (toBool stat)
-            then peek handlePtr
-            else fail "c_cryptAcquireCtx"
-
-cryptGenRandom :: Word32 -> Int -> IO B.ByteString
-cryptGenRandom h i = 
-   BI.create i $ \c_buffer -> do
-      stat <- c_cryptGenRandom (fromIntegral h) (fromIntegral i) c_buffer
-      if (toBool stat)
-         then return ()
-         else fail "c_cryptGenRandom"
-
-cryptReleaseCtx :: Word32 -> IO ()
-cryptReleaseCtx h = do
-   stat <- c_cryptReleaseCtx h 0
-   if (toBool stat)
-      then return ()
-      else fail "c_cryptReleaseCtx"
-
--- |Inefficiently get a specific number of bytes of cryptographically
--- secure random data using the system-specific facilities.
---
--- This function will return zero bytes
--- on platforms without a secure RNG!
-getEntropy :: Int -> IO B.ByteString
-getEntropy n = do
-#ifdef HAVE_RDRAND
-    b <- cpuHasRdRand
-    if b then hGetEntropy UseRdRand n
-         else do
-#endif
-   h <- cryptAcquireCtx
-   bs <- cryptGenRandom h n
-   let !bs' = bs
-   cryptReleaseCtx h
-   return bs'
-
--- |Open a handle from which random data can be read
-openHandle :: IO CryptHandle
-openHandle = do
-#ifdef HAVE_RDRAND
-    b <- cpuHasRdRand
-    if b then return UseRdRand
-         else do
-#endif
-    liftM CH cryptAcquireCtx
-
--- |Close the `CryptHandle`
-closeHandle (CH h) = cryptReleaseCtx h
-
--- |Read from `CryptHandle`
-hGetEntropy :: CryptHandle -> Int -> IO B.ByteString 
-hGetEntropy (CH h) = cryptGenRandom h
-#ifdef HAVE_RDRAND
-hGetEntropy UseRdRand =
-    B.create n $ \ptr ->  do
-                r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
-                when (r /= 0)
-                     (fail "RDRand failed to gather entropy")
-#endif
-
+module System.Entropy
+        ( getEntropy,
+#if defined(isWindows)
+         module System.EntropyWindows
+        ) where
+import System.EntropyWindows
 #else
-{- Not windows, assuming nix with a /dev/urandom -}
-import System.Posix (openFd, closeFd, fdReadBuf, OpenMode(..), defaultFileFlags, Fd)
-import Foreign.Ptr
-
-source :: FilePath
-source = "/dev/urandom"
-
--- |Handle for manual resource mangement
-data CryptHandle
-    = CH Fd
-#ifdef HAVE_RDRAND
-    | UseRdRand
-#endif
-
--- |Open a `CryptHandle`
-openHandle :: IO CryptHandle
-openHandle = do
-#ifdef HAVE_RDRAND
-    b <- cpuHasRdRand
-    if b then return UseRdRand
-         else do
-#endif
-    liftM CH (openFd source ReadOnly Nothing defaultFileFlags)
-
--- |Close the `CryptHandle`
-closeHandle :: CryptHandle -> IO ()
-closeHandle (CH h) = closeFd h
-#ifdef HAVE_RDRAND
-closeHandle UseRdRand = return ()
-#endif
-
-fdReadBS :: Fd -> Int -> IO B.ByteString
-fdReadBS fd n = do
-    allocaBytes n $ \buf -> do
-        rc <- fdReadBuf fd buf (fromIntegral n)
-        case rc of
-            0 -> ioError (ioeSetErrorString (mkIOError eofErrorType "fdRead" Nothing Nothing) "EOF")
-            n' -> B.packCStringLen (castPtr buf, fromIntegral n')
-
--- |Read random data from a `CryptHandle`
-hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
-hGetEntropy (CH h) = fdReadBS h
-#ifdef HAVE_RDRAND
-hGetEntropy UseRdRand = \n -> do
-    B.create n $ \ptr ->  do
-                r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
-                when (r /= 0)
-                     (fail "RDRand failed to gather entropy")
+         module System.EntropyNix
+        ) where
+import System.EntropyNix
 #endif
 
-#ifdef HAVE_RDRAND
-foreign import ccall unsafe "cpu_has_rdrand"
-   c_cpu_has_rdrand :: IO CInt
-
-foreign import ccall unsafe "get_rand_bytes"
-  c_get_rand_bytes :: Ptr CUChar -> CSize -> IO CInt
-
-cpuHasRdRand :: IO Bool
-cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
-#endif
+import qualified Data.ByteString as B
 
 -- |Inefficiently get a specific number of bytes of cryptographically
 -- secure random data using the system-specific facilities.
 --
 -- Use '/dev/urandom' on *nix and CryptAPI when on Windows.  In short,
--- this entropy is considered "cryptographically secure" but not true
+-- this entropy is considered cryptographically secure but not true
 -- entropy.
 getEntropy :: Int -> IO B.ByteString
 getEntropy n = do
@@ -221,5 +40,3 @@
     e <- hGetEntropy h n
     closeHandle h
     return e
-#endif
-{- OS Test -}
diff --git a/System/EntropyNix.hs b/System/EntropyNix.hs
new file mode 100644
--- /dev/null
+++ b/System/EntropyNix.hs
@@ -0,0 +1,111 @@
+{-# LANGUAGE CPP, ForeignFunctionInterface, BangPatterns, ScopedTypeVariables #-}
+{-|
+ Maintainer: Thomas.DuBuisson@gmail.com
+ Stability: beta
+ Portability: portable
+
+ Obtain entropy from system sources or x86 RDRAND when available.
+
+-}
+
+module System.EntropyNix
+        ( CryptHandle
+        , openHandle
+        , hGetEntropy
+        , closeHandle
+        ) where
+
+import Control.Monad (liftM, when)
+import Data.ByteString as B
+import System.IO.Error (mkIOError, eofErrorType, ioeSetErrorString)
+
+import Foreign (allocaBytes)
+import Foreign.Ptr
+import Foreign.C.Types
+import Data.ByteString.Internal as B
+
+#ifdef XEN
+data CryptHandle = UseRdRand -- or die trying
+#else
+
+import System.Posix (openFd, closeFd, fdReadBuf, OpenMode(..), defaultFileFlags, Fd)
+
+source :: FilePath
+source = "/dev/urandom"
+
+-- |Handle for manual resource mangement
+data CryptHandle
+    = CH Fd
+#ifdef HAVE_RDRAND
+    | UseRdRand
+#endif
+#endif
+
+-- |Open a `CryptHandle`
+openHandle :: IO CryptHandle
+openHandle = do
+#ifdef HAVE_RDRAND
+    b <- cpuHasRdRand
+    if b then return UseRdRand
+         else nonRDRandHandle
+#else
+              nonRDRandHandle
+#endif
+ where
+#ifdef XEN
+  nonRDRandHandle :: IO CryptHandle
+  nonRDRandHandle = error "entropy: On halvm there is no entropy other than RDRAND."
+#else
+  nonRDRandHandle :: IO CryptHandle
+  nonRDRandHandle = liftM CH (openFd source ReadOnly Nothing defaultFileFlags)
+#endif
+
+-- |Close the `CryptHandle`
+closeHandle :: CryptHandle -> IO ()
+#ifndef XEN
+closeHandle (CH h) = closeFd h
+#endif
+#ifdef HAVE_RDRAND
+closeHandle UseRdRand = return ()
+#endif
+
+-- |Read random data from a `CryptHandle`
+#ifdef XEN
+hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
+hGetEntropy UseRdRand = \n -> do
+    B.create n $ \ptr ->  do
+                r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
+                when (r /= 0)
+                     (fail "RDRand failed to gather entropy")
+#else
+hGetEntropy :: CryptHandle -> Int -> IO B.ByteString
+hGetEntropy (CH h) = fdReadBS h
+#ifdef HAVE_RDRAND
+hGetEntropy UseRdRand = \n -> do
+    B.create n $ \ptr ->  do
+                r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
+                when (r /= 0)
+                     (fail "RDRand failed to gather entropy")
+#endif
+
+fdReadBS :: Fd -> Int -> IO B.ByteString
+fdReadBS fd n = do
+    allocaBytes n $ \buf -> do
+        rc <- fdReadBuf fd buf (fromIntegral n)
+        case rc of
+            0 -> ioError (ioeSetErrorString (mkIOError eofErrorType "fdRead" Nothing Nothing) "EOF")
+            n' -> B.packCStringLen (castPtr buf, fromIntegral n')
+#endif
+
+
+#ifdef HAVE_RDRAND
+foreign import ccall unsafe "cpu_has_rdrand"
+   c_cpu_has_rdrand :: IO CInt
+
+foreign import ccall unsafe "get_rand_bytes"
+  c_get_rand_bytes :: Ptr CUChar -> CSize -> IO CInt
+
+cpuHasRdRand :: IO Bool
+cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
+#endif
+
diff --git a/System/EntropyWindows.hs b/System/EntropyWindows.hs
new file mode 100644
--- /dev/null
+++ b/System/EntropyWindows.hs
@@ -0,0 +1,128 @@
+{-# LANGUAGE CPP, ForeignFunctionInterface, BangPatterns, ScopedTypeVariables #-}
+{-|
+ Maintainer: Thomas.DuBuisson@gmail.com
+ Stability: beta
+ Portability: portable
+
+ Obtain entropy from system sources or x86 RDRAND when available.
+-}
+
+module System.EntropyWindows
+        ( CryptHandle
+        , openHandle
+        , hGetEntropy
+        , closeHandle
+        ) where
+
+import Control.Monad (liftM, when)
+import System.IO.Error (mkIOError, eofErrorType, ioeSetErrorString)
+import Foreign (allocaBytes)
+import Data.ByteString as B
+import Data.ByteString.Internal as BI
+import Data.Int (Int32)
+import Data.Word (Word32, Word8)
+import Foreign.C.String (CString, withCString)
+import Foreign.C.Types
+import Foreign.Ptr (Ptr, nullPtr, castPtr)
+import Foreign.Marshal.Alloc (alloca)
+import Foreign.Marshal.Utils (toBool)
+import Foreign.Storable (peek)
+
+{- C example for windows rng - taken from a blog, can't recall which one but thank you!
+        #include <Windows.h>
+        #include <Wincrypt.h>
+        ...
+        //
+        // DISCLAIMER: Don't forget to check your error codes!!
+        // I am not checking as to make the example simple...
+        //
+        HCRYPTPROV hCryptCtx = NULL;
+        BYTE randomArray[128];
+
+        CryptAcquireContext(&hCryptCtx, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
+        CryptGenRandom(hCryptCtx, 128, randomArray);
+        CryptReleaseContext(hCryptCtx, 0);
+-}
+
+
+#ifdef HAVE_RDRAND
+foreign import ccall unsafe "cpu_has_rdrand"
+   c_cpu_has_rdrand :: IO CInt
+
+foreign import ccall unsafe "get_rand_bytes"
+  c_get_rand_bytes :: Ptr CUChar -> CSize -> IO CInt
+
+cpuHasRdRand :: IO Bool
+cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
+#endif
+
+data CryptHandle
+    = CH Word32
+#ifdef HAVE_RDRAND
+    | UseRdRand
+#endif
+
+-- Define the constants we need from WinCrypt.h 
+msDefProv :: String
+msDefProv = "Microsoft Base Cryptographic Provider v1.0"
+provRSAFull :: Word32
+provRSAFull = 1
+cryptVerifyContext :: Word32
+cryptVerifyContext = fromIntegral 0xF0000000
+
+-- Declare the required CryptoAPI imports 
+foreign import stdcall unsafe "CryptAcquireContextA"
+   c_cryptAcquireCtx :: Ptr Word32 -> CString -> CString -> Word32 -> Word32 -> IO Int32
+foreign import stdcall unsafe "CryptGenRandom"
+   c_cryptGenRandom :: Word32 -> Word32 -> Ptr Word8 -> IO Int32
+foreign import stdcall unsafe "CryptReleaseContext"
+   c_cryptReleaseCtx :: Word32 -> Word32 -> IO Int32
+
+cryptAcquireCtx :: IO Word32
+cryptAcquireCtx =
+   alloca $ \handlePtr -> 
+      withCString msDefProv $ \provName -> do
+         stat <- c_cryptAcquireCtx handlePtr nullPtr provName provRSAFull cryptVerifyContext
+         if (toBool stat)
+            then peek handlePtr
+            else fail "c_cryptAcquireCtx"
+
+cryptGenRandom :: Word32 -> Int -> IO B.ByteString
+cryptGenRandom h i = 
+   BI.create i $ \c_buffer -> do
+      stat <- c_cryptGenRandom h (fromIntegral i) c_buffer
+      if (toBool stat)
+         then return ()
+         else fail "c_cryptGenRandom"
+
+cryptReleaseCtx :: Word32 -> IO ()
+cryptReleaseCtx h = do
+   stat <- c_cryptReleaseCtx h 0
+   if (toBool stat)
+      then return ()
+      else fail "c_cryptReleaseCtx"
+
+-- |Open a handle from which random data can be read
+openHandle :: IO CryptHandle
+openHandle = do
+#ifdef HAVE_RDRAND
+    b <- cpuHasRdRand
+    if b then return UseRdRand
+         else do
+#endif
+                  liftM CH cryptAcquireCtx
+
+-- |Close the `CryptHandle`
+closeHandle :: CryptHandle -> IO ()
+closeHandle (CH h) = cryptReleaseCtx h
+
+-- |Read from `CryptHandle`
+hGetEntropy :: CryptHandle -> Int -> IO B.ByteString 
+hGetEntropy (CH h) n = cryptGenRandom h n
+#ifdef HAVE_RDRAND
+hGetEntropy UseRdRand n =
+    BI.create n $ \ptr ->  do
+                r <- c_get_rand_bytes (castPtr ptr) (fromIntegral n)
+                when (r /= 0)
+                     (fail "RDRand failed to gather entropy")
+#endif
diff --git a/entropy.cabal b/entropy.cabal
--- a/entropy.cabal
+++ b/entropy.cabal
@@ -1,5 +1,5 @@
 name:           entropy
-version:        0.2.2.4
+version:        0.3
 description:    A platform independent method to obtain cryptographically strong entropy 
                 (urandom on Linux, CryptAPI on Windows, patches welcome). 
                 Users looking for cryptographically strong (number-theoretically
@@ -14,20 +14,33 @@
 homepage:       https://github.com/TomMD/entropy
 bug-reports:    https://github.com/TomMD/entropy/issues
 stability:      stable
+-- build-type:  Simple
+-- ^^ Used for HaLVM
 build-type:        Custom
-cabal-version:     >=1.10
+-- ^^ Test for RDRAND support using 'ghc'
+cabal-version:  >=1.10
 tested-with:    GHC == 7.6.3
 -- data-files:
 extra-source-files:   ./cbits/rdrand.c, ./cbits/rdrand.h, README.md
 
+-- Notice to compile  with HaLVM the above 'build-type' must be changed
+-- to 'Simple' instead of 'Custom'.  The current build system naively
+-- runs GHC to determine if the compiler supports RDRAND before proceeding.
+flag halvm
+    description:        Build for the HaLVM
+    default:            False
 library
-  ghc-options:  -Wall -O2
+  ghc-options:  -O2
   exposed-modules: System.Entropy
+  if os(windows)
+    other-modules: System.EntropyWindows
+  else
+    other-modules: System.EntropyNix
   other-extensions:    CPP, ForeignFunctionInterface, BangPatterns, ScopedTypeVariables
   build-depends: base == 4.*, bytestring
-  -- hs-source-dirs:
-  -- other-modules:
   default-language:    Haskell2010
+  if(flag(halvm))
+    cpp-options: -DXEN -DHAVE_RDRAND
   if arch(x86_64)
     cpp-options: -Darch_x86_64
     c-sources:    cbits/rdrand.c
@@ -36,7 +49,8 @@
     cpp-options: -DisWindows
     extra-libraries: advapi32
   else
-    Build-Depends: unix
+    if !flag(halvm)
+       Build-Depends: unix
 
 source-repository head
     type:       git
