Date: Mon, 25 Jul 2011 23:46:46 +0300 From: Mikolaj Golub <trociny@freebsd.org> To: Kostik Belousov <kostikbel@gmail.com> Cc: Marko Zec <zec@freebsd.org>, "Bjoern A. Zeeb" <bz@freebsd.org>, Robert Watson <rwatson@freebsd.org>, freebsd-virtualization@freebsd.org Subject: Re: FIX: accessing module's virtualized global variables from another module Message-ID: <868vrmulzd.fsf@kopusha.home.net> References: <86r55ghzsi.fsf@kopusha.home.net> <20110724151114.GP17489@deviant.kiev.zoral.com.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
--=-=-= On Sun, 24 Jul 2011 18:11:14 +0300 Kostik Belousov wrote: KB> On Sun, Jul 24, 2011 at 11:02:21AM +0300, Mikolaj Golub wrote: >> Also, could someone explain what is kern/link_elf_obj.c for? The patch does >> not deal with this file, but I see the reloactions here similar to those in >> link_elf.c. So I might need to do similar modifiactions in link_elf_obj.c too, >> but I don't know where this code is used (it looks like it is not executed on >> my box, so I don't know how to test it). KB> The link_elf_obj is a linker for architectures that use object file format KB> for the modules. So far, the list consists only of amd64. Thanks! And there is no need in hacks with relocations in this case: in link_elf_load_file() it just allocates space in kernel 'set_vnet' set for 'set_vnet' from the module and sets addr to point to this space. As the fix appears to be link_elf.c specific and the code is used only in this file I have modified the patch placing set_vnet list and its functions in link_elf.c. -- Mikolaj Golub --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=vnet.set_vnet.patch Index: sys/kern/link_elf.c =================================================================== --- sys/kern/link_elf.c (revision 224397) +++ sys/kern/link_elf.c (working copy) @@ -123,6 +123,17 @@ typedef struct elf_file { #endif } *elf_file_t; +#ifdef VIMAGE +struct set_vnet { + uintptr_t vs_start; + uintptr_t vs_stop; + uintptr_t vs_base; + TAILQ_ENTRY(set_vnet) vs_link; +}; + +static TAILQ_HEAD(set_vnet_head, set_vnet) set_vnet_list; +#endif + #include <kern/kern_ctf.c> static int link_elf_link_common_finish(linker_file_t); @@ -345,6 +356,9 @@ link_elf_init(void* arg) (void)link_elf_link_common_finish(linker_kernel_file); linker_kernel_file->flags |= LINKER_FILE_LINKED; +#ifdef VIMAGE + TAILQ_INIT(&set_vnet_list); +#endif } SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_THIRD, link_elf_init, 0); @@ -520,7 +534,89 @@ parse_dpcpu(elf_file_t ef) } #ifdef VIMAGE +static void +set_vnet_insert(struct set_vnet *set) +{ + struct set_vnet *iter; + + TAILQ_FOREACH(iter, &set_vnet_list, vs_link) { + + KASSERT((set->vs_start < iter->vs_start && set->vs_stop < iter->vs_stop) || + (set->vs_start > iter->vs_start && set->vs_stop > iter->vs_stop), + ("vnet sets intersection: to insert: 0x%jx-0x%jx; inserted: 0x%jx-0x%jx", + (uintmax_t)set->vs_start, (uintmax_t)set->vs_stop, + (uintmax_t)iter->vs_start, (uintmax_t)iter->vs_stop)); + + if (iter->vs_start > set->vs_start) { + TAILQ_INSERT_BEFORE(iter, set, vs_link); + break; + } + } + + if (iter == NULL) + TAILQ_INSERT_TAIL(&set_vnet_list, set, vs_link); +} + +static void +set_vnet_remove(struct set_vnet *set) +{ + TAILQ_REMOVE(&set_vnet_list, set, vs_link); +} + +static struct set_vnet * +set_vnet_search(uintptr_t addr) +{ + struct set_vnet *set; + + TAILQ_FOREACH(set, &set_vnet_list, vs_link) { + if (addr < set->vs_start) + return (NULL); + if (addr < set->vs_stop) + return (set); + } + return (NULL); +} + +static void +set_vnet_add(uintptr_t start, uintptr_t stop, uintptr_t base) +{ + struct set_vnet *set; + + set = malloc(sizeof(*set), M_LINKER, M_WAITOK); + set->vs_start = start; + set->vs_stop = stop; + set->vs_base = base; + set_vnet_insert(set); +} + +static void +set_vnet_delete(uintptr_t start) +{ + struct set_vnet *set; + + set = set_vnet_search(start); + KASSERT(set != NULL, ("deleting unknown vnet set (start = 0x%jx)", + (uintmax_t)start)); + set_vnet_remove(set); + free(set, M_LINKER); +} + static int +set_vnet_find(uintptr_t addr, uintptr_t *start, uintptr_t *base) +{ + struct set_vnet *set; + + set = set_vnet_search(addr); + if (set != NULL) { + *start = set->vs_start; + *base = set->vs_base; + return (1); + } else { + return (0); + } +} + +static int parse_vnet(elf_file_t ef) { int count; @@ -544,6 +640,7 @@ parse_vnet(elf_file_t ef) return (ENOSPC); memcpy((void *)ef->vnet_base, (void *)ef->vnet_start, count); vnet_data_copy((void *)ef->vnet_base, count); + set_vnet_add(ef->vnet_start, ef->vnet_stop, ef->vnet_base); return (0); } @@ -1000,6 +1097,7 @@ link_elf_unload_file(linker_file_t file) if (ef->vnet_base != 0) { vnet_data_free((void *)ef->vnet_base, ef->vnet_stop - ef->vnet_start); + set_vnet_delete(ef->vnet_start); } #endif #ifdef GDB @@ -1438,6 +1536,10 @@ elf_lookup(linker_file_t lf, Elf_Size symidx, int elf_file_t ef = (elf_file_t)lf; const Elf_Sym *sym; const char *symbol; + Elf_Addr addr; +#ifdef VIMAGE + uintptr_t vnet_start, vnet_base; +#endif /* Don't even try to lookup the symbol if the index is bogus. */ if (symidx >= ef->nchains) @@ -1469,7 +1571,13 @@ elf_lookup(linker_file_t lf, Elf_Size symidx, int if (*symbol == 0) return (0); - return ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps)); + addr = ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps)); + +#ifdef VIMAGE + if (set_vnet_find(addr, &vnet_start, &vnet_base)) + addr = addr - vnet_start + vnet_base; +#endif + return addr; } static void --=-=-=--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?868vrmulzd.fsf>