(Sorry, I mangled the first patch series. Please disregard those messages.) These RFC patches add support for Ksplice [1], a rebootless update system, to the kernel. I previously mentioned Ksplice to the LKML a few months ago [2]. The basic idea is that Ksplice can apply an update to a running Linux kernel based only on a source code patch and the original kernel source. The Ksplice technical overview document [3] describes the design of Ksplice and one of the ways that Ksplice has been evaluated. [1] http://web.mit.edu/ksplice [2] http://lkml.org/lkml/2008/4/23/330 [3] http://web.mit.edu/ksplice/doc/ksplice.pdf The interface between the Ksplice kernel component and the userspace utilities is documented in patch 6/9 of this series. The current implementation of the userspace utilities is available from the Ksplice website and the Ksplice git repository [4]. The Ksplice userspace utilities transparently support both "integrated" operation (updating a kernel patched with this patch series) and "standalone" operation (updating a completely unmodified kernel). [4] http://web.mit.edu/ksplice/ksplice.git This series of patches depends upon the -ffunction-sections and -fdata-sections patches proposed by Denys Vlasenko (for reasons unrelated to Ksplice) a few weeks ago [5]. Ksplice's 'run-pre matching' process is much simpler if the original kernel was compiled with -ffunction-sections and -fdata-sections, and so we require these compiler options for this patch series. We think that requiring these options in order to build a kernel with integrated Ksplice support is reasonable, but we welcome feedback. [5] http://lkml.org/lkml/2008/8/24/159 Denys Vlasenko has already submitted patches to the LKML for allowing all architectures to compile with -ffunction-sections and -fdata-sections [5]; he has said that he will later submit patches making it possible to run a kernel with these options [6]. In the meantime, we have a patch that creates a ...
From: Tim Abbott <tabbott@mit.edu>
Ksplice needs access to the kernel_symbol structure in order to
support modifications to the exported symbol table.
Signed-off-by: Tim Abbott <tabbott@mit.edu>
---
kernel/module.c | 80 ++++++++++++++++++++++++++----------------------------
1 files changed, 39 insertions(+), 41 deletions(-)
diff --git a/kernel/module.c b/kernel/module.c
index 6cedfc7..8954556 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -254,7 +254,7 @@ struct find_symbol_arg {
/* Output */
struct module *owner;
const unsigned long *crc;
- unsigned long value;
+ const struct kernel_symbol *sym;
};
static bool find_symbol_in_section(const struct symsearch *syms,
@@ -295,17 +295,17 @@ static bool find_symbol_in_section(const struct symsearch *syms,
fsa->owner = owner;
fsa->crc = symversion(syms->crcs, symnum);
- fsa->value = syms->start[symnum].value;
+ fsa->sym = &syms->start[symnum];
return true;
}
-/* Find a symbol, return value, (optional) crc and (optional) module
- * which owns it */
-static unsigned long find_symbol(const char *name,
- struct module **owner,
- const unsigned long **crc,
- bool gplok,
- bool warn)
+/* Find a symbol and return it, along with, (optional) crc and
+ * (optional) module which owns it */
+static const struct kernel_symbol *find_symbol(const char *name,
+ struct module **owner,
+ const unsigned long **crc,
+ bool gplok,
+ bool warn)
{
struct find_symbol_arg fsa;
@@ -318,11 +318,11 @@ static unsigned long find_symbol(const char *name,
*owner = fsa.owner;
if (crc)
*crc = fsa.crc;
- return fsa.value;
+ return fsa.sym;
}
DEBUGP("Failed to find symbol %s\n", name);
- return -ENOENT;
+ return NULL;
}
/* Search for module by name: must hold module_mutex. */
@@ -819,7 +819,7 @@ void __symbol_put(const char *symbol)
struct module *owner;
preempt_disable();
- if ...From: Tim Abbott <tabbott@mit.edu>
Ksplice's run-pre matching process needs to be able to determine the
module that contains a particular data address.
Signed-off-by: Tim Abbott <tabbott@mit.edu>
---
include/linux/module.h | 2 ++
kernel/module.c | 28 ++++++++++++++++++++++++++++
2 files changed, 30 insertions(+), 0 deletions(-)
diff --git a/include/linux/module.h b/include/linux/module.h
index 68e0955..b7cdfb4 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -362,6 +362,8 @@ static inline int module_is_live(struct module *mod)
/* Is this address in a module? (second is with no locks, for oops) */
struct module *module_text_address(unsigned long addr);
struct module *__module_text_address(unsigned long addr);
+struct module *module_data_address(unsigned long addr);
+struct module *__module_data_address(unsigned long addr);
int is_module_address(unsigned long addr);
/* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
diff --git a/kernel/module.c b/kernel/module.c
index 8954556..dda2f80 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2682,6 +2682,34 @@ struct module *module_text_address(unsigned long addr)
return mod;
}
+struct module *__module_data_address(unsigned long addr)
+{
+ struct module *mod;
+
+ if (addr < module_addr_min || addr > module_addr_max)
+ return NULL;
+
+ list_for_each_entry(mod, &modules, list) {
+ if (within(addr, mod->module_core + mod->core_text_size,
+ mod->core_size - mod->core_text_size) ||
+ within(addr, mod->module_init + mod->init_text_size,
+ mod->init_size - mod->init_text_size))
+ return mod;
+ }
+ return NULL;
+}
+
+struct module *module_data_address(unsigned long addr)
+{
+ struct module *mod;
+
+ preempt_disable();
+ mod = __module_data_address(addr);
+ preempt_enable();
+
+ return mod;
+}
+
/* Don't grab lock, we're oopsing. */
void print_modules(void)
{
--
1.5.4.3
--
From: Anders Kaseorg <andersk@mit.edu>
kallsyms_lookup_name only returns the first match that it finds.
Ksplice needs information about all symbols with a given name in order
to correctly resolve local symbols.
kallsyms_on_each_symbol provides a generic mechanism for iterating
over the kallsyms table.
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
---
include/linux/kallsyms.h | 13 +++++++++++++
include/linux/module.h | 12 ++++++++++++
kernel/kallsyms.c | 18 ++++++++++++++++++
kernel/module.c | 19 +++++++++++++++++++
4 files changed, 62 insertions(+), 0 deletions(-)
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index b961448..b8ee4d2 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -17,6 +17,11 @@
/* Lookup the address for a symbol. Returns 0 if not found. */
unsigned long kallsyms_lookup_name(const char *name);
+/* Call a function on each kallsyms symbol in the core kernel */
+int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
+ unsigned long),
+ void *data);
+
extern int kallsyms_lookup_size_offset(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset);
@@ -43,6 +48,14 @@ static inline unsigned long kallsyms_lookup_name(const char *name)
return 0;
}
+static inline int kallsyms_on_each_symbol(int (*fn)(void *, const char *,
+ struct module *,
+ unsigned long),
+ void *data)
+{
+ return 0;
+}
+
static inline int kallsyms_lookup_size_offset(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset)
diff --git a/include/linux/module.h b/include/linux/module.h
index b7cdfb4..cd982cd 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -374,6 +374,10 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
/* Look for this name: can be of form module:name. */
unsigned long module_kallsyms_lookup_name(const ...From: Tim Abbott <tabbott@mit.edu>
Make module_mutex, find_module(), find_symbol(), and use_module()
global. Ksplice needs access to these functions from module.c in
order to resolve symbols and implement dependency handling.
Signed-off-by: Tim Abbott <tabbott@mit.edu>
---
include/linux/module.h | 13 +++++++++++++
kernel/module.c | 18 +++++++++---------
2 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/include/linux/module.h b/include/linux/module.h
index cd982cd..6ae0fc9 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -351,6 +351,8 @@ struct module
#define MODULE_ARCH_INIT {}
#endif
+extern struct mutex module_mutex;
+
/* FIXME: It'd be nice to isolate modules during init, too, so they
aren't used before they (may) fail. But presently too much code
(IDE & SCSI) require entry into the module during init.*/
@@ -366,6 +368,16 @@ struct module *module_data_address(unsigned long addr);
struct module *__module_data_address(unsigned long addr);
int is_module_address(unsigned long addr);
+/* Search for module by name: must hold module_mutex. */
+struct module *find_module(const char *name);
+
+/* Search for an exported symbol by name. */
+const struct kernel_symbol *find_symbol(const char *name,
+ struct module **owner,
+ const unsigned long **crc,
+ bool gplok,
+ bool warn);
+
/* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
symnum out of range. */
int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
@@ -431,6 +443,7 @@ static inline void __module_get(struct module *module)
#define symbol_put_addr(p) do { } while(0)
#endif /* CONFIG_MODULE_UNLOAD */
+int use_module(struct module *a, struct module *b);
/* This is a #define so the string doesn't get put in every .o file */
#define module_name(mod) \
diff --git a/kernel/module.c b/kernel/module.c
index 343c8f8..2acb646 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ ...The architecture-independent core of Ksplice. Ksplice makes it possible to apply certain kinds of patches to the kernel without having to reboot. Signed-off-by: Jeffrey Brian Arnold <jbarnold@mit.edu> Signed-off-by: Anders Kaseorg <andersk@mit.edu> Signed-off-by: Tim Abbott <tabbott@mit.edu> Tested-by: Waseem Daher <wdaher@mit.edu> --- MAINTAINERS | 10 + arch/Kconfig | 14 + include/linux/ksplice.h | 202 +++++ kernel/Makefile | 2 + kernel/ksplice.c | 1997 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 2225 insertions(+), 0 deletions(-) create mode 100644 include/linux/ksplice.h create mode 100644 kernel/ksplice.c diff --git a/MAINTAINERS b/MAINTAINERS index 186be3b..bdc6dd7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2476,6 +2476,16 @@ W: http://miguelojeda.es/auxdisplay.htm W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained +KSPLICE: +P: Jeffrey Brian Arnold +M: jbarnold@mit.edu +P: Anders Kaseorg +M: andersk@mit.edu +P: Tim Abbott +M: tabbott@mit.edu +W: http://web.mit.edu/ksplice +S: Maintained + LAPB module L: linux-x25@vger.kernel.org S: Orphan diff --git a/arch/Kconfig b/arch/Kconfig index 364c6da..9d5a843 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -27,6 +27,17 @@ config KPROBES for kernel debugging, non-intrusive instrumentation and testing. If in doubt, say "N". +config KSPLICE + bool "Ksplice rebootless kernel updates" + depends on KALLSYMS_ALL && MODULE_UNLOAD && SYSFS && \ + FUNCTION_DATA_SECTIONS + depends on HAVE_KSPLICE + help + Say Y here if you want to be able to apply certain kinds of + patches to your running kernel, without rebooting. + + If unsure, say N. + config HAVE_EFFICIENT_UNALIGNED_ACCESS def_bool n help @@ -56,6 +67,9 @@ config HAVE_IOREMAP_PROT config HAVE_KPROBES def_bool n +config HAVE_KSPLICE + def_bool n + config HAVE_KRETPROBES def_bool n diff ...
This document assumes familiarity with the Ksplice design and describes notable implementation details and the interface between the Ksplice kernel component and the Ksplice user space component. Signed-off-by: Jeffrey Brian Arnold <jbarnold@mit.edu> Signed-off-by: Tim Abbott <tabbott@mit.edu> --- Documentation/ksplice.txt | 247 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 247 insertions(+), 0 deletions(-) create mode 100644 Documentation/ksplice.txt diff --git a/Documentation/ksplice.txt b/Documentation/ksplice.txt new file mode 100644 index 0000000..a8fb0ba --- /dev/null +++ b/Documentation/ksplice.txt @@ -0,0 +1,247 @@ +Ksplice +------- + +CONTENTS: + +1. Concepts: Updates, packs, helper modules, primary modules +2. What changes can Ksplice handle? +3. Dependency model +4. Locking model +5. altinstructions, smplocks, and parainstructions +6. sysfs interface +7. debugfs interface + +0. Design Description +--------------------- + +For a description of the Ksplice design, please see the Ksplice technical +overview document: <http://web.mit.edu/ksplice/doc/ksplice.pdf>. For usage +examples and the Ksplice man pages, please see <http://web.mit.edu/ksplice/>. + +The document below assumes familiarity with the Ksplice design and describes +notable implementation details and the interface between the Ksplice kernel +component and the Ksplice user space component. + +1. Concepts: Updates, packs, helper modules, primary modules +------------------------------------------------------------ + +A Ksplice update (struct update) contains one or more Ksplice packs, one for +each target kernel module that should be changed by the update. Ksplice packs +are grouped together into a Ksplice update in order to allow multiple +compilation units to be changed atomically. + +The contents of a Ksplice pack are documented via kernel-doc in +include/linux/ksplice.h. To construct a new Ksplice update to be performed +atomically, one needs to: + 1. ...
Add support for Ksplice on x86. Signed-off-by: Jeffrey Brian Arnold <jbarnold@mit.edu> Signed-off-by: Anders Kaseorg <andersk@mit.edu> Signed-off-by: Tim Abbott <tabbott@mit.edu> --- arch/x86/Kconfig | 1 + arch/x86/kernel/ksplice-arch.c | 91 ++++++++++++++++++++++++++++++++++++++++ arch/x86/mm/init_32.c | 6 +- arch/x86/mm/init_64.c | 4 +- 4 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 arch/x86/kernel/ksplice-arch.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ed92864..b5ec2f4 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -23,6 +23,7 @@ config X86 select HAVE_OPROFILE select HAVE_IOREMAP_PROT select HAVE_KPROBES + select HAVE_KSPLICE select ARCH_WANT_OPTIONAL_GPIOLIB select HAVE_KRETPROBES select HAVE_DYNAMIC_FTRACE diff --git a/arch/x86/kernel/ksplice-arch.c b/arch/x86/kernel/ksplice-arch.c new file mode 100644 index 0000000..52314c4 --- /dev/null +++ b/arch/x86/kernel/ksplice-arch.c @@ -0,0 +1,91 @@ +/* Copyright (C) 2007-2008 Jeffrey Brian Arnold <jbarnold@mit.edu> + * Copyright (C) 2008 Anders Kaseorg <andersk@mit.edu>, + * Tim Abbott <tabbott@mit.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#define KSPLICE_IP(x) ((x)->thread.ip) +#define KSPLICE_SP(x) ((x)->thread.sp) + +static const struct ksplice_symbol trampoline_symbol = ...
Add support for Ksplice on ARM. Signed-off-by: Jeffrey Brian Arnold <jbarnold@mit.edu> Signed-off-by: Anders Kaseorg <andersk@mit.edu> Signed-off-by: Tim Abbott <tabbott@mit.edu> --- arch/arm/Kconfig | 1 + arch/arm/kernel/ksplice-arch.c | 79 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 0 deletions(-) create mode 100644 arch/arm/kernel/ksplice-arch.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 70dba16..e73f205 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -14,6 +14,7 @@ config ARM select HAVE_OPROFILE select HAVE_ARCH_KGDB select HAVE_KPROBES if (!XIP_KERNEL) + select HAVE_KSPLICE if (!XIP_KERNEL) select HAVE_KRETPROBES if (HAVE_KPROBES) select HAVE_FTRACE if (!XIP_KERNEL) select HAVE_DYNAMIC_FTRACE if (HAVE_FTRACE) diff --git a/arch/arm/kernel/ksplice-arch.c b/arch/arm/kernel/ksplice-arch.c new file mode 100644 index 0000000..981cf75 --- /dev/null +++ b/arch/arm/kernel/ksplice-arch.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2007-2008 Jeffrey Brian Arnold <jbarnold@mit.edu> + * Copyright (C) 2008 Anders Kaseorg <andersk@mit.edu>, + * Tim Abbott <tabbott@mit.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/thread_info.h> +#define KSPLICE_IP(x) thread_saved_pc(x) +#define KSPLICE_SP(x) thread_saved_fp(x) + +static const struct ksplice_symbol ...
From: Tim Abbott <tabbott@mit.edu> Export the symbols needed to build Ksplice as a module. Signed-off-by: Tim Abbott <tabbott@mit.edu> --- arch/Kconfig | 2 +- arch/x86/mm/init_32.c | 5 +++-- arch/x86/mm/init_64.c | 3 ++- kernel/kallsyms.c | 1 + kernel/module.c | 9 +++++++++ kernel/sched.c | 1 + 6 files changed, 17 insertions(+), 4 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 9d5a843..cfbbcf3 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -28,7 +28,7 @@ config KPROBES If in doubt, say "N". config KSPLICE - bool "Ksplice rebootless kernel updates" + tristate "Ksplice rebootless kernel updates" depends on KALLSYMS_ALL && MODULE_UNLOAD && SYSFS && \ FUNCTION_DATA_SECTIONS depends on HAVE_KSPLICE diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 5998d5c..549b021 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -1036,7 +1036,8 @@ void mark_rodata_ro(void) unsigned long start = PFN_ALIGN(_text); unsigned long size = PFN_ALIGN(_etext) - start; -#if !defined(CONFIG_DYNAMIC_FTRACE) && !defined(CONFIG_KSPLICE) +#if !defined(CONFIG_DYNAMIC_FTRACE) && \ + !defined(CONFIG_KSPLICE) && !defined(CONFIG_KSPLICE_MODULE) /* Dynamic tracing and Ksplice modify the kernel text section */ set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); printk(KERN_INFO "Write protecting the kernel text: %luk\n", @@ -1050,7 +1051,7 @@ void mark_rodata_ro(void) printk(KERN_INFO "Testing CPA: write protecting again\n"); set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT); #endif -#endif /* !CONFIG_DYNAMIC_FTRACE && !CONFIG_KSPLICE */ +#endif /* !CONFIG_DYNAMIC_FTRACE && !CONFIG_KSPLICE && !CONFIG_KSPLICE_MODULE */ start += size; size = (unsigned long)__end_rodata - start; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 31db657..dec6325 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -857,7 +857,8 @@ void ...
