/****************************************************************************** * xc_ia64_linux_save.c * * Save the state of a running Linux session. * * Copyright (c) 2003, K A Fraser. * Rewritten for ia64 by Tristan Gingold */ #include #include #include #include #include #include "xg_private.h" /* ** Default values for important tuning parameters. Can override by passing ** non-zero replacement values to xc_linux_save(). ** ** XXX SMH: should consider if want to be able to override MAX_MBIT_RATE too. ** */ #define DEF_MAX_ITERS (4 - 1) /* limit us to 4 times round loop */ #define DEF_MAX_FACTOR 3 /* never send more than 3x nr_pfns */ /* ** During (live) save/migrate, we maintain a number of bitmaps to track ** which pages we have to send, and to skip. */ #define BITS_PER_LONG (sizeof(unsigned long) * 8) #define BITMAP_ENTRY(_nr,_bmap) \ ((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG] #define BITMAP_SHIFT(_nr) ((_nr) % BITS_PER_LONG) static inline int test_bit (int nr, volatile void * addr) { return (BITMAP_ENTRY(nr, addr) >> BITMAP_SHIFT(nr)) & 1; } static inline void clear_bit (int nr, volatile void * addr) { BITMAP_ENTRY(nr, addr) &= ~(1UL << BITMAP_SHIFT(nr)); } static inline void set_bit ( int nr, volatile void * addr) { BITMAP_ENTRY(nr, addr) |= (1UL << BITMAP_SHIFT(nr)); } /* total number of pages used by the current guest */ static unsigned long max_pfn; static int xc_ia64_shadow_control(int xc_handle, uint32_t domid, unsigned int sop, unsigned long *dirty_bitmap, unsigned long pages, xc_shadow_op_stats_t *stats) { if (dirty_bitmap != NULL && pages > 0) { int i; unsigned char *bmap = (unsigned char *)dirty_bitmap; unsigned long bmap_bytes = ((pages + BITS_PER_LONG - 1) & ~(BITS_PER_LONG - 1)) / 8; unsigned int bmap_pages = (bmap_bytes + PAGE_SIZE - 1) / PAGE_SIZE; /* Touch the page so that it is in the TC. FIXME: use a more reliable method. */ for (i = 0 ; i < bmap_pages ; i++) bmap[i * PAGE_SIZE] = 0; /* Because bmap is not page aligned (allocated by malloc), be sure the last page is touched. */ bmap[bmap_bytes - 1] = 0; } return xc_shadow_control(xc_handle, domid, sop, dirty_bitmap, pages, NULL, 0, stats); } static inline ssize_t write_exact(int fd, void *buf, size_t count) { if (write(fd, buf, count) != count) return 0; return 1; } static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd, int dom, xc_dominfo_t *info) { int i = 0; if (!(*suspend)(dom)) { ERROR("Suspend request failed"); return -1; } retry: if (xc_domain_getinfo(xc_handle, dom, 1, info) != 1) { ERROR("Could not get domain info"); return -1; } if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend) return 0; // success if (info->paused) { // try unpausing domain, wait, and retest xc_domain_unpause(xc_handle, dom); ERROR("Domain was paused. Wait and re-test."); usleep(10000); // 10ms goto retry; } if(++i < 100) { ERROR("Retry suspend domain."); usleep(10000); // 10ms goto retry; } ERROR("Unable to suspend domain."); return -1; } int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, uint32_t max_factor, uint32_t flags, int (*suspend)(int)) { DECLARE_DOMCTL; xc_dominfo_t info; int rc = 1; //int live = (flags & XCFLAGS_LIVE); int debug = (flags & XCFLAGS_DEBUG); int live = (flags & XCFLAGS_LIVE); /* The new domain's shared-info frame number. */ unsigned long shared_info_frame; /* A copy of the CPU context of the guest. */ vcpu_guest_context_t ctxt; unsigned long *page_array = NULL; /* Live mapping of shared info structure */ shared_info_t *live_shinfo = NULL; /* Iteration number. */ int iter; /* Number of pages sent in the last iteration (live only). */ unsigned int sent_last_iter; /* Number of pages sent (live only). */ unsigned int total_sent; /* Size of the shadow bitmap (live only). */ unsigned int bitmap_size = 0; /* True if last iteration. */ int last_iter; /* Bitmap of pages to be sent. */ unsigned long *to_send = NULL; /* Bitmap of pages not to be sent (because dirtied). */ unsigned long *to_skip = NULL; char *mem; if (debug) fprintf (stderr, "xc_linux_save (ia64): started dom=%d\n", dom); /* If no explicit control parameters given, use defaults */ if (!max_iters) max_iters = DEF_MAX_ITERS; if (!max_factor) max_factor = DEF_MAX_FACTOR; //initialize_mbit_rate(); if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) { ERROR("Could not get domain info"); return 1; } shared_info_frame = info.shared_info_frame; #if 0 /* cheesy sanity check */ if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) { ERROR("Invalid state record -- pfn count out of range: %lu", (info.max_memkb >> (PAGE_SHIFT - 10))); goto out; } #endif /* Map the shared info frame */
#
# Copyright (C) 2008-2010 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk

PKG_NAME:=button-hotplug
PKG_RELEASE:=3

include $(INCLUDE_DIR)/package.mk

define KernelPackage/button-hotplug
  SUBMENU:=Other modules
  TITLE:=Button Hotplug driver
  DEPENDS:=+kmod-input-core
  FILES:=$(PKG_BUILD_DIR)/button-hotplug.ko
  AUTOLOAD:=$(call AutoLoad,30,button-hotplug,1)
  KCONFIG:=
endef

define KernelPackage/button-hotplug/description
  Kernel module to generate button uevent-s from input subsystem events.
  If your device uses GPIO buttons, see gpio-button-hotplug.
endef

EXTRA_KCONFIG:= \
	CONFIG_BUTTON_HOTPLUG=m

EXTRA_CFLAGS:= \
	$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
	$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \

MAKE_OPTS:= \
	ARCH="$(LINUX_KARCH)" \
	CROSS_COMPILE="$(TARGET_CROSS)" \
	SUBDIRS="$(PKG_BUILD_DIR)" \
	EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
	$(EXTRA_KCONFIG)

define Build/Prepare
	mkdir -p $(PKG_BUILD_DIR)
	$(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Build/Compile
	$(MAKE) -C "$(LINUX_DIR)" \
		$(MAKE_OPTS) \
		modules
endef

$(eval $(call KernelPackage,button-hotplug))