/****************************************************************************** * xc_hvm_build.c */ #define ELFSIZE 32 #include #include #include "xg_private.h" #include "xc_private.h" #include "xc_elf.h" #include #include #include #include #include #include #define HVM_LOADER_ENTR_ADDR 0x00100000 static int parseelfimage( char *elfbase, unsigned long elfsize, struct domain_setup_info *dsi); static int loadelfimage( char *elfbase, int xch, uint32_t dom, unsigned long *parray, struct domain_setup_info *dsi); static void xc_set_hvm_param(int handle, domid_t dom, int param, unsigned long value) { DECLARE_HYPERCALL; xen_hvm_param_t arg; int rc; hypercall.op = __HYPERVISOR_hvm_op; hypercall.arg[0] = HVMOP_set_param; hypercall.arg[1] = (unsigned long)&arg; arg.domid = dom; arg.index = param; arg.value = value; if ( lock_pages(&arg, sizeof(arg)) != 0 ) { PERROR("Could not lock memory for set parameter"); return; } rc = do_xen_hypercall(handle, &hypercall); unlock_pages(&arg, sizeof(arg)); if (rc < 0) PERROR("set HVM parameter failed (%d)", rc); } static void build_e820map(void *e820_page, unsigned long long mem_size) { struct e820entry *e820entry = (struct e820entry *)(((unsigned char *)e820_page) + E820_MAP_OFFSET); unsigned long long extra_mem_size = 0; unsigned char nr_map = 0; /* * Physical address space from HVM_BELOW_4G_RAM_END to 4G is reserved * for PCI devices MMIO. So if HVM has more than HVM_BELOW_4G_RAM_END * RAM, memory beyond HVM_BELOW_4G_RAM_END will go to 4G above. */ if ( mem_size > HVM_BELOW_4G_RAM_END ) { extra_mem_size = mem_size - HVM_BELOW_4G_RAM_END; mem_size = HVM_BELOW_4G_RAM_END; } /* 0x0-0x9F000: Ordinary RAM. */ e820entry[nr_map].addr = 0x0; e820entry[nr_map].size = 0x9F000; e820entry[nr_map].type = E820_RAM; nr_map++; /* * 0x9F000-0x9F800: SMBIOS tables. * 0x9FC00-0xA0000: Extended BIOS Data Area (EBDA). * TODO: SMBIOS tables should be moved higher (>=0xE0000). * They are unusually low in our memory map: could cause problems? */ e820entry[nr_map].addr = 0x9F000; e820entry[nr_map].size = 0x1000; e820entry[nr_map].type = E820_RESERVED; nr_map++; /* * Following regions are standard regions of the PC memory map. * They are not covered by e820 regions. OSes will not use as RAM. * 0xA0000-0xC0000: VGA memory-mapped I/O. Not covered by E820. * 0xC0000-0xE0000: 16-bit devices, expansion ROMs (inc. vgabios). * TODO: hvmloader should free pages which turn out to be unused. */ /* * 0xE0000-0x0F0000: PC-specific area. We place ACPI tables here. * We *cannot* mark as E820_ACPI, for two reasons: * 1. ACPI spec. says that E820_ACPI regions below * 16MB must clip INT15h 0x88 and 0xe801 queries. * Our rombios doesn't do this. * 2. The OS is allowed to reclaim ACPI memory after * parsing the tables. But our FACS is in this * region and it must not be reclaimed (it contains * the ACPI global lock!). * 0xF0000-0x100000: System BIOS. * TODO: hvmloader should free pages which turn out to be unused. */ e820entry[nr_map].addr = 0xE0000; e820entry[nr_map].size = 0x20000; e820entry[nr_map].type = E820_RESERVED; nr_map++; /* Low RAM goes here. Remove 3 pages for ioreq, bufioreq, and xenstore. */ e820entry[nr_map].addr = 0x100000; e820entry[nr_map].size = mem_size - 0x100000 - PAGE_SIZE * 3; e820entry[nr_map].type = E820_RAM; nr_map++; if ( extra_mem_size ) { e820entry[nr_map].addr = (1ULL << 32); e820entry[nr_map].size = extra_mem_size; e820entry[nr_map].type = E820_RAM; nr_map++; } *(((unsigned char *)e820_page) + E820_MAP_NR_OFFSET) = nr_map; } static void set_hvm_info_checksum(struct hvm_info_table *t) { uint8_t *ptr = (uint8_t *)t, sum = 0; unsigned int i; t->checksum = 0; for (i = 0; i < t->length; i++) sum += *ptr++; t->checksum = -sum; } /* * Use E820 reserved memory 0x9F800 to pass HVM info to hvmloader * hvmloader will use this info to set BIOS accordingly */ static int set_hvm_info(int xc_handle, uint32_t dom, xen_pfn_t *pfn_list, unsigned int vcpus, unsigned int acpi) { char *va_map; struct hvm_info_table *va_hvm; va_map = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, pfn_list[HVM_INFO_PFN]); if ( va_map == NULL ) return -1; va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET); memset(va_hvm, 0, sizeof(*va_hvm)); strncpy(va_hvm->signature, "HVM INFO", 8); va_hvm->length = sizeof(struct hvm_info_table); va_hvm->acpi_enabled = acpi; va_hvm->nr_vcpus = vcpus; set_hvm_info_checksum(va_hvm); munmap(va_map, PAGE_SIZE); return 0; } static int setup_guest(int xc_handle, uint32_t dom, int memsize, char *image, unsigned long image_size, vcpu_guest_context_t *ctxt, unsigned long shared_info_frame, unsigned int vcpus, unsigned int pae, unsigned int acpi, unsigned int store_evtchn, unsigned long *store_mfn) { xen_pfn_t *page_array = NULL; unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT); unsigned long shared_page_nr; shared_info_t *shared_info; void *e820_page; struct domain_setup_info dsi; uint64_t v_end; int rc; memset(&dsi, 0, sizeof(struct domain_setup_info)); if ( (parseelfimage(image, image_size, &dsi)) != 0 ) goto error_out; if ( (dsi.v_kernstart & (PAGE_SIZE - 1)) != 0 ) { PERROR("Guest OS must load to a page boundary.\n"); goto error_out; } v_end = (unsigned long long)memsize << 20; IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" " Loaded HVM loader: %016"PRIx64"->%016"PRIx64"\n" " TOTAL: %016"PRIx64"->%016"PRIx64"\n", dsi.v_kernstart, dsi.v_kernend, dsi.v_start, v_end); IPRINTF(" ENTRY ADDRESS: %016"PRIx64"\n", dsi.v_kernentry); if ( (v_end - dsi.v_start) > ((unsigned long long)nr_pages << PAGE_SHIFT) ) { PERROR("Initial guest OS requires too much space: " "(%lluMB is greater than %lluMB limit)\n", (unsigned long long)(v_end - dsi.v_start) >> 20, ((unsigned long long)nr_pages << PAGE_SHIFT) >> 20); goto error_out; } if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL ) { PERROR("Could not allocate memory.\n"); goto error_out; } for ( i = 0; i < nr_pages; i++ ) page_array[i] = i; for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < nr_pages; i++ ) page_array[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */ rc = xc_domain_memory_populate_physmap( xc_handle, dom, (nr_pages > 0xa0) ? 0xa0 : nr_pages, 0, 0, &page_array[0x00]); if ( (rc == 0) && (nr_pages > 0xc0) ) rc = xc_domain_memory_populate_physmap( xc_handle, dom, nr_pages - 0xc0, 0, 0, &page_array[0xc0]); if ( rc != 0 ) { PERROR("Could not allocate memory for HVM guest.\n"); goto error_out; } if ( xc_domain_translate_gpfn_list(xc_handle, dom, nr_pages, page_array, page_array) ) { PERROR("Could not translate addresses of HVM guest.\n"); goto error_out; } loadelfimage(image, xc_handle, dom, page_array, &dsi); if ( set_hvm_info(xc_handle, dom, page_array, vcpus, acpi) ) { ERROR("Couldn't set hvm info for HVM guest.\n"); goto error_out; } xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae); if ( (e820_page = xc_map_foreign_range( xc_handle, dom, PAGE_SIZE, PR
--- a/Makefile
+++ b/Makefile
@@ -42,8 +42,8 @@ PLATS= aix ansi bsd freebsd generic linu
 
 # What to install.
 TO_BIN= lua luac
-TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
-TO_LIB= liblua.a
+TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp lnum_config.h
+TO_LIB= liblua.a liblua.so.$R
 TO_MAN= lua.1 luac.1
 
 # Lua version and release.
@@ -63,6 +63,7 @@ install: dummy
 	cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
 	cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
 	cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
+	ln -s liblua.so.$R $(INSTALL_LIB)/liblua.so
 	cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
 
 ranlib:
--- a/src/ldo.h
+++ b/src/ldo.h
@@ -46,7 +46,7 @@ LUAI_FUNC int luaD_pcall (lua_State *L,
 LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
 LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
 LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
-LUAI_FUNC void luaD_growstack (lua_State *L, int n);
+LUA_API void luaD_growstack (lua_State *L, int n);
 
 LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
 LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
--- a/src/lfunc.h
+++ b/src/lfunc.h
@@ -18,7 +18,7 @@
                          cast(int, sizeof(TValue *)*((n)-1)))
 
 
-LUAI_FUNC Proto *luaF_newproto (lua_State *L);
+LUA_API Proto *luaF_newproto (lua_State *L);
 LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
 LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
 LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
--- a/src/lmem.h
+++ b/src/lmem.h
@@ -38,9 +38,9 @@
    ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
 
 
-LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
+LUA_API void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
                                                           size_t size);
-LUAI_FUNC void *luaM_toobig (lua_State *L);
+LUA_API void *luaM_toobig (lua_State *L);
 LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
                                size_t size_elem, int limit,
                                const char *errormsg);
--- a/src/lstring.h
+++ b/src/lstring.h
@@ -25,7 +25,7 @@
 
 LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
 LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
-LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
+LUA_API TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
 
 
 #endif
--- a/src/lundump.h
+++ b/src/lundump.h
@@ -17,7 +17,7 @@ LUAI_FUNC Proto* luaU_undump (lua_State*
 LUAI_FUNC void luaU_header (char* h);
 
 /* dump one chunk; from ldump.c */
-LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
+LUA_API int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
 
 #ifdef luac_c
 /* print one chunk; from print.c */
--- a/src/Makefile
+++ b/src/Makefile
@@ -23,6 +23,7 @@ MYLIBS=
 PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
 
 LUA_A=	liblua.a
+LUA_SO= liblua.so
 CORE_O=	lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
 	lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o  \
 	lundump.o lvm.o lzio.o lnum.o
@@ -33,11 +34,12 @@ LUA_T=	lua
 LUA_O=	lua.o
 
 LUAC_T=	luac
-LUAC_O=	luac.o print.o
+LUAC_O=	luac.o print.o lopcodes.o
 
 ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
-ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
+ALL_T= $(LUA_A) $(LUA_SO) $(LUA_T) $(LUAC_T)
 ALL_A= $(LUA_A)
+ALL_SO= $(LUA_SO)
 
 default: $(PLAT)
 
@@ -47,14 +49,23 @@ o:	$(ALL_O)
 
 a:	$(ALL_A)
 
+so:	$(ALL_SO)
+
 $(LUA_A): $(CORE_O) $(LIB_O)
 	$(AR) $@ $(CORE_O) $(LIB_O)	# DLL needs all object files
 	$(RANLIB) $@
 
-$(LUA_T): $(LUA_O) $(LUA_A)
-	$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
+$(LUA_SO): $(CORE_O) $(LIB_O)
+	$(CC) -o $@.$(PKG_VERSION) -shared -Wl,-soname="$@.$(PKG_VERSION)" $?
+	ln -fs $@.$(PKG_VERSION) $@
+
+$(LUA_T): $(LUA_O) $(LUA_SO)
+	$(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUA_O) $(LIBS)
+
+$(LUAC_T): $(LUAC_O) $(LUA_SO)
+	$(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUAC_O) $(LIBS)
 
-$(LUAC_T): $(LUAC_O) $(LUA_A)
+$(LUAC_T)-host: $(LUAC_O) $(LUA_A)
 	$(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
 
 clean:
@@ -96,7 +107,7 @@ generic:
 	$(MAKE) all MYCFLAGS=
 
 linux:
-	$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
+	$(MAKE) all MYCFLAGS+=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
 
 macosx:
 	$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"