Date: Mon, 21 Sep 2009 00:54:59 -0700 From: Julian Elischer <julian@elischer.org> To: FreeBSD virtualization mailing list <freebsd-virtualization@freebsd.org>, Robert Watson <rwatson@freebsd.org>, Marko Zec <zec@FreeBSD.org>, "Bjoern A. Zeeb" <bz@FreeBSD.org> Subject: reducing the memory redirections needed for vnet use. Message-ID: <4AB73152.1020703@elischer.org>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------030507070006070008040707 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit I've been running the folllowing set of diffs as a proof of concept change for a couple of months now. The diff is to cache the vnet address fixup constant in the pcpu area. This means that the address of V_xxx is now (%fs:pcpu_offset)+symbol (*) the cost in the machine dependent part of the scheduler is minimal and I have never been able to measure the difference in context times (though I didn't try that hard). The important partof this however is not so oonbvious. If we wanted to have per-vnet-per-cpu memory for per cpu stats collection in vnets, then this approach becomes the blueprint as to how that must be done. Obviously memory to hold all the data needs to be allocated, but once that is donem the pcpu specific section of the memory need sto be selected by teh scheduerl as teh thread moves between cpus. This patch shows where that would occur, and also, where it would be stored. In the patch the preprocessor variable VNET_PCPU_DATA should be ignored as it is just my personal way of turning the feature on and off for testing. (*) I'm not convinced that the equivalent cannot be done in a single instruction addressing mode on some cpus.. certainly I think it may have been possible on the 68000 family from memory. --------------030507070006070008040707 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="pcpu.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="pcpu.diff" Index: kern/kern_synch.c =================================================================== --- kern/kern_synch.c (revision 197380) +++ kern/kern_synch.c (working copy) @@ -65,6 +65,10 @@ #include <machine/cpu.h> +#if defined(VIMAGE) && defined(VNET_PCPU_DATA) +#include <net/vnet.h> +#endif + #ifdef XEN #include <vm/vm.h> #include <vm/vm_param.h> @@ -447,6 +451,14 @@ PT_UPDATES_FLUSH(); #endif sched_switch(td, newtd, flags); +#if defined(VIMAGE) && defined(VNET_PCPU_DATA) + if (td->td_vnet) { + PCPU_SET(vnet_data_adj, td->td_vnet->vnet_data_base); + } else { + /* Added to a vnet symbol, gives something near 0 */ + PCPU_SET(vnet_data_adj, -VNET_START); + } +#endif KTR_STATE1(KTR_SCHED, "thread", sched_tdname(td), "running", "prio:%d", td->td_priority); Index: kern/kern_fork.c =================================================================== --- kern/kern_fork.c (revision 197380) +++ kern/kern_fork.c (working copy) @@ -540,7 +540,7 @@ td2->td_sigmask = td->td_sigmask; td2->td_flags = TDF_INMEM; -#ifdef VIMAGE +#ifdef VIMAGE /* if we ever make curvnet always valid, change this. */ td2->td_vnet = NULL; td2->td_vnet_lpush = NULL; #endif @@ -817,6 +817,10 @@ td = curthread; p = td->td_proc; +#if defined(VIMAGE) && defined(VNET_PCPU_DATA) + /* if we ever make curvnet always valid, change this. */ + PCPU_SET(vnet_data_adj, (uintptr_t)NULL); +#endif KASSERT(p->p_state == PRS_NORMAL, ("executing process is still new")); CTR4(KTR_PROC, "fork_exit: new thread %p (td_sched %p, pid %d, %s)", Index: net/vnet.c =================================================================== --- net/vnet.c (revision 197380) +++ net/vnet.c (working copy) @@ -145,15 +145,7 @@ * module will find every network stack instance with proper default values. */ -/* - * Location of the kernel's 'set_vnet' linker set. - */ -extern uintptr_t *__start_set_vnet; -extern uintptr_t *__stop_set_vnet; -#define VNET_START (uintptr_t)&__start_set_vnet -#define VNET_STOP (uintptr_t)&__stop_set_vnet - /* * Number of bytes of data in the 'set_vnet' linker set, and hence the total * size of all kernel virtualized global variables, and the malloc(9) type Index: net/vnet.h =================================================================== --- net/vnet.h (revision 197380) +++ net/vnet.h (working copy) @@ -92,6 +92,14 @@ #include <sys/sx.h> /* + * Location of the kernel's 'set_vnet' linker set. + */ +extern uintptr_t *__start_set_vnet; +extern uintptr_t *__stop_set_vnet; + +#define VNET_START (uintptr_t)&__start_set_vnet +#define VNET_STOP (uintptr_t)&__stop_set_vnet +/* * Functions to allocate and destroy virtual network stacks. */ struct vnet *vnet_alloc(void); @@ -107,6 +115,28 @@ * Various macros -- get and set the current network stack, but also * assertions. */ +#ifdef VNET_PCPU_DATA + +#define VNET_PCPU_SET(a, b) PCPU_SET(a, b) + +#define CURVNET_DO_RESTORE() do { \ + if ((curvnet = saved_vnet) == NULL) { \ + PCPU_SET(vnet_data_adj, (uintptr_t)NULL); \ + } else { \ + PCPU_SET(vnet_data_adj, saved_vnet->vnet_data_base); \ + } \ +} while (0) + +#else + +#define VNET_PCPU_SET(a, b) + +#define CURVNET_DO_RESTORE() do { \ + curvnet = saved_vnet; \ +} while (0) + +#endif + #ifdef VNET_DEBUG #define VNET_ASSERT(condition) \ if (!(condition)) { \ @@ -120,34 +150,44 @@ struct vnet *saved_vnet = curvnet; \ const char *saved_vnet_lpush = curthread->td_vnet_lpush; \ curvnet = arg; \ + VNET_PCPU_SET(vnet_data_adj, curvnet->vnet_data_base); \ curthread->td_vnet_lpush = __FUNCTION__; -#define CURVNET_SET_VERBOSE(arg) \ +#define CURVNET_SET_VERBOSE(arg) \ CURVNET_SET_QUIET(arg) \ if (saved_vnet) \ - printf("CURVNET_SET(%p) in %s() on cpu %d, prev %p in %s()\n", \ + printf("CURVNET_SET(%p) in %s() on cpu %d," \ + " prev %p in %s()\n", \ curvnet, curthread->td_vnet_lpush, curcpu, \ saved_vnet, saved_vnet_lpush); #define CURVNET_SET(arg) CURVNET_SET_VERBOSE(arg) -#define CURVNET_RESTORE() \ +#define CURVNET_RESTORE() do { \ VNET_ASSERT(saved_vnet == NULL || \ saved_vnet->vnet_magic_n == VNET_MAGIC_N); \ - curvnet = saved_vnet; \ - curthread->td_vnet_lpush = saved_vnet_lpush; + CURVNET_DO_RESTORE(); \ + curthread->td_vnet_lpush = saved_vnet_lpush; \ +} while (0) + #else /* !VNET_DEBUG */ + #define VNET_ASSERT(condition) #define CURVNET_SET(arg) \ - struct vnet *saved_vnet = curvnet; \ - curvnet = arg; +struct vnet *saved_vnet = curvnet; \ + do { \ + curvnet = arg; \ + VNET_PCPU_SET(vnet_data_adj, curvnet->vnet_data_base); \ +} while (0) #define CURVNET_SET_VERBOSE(arg) CURVNET_SET(arg) #define CURVNET_SET_QUIET(arg) CURVNET_SET(arg) -#define CURVNET_RESTORE() \ - curvnet = saved_vnet; +#define CURVNET_RESTORE() do { \ + CURVNET_DO_RESTORE(); \ +} while (0) + #endif /* VNET_DEBUG */ extern struct vnet *vnet0; @@ -205,8 +245,13 @@ #define VNET_VNET_PTR(vnet, n) _VNET_PTR((vnet)->vnet_data_base, n) #define VNET_VNET(vnet, n) (*VNET_VNET_PTR((vnet), n)) +#ifdef VNET_PCPU_DATA +#define VNET(n) _VNET(PCPU_GET(vnet_data_adj), n) +#define VNET_PTR(n) _VNET_PTR(PCPU_GET(vnet_data_adj), n) +#else #define VNET_PTR(n) VNET_VNET_PTR(curvnet, n) #define VNET(n) VNET_VNET(curvnet, n) +#endif /* * Virtual network stack allocator interfaces from the kernel linker. @@ -324,6 +369,7 @@ #define CURVNET_SET(arg) #define CURVNET_SET_QUIET(arg) #define CURVNET_RESTORE() +#define VNET_PCPU_SET(a, b) #define VNET_LIST_RLOCK() #define VNET_LIST_RLOCK_NOSLEEP() Index: ddb/db_sym.c =================================================================== --- ddb/db_sym.c (revision 197380) +++ ddb/db_sym.c (working copy) @@ -64,12 +64,6 @@ static int db_cpu = -1; #ifdef VIMAGE -extern uintptr_t *__start_set_vnet; -extern uintptr_t *__stop_set_vnet; - -#define VNET_START (uintptr_t)&__start_set_vnet -#define VNET_STOP (uintptr_t)&__stop_set_vnet - static void *db_vnet = NULL; #endif Index: sys/pcpu.h =================================================================== --- sys/pcpu.h (revision 197380) +++ sys/pcpu.h (working copy) @@ -161,6 +161,11 @@ */ uintptr_t pc_dynamic; +#define VNET_PCPU_DATA 1 /* also in vnet.h */ +#if defined(VIMAGE) && defined(VNET_PCPU_DATA) /* maybe always here? */ + uintptr_t pc_vnet_data_adj; /* offset to per vnet data area */ +#endif + /* * Keep MD fields last, so that CPU-specific variations on a * single architecture don't result in offset variations of --------------030507070006070008040707--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4AB73152.1020703>