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
[-- Attachment #1 --]
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
[-- Attachment #2 --]
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>
