Skip to content
This repository was archived by the owner on Jan 8, 2025. It is now read-only.

Commit

Permalink
ia64 support
Browse files Browse the repository at this point in the history
This patch adds support for kexec-tools on ia64. This patch applies on
top of -kdump7 patch from <http://lse.sourceforge.net/kdump/>.

Signed-off-by: Khalid Aziz <[email protected]>
Signed-off-by: Maneesh Soni <[email protected]>
  • Loading branch information
Khalid Aziz authored and ebiederm committed Jul 27, 2006
1 parent 0a196ba commit 2f646b5
Show file tree
Hide file tree
Showing 12 changed files with 456 additions and 55 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ PKGLIBDIR=$(LIBDIR)/$(PACKAGE)
PKGINCLUDEIR=$(INCLUDEDIR)/$(PACKAGE)

MAN_PAGES:= kexec/kexec.8
MAN_PAGES+= kdump/kdump.8
BINARIES_i386:= $(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test
BINARIES_x86_64:=$(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test
BINARIES:=$(SBINDIR)/kexec $(SBINDIR)/kdump $(BINARIES_$(ARCH))
Expand Down
4 changes: 4 additions & 0 deletions kdump/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ KDUMP_SRCS:= $(KDUMP_C_SRCS)
KDUMP_OBJS:= $(KDUMP_C_OBJS)
KDUMP_DEPS:= $(KDUMP_C_DEPS)
KDUMP:= $(SBINDIR)/kdump
KDUMP_MANPAGE:= $(MANDIR)/man8/kdump.8

include $(KDUMP_DEPS)

Expand All @@ -25,6 +26,9 @@ $(KDUMP): $(KDUMP_OBJS)
mkdir -p $(@D)
$(CC) $(CFLAGS) -o $@ $(KDUMP_OBJS)

$(KDUMP_MANPAGE): kdump/kdump.8
$(MKDIR) -p $(MANDIR)/man8
cp kdump/kdump.8 $(KDUMP_MANPAGE)
echo::
@echo "KDUMP_C_SRCS $(KDUMP_C_SRCS)"
@echo "KDUMP_C_DEPS $(KDUMP_C_DEPS)"
Expand Down
39 changes: 39 additions & 0 deletions kdump/kdump.8
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.\" Hey, EMACS: -*- nroff -*-
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH KDUMP 8 "Jul 27, 2005"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
.\" .nh disable hyphenation
.\" .hy enable hyphenation
.\" .ad l left justify
.\" .ad b justify to both left and right margins
.\" .nf disable filling
.\" .fi enable filling
.\" .br insert line break
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
kdump \- This is just a placeholder until real man page has been written
.SH SYNOPSIS
.B kdump
.RI [ options ] " start_address" ...
.SH DESCRIPTION
.PP
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
.\" respectively.
\fBkdump\fP does not have a man page yet.
.SH OPTIONS
.\"These programs follow the usual GNU command line syntax, with long
.\"options starting with two dashes (`-').
.\"A summary of options is included below.
.\"For a complete description, see the Info files.
.SH SEE ALSO
.SH AUTHOR
kdump was written by Eric Biederman.
.PP
This manual page was written by Khalid Aziz <[email protected]>,
for the Debian project (but may be used by others).
4 changes: 4 additions & 0 deletions kexec/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ KEXEC_SRCS:= $(KEXEC_C_SRCS) $(KEXEC_S_SRCS)
KEXEC_OBJS:= $(KEXEC_C_OBJS) $(KEXEC_S_OBJS)
KEXEC_DEPS:= $(KEXEC_C_DEPS) $(KEXEC_S_DEPS)
KEXEC:= $(SBINDIR)/kexec
KEXEC_MANPAGE:= $(MANDIR)/man8/kexec.8

include $(KEXEC_DEPS)

Expand All @@ -51,6 +52,9 @@ $(KEXEC): $(KEXEC_OBJS) $(UTIL_LIB)
mkdir -p $(@D)
$(CC) $(KCFLAGS) -o $@ $(KEXEC_OBJS) $(UTIL_LIB) $(LIBS)

$(KEXEC_MANPAGE): kexec/kexec.8
$(MKDIR) -p $(MANDIR)/man8
cp kexec/kexec.8 $(KEXEC_MANPAGE)
echo::
@echo "KEXEC_C_SRCS $(KEXEC_C_SRCS)"
@echo "KEXEC_C_DEPS $(KEXEC_C_DEPS)"
Expand Down
60 changes: 52 additions & 8 deletions kexec/arch/ia64/kexec-elf-ia64.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Copyright (C) 2004 Silicon Graphics, Inc.
* Jesse Barnes <[email protected]>
* Copyright (C) 2004 Khalid Aziz <[email protected]> Hewlett Packard Co
* Copyright (C) 2005 Zou Nan hai <[email protected]> Intel Corp
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -34,6 +35,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
#include <limits.h>
#include <elf.h>
#include <boot/elf_boot.h>
#include <ip_checksum.h>
Expand Down Expand Up @@ -74,23 +76,29 @@ void elf_ia64_usage(void)
{
printf(
" --command-line=STRING Set the kernel command line to STRING.\n"
" --append=STRING Set the kernel command line to STRING.\n");
" --append=STRING Set the kernel command line to STRING.\n"
" --initrd=FILE Use FILE as the kernel's initial ramdisk.\n");
}

int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
struct kexec_info *info)
{
struct mem_ehdr ehdr;
const char *command_line;
int command_line_len;
unsigned long entry, max_addr;
const char *command_line, *ramdisk=0;
char *ramdisk_buf = NULL;
off_t ramdisk_size = 0;
unsigned long command_line_len;
unsigned long entry, max_addr, gp_value;
unsigned command_line_base, ramdisk_base;
int result;
int opt;
#define OPT_APPEND (OPT_ARCH_MAX+0)
#define OPT_RAMDISK (OPT_ARCH_MAX+1)
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{"command-line", 1, 0, OPT_APPEND},
{"append", 1, 0, OPT_APPEND},
{"initrd", 1, 0, OPT_RAMDISK},
{0, 0, 0, 0},
};

Expand All @@ -110,11 +118,14 @@ int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
case OPT_APPEND:
command_line = optarg;
break;
case OPT_RAMDISK:
ramdisk = optarg;
break;
}
}
command_line_len = 0;
if (command_line) {
command_line_len = strlen(command_line) + 1;
command_line_len = strlen(command_line) + 16;
}

/* Parse the Elf file */
Expand All @@ -129,13 +140,46 @@ int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,

/* Load the Elf data */
result = elf_exec_load(&ehdr, info);
free_elf_info(&ehdr);
if (result < 0) {
fprintf(stderr, "ELF load failed\n");
free_elf_info(&ehdr);
return result;
}


/* Load the setup code */
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
0x80000, ULONG_MAX, 1);

if (command_line_len) {
char *cmdline = xmalloc(command_line_len);
strcpy(cmdline, command_line);
command_line_len = (command_line_len + 15)&(~15);
elf_rel_set_symbol(&info->rhdr, "__command_line_len",
&command_line_len, sizeof(long));
command_line_base = add_buffer(info, cmdline,
command_line_len, command_line_len,
16, 0, max_addr, 1);
elf_rel_set_symbol(&info->rhdr, "__command_line",
&command_line_base, sizeof(long));
}

/* For now we don't have arguments to pass :( */
info->entry = (void *)entry;
if (ramdisk) {
ramdisk_buf = slurp_file(ramdisk, &ramdisk_size);
ramdisk_base = add_buffer(info, ramdisk_buf, ramdisk_size,
ramdisk_size,
getpagesize(), 0, max_addr, 1);
elf_rel_set_symbol(&info->rhdr, "__ramdisk_base",
&ramdisk_base, sizeof(long));
elf_rel_set_symbol(&info->rhdr, "__ramdisk_size",
&ramdisk_size, sizeof(long));
}

gp_value = info->rhdr.rel_addr + 0x200000;
elf_rel_set_symbol(&info->rhdr, "__gp_value", &gp_value,
sizeof(gp_value));

elf_rel_set_symbol(&info->rhdr, "__kernel_entry", &entry, sizeof(entry));
free_elf_info(&ehdr);
return 0;
}
96 changes: 91 additions & 5 deletions kexec/arch/ia64/kexec-elf-rel-ia64.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
/* Most of the code in this file is
* based on arch/ia64/kernel/module.c in Linux kernel
*/

#include <stdio.h>
#include <elf.h>
#include "../../kexec.h"
#include "../../kexec-elf.h"

#define MAX_LTOFF ((uint64_t) (1 << 22))

int machine_verify_elf_rel(struct mem_ehdr *ehdr)
{
if (ehdr->ei_data != ELFDATA2LSB) {
Expand All @@ -17,12 +23,40 @@ int machine_verify_elf_rel(struct mem_ehdr *ehdr)
return 1;
}

static void
ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val)
{
uint64_t m0, m1, v0, v1, b0, b1, *b = (uint64_t *) (insn_addr & -16);
# define insn_mask ((1UL << 41) - 1)
unsigned long shift;

b0 = b[0]; b1 = b[1];
shift = 5 + 41 * (insn_addr % 16); /* 5 bits of template, then 3 x 41-bit instructions */
if (shift >= 64) {
m1 = mask << (shift - 64);
v1 = val << (shift - 64);
} else {
m0 = mask << shift; m1 = mask >> (64 - shift);
v0 = val << shift; v1 = val >> (64 - shift);
b[0] = (b0 & ~m0) | (v0 & m0);
}
b[1] = (b1 & ~m1) | (v1 & m1);
}

static inline uint64_t
bundle (const uint64_t insn)
{
return insn & ~0xfUL;
}

void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
void *location, unsigned long address, unsigned long value)
{
uint64_t gp_value = ehdr->rel_addr + 0x200000;
switch(r_type) {
case R_IA64_NONE:
break;
case R_IA64_SEGREL64LSB:
case R_IA64_DIR64LSB:
*((uint64_t *)location) = value;
break;
Expand All @@ -31,15 +65,67 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
if (value != *((uint32_t *)location))
goto overflow;
break;
case R_IA64_PCREL21B:
case R_IA64_IMM64:
ia64_patch((uint64_t)location, 0x01fffefe000UL,
/* bit 63 -> 36 */
(((value & 0x8000000000000000UL) >> 27)
/* bit 21 -> 21 */
| ((value & 0x0000000000200000UL) << 0)
/* bit 16 -> 22 */
| ((value & 0x00000000001f0000UL) << 6)
/* bit 7 -> 27 */
| ((value & 0x000000000000ff80UL) << 20)
/* bit 0 -> 13 */
| ((value & 0x000000000000007fUL) << 13)));
ia64_patch((uint64_t)location - 1, 0x1ffffffffffUL, value>>22);
break;
case R_IA64_IMM22:
if (value + (1 << 21) >= (1 << 22))
die("value out of IMM22 range\n");
ia64_patch((uint64_t)location, 0x01fffcfe000UL,
/* bit 21 -> 36 */
(((value & 0x200000UL) << 15)
/* bit 16 -> 22 */
| ((value & 0x1f0000UL) << 6)
/* bit 7 -> 27 */
| ((value & 0x00ff80UL) << 20)
/* bit 0 -> 13 */
| ((value & 0x00007fUL) << 13) ));
break;
case R_IA64_PCREL21B: {
uint64_t delta = ((int64_t)value - (int64_t)address)/16;
if (delta + (1 << 20) >= (1 << 21))
die("value out of IMM21B range\n");
value = ((int64_t)(value - bundle(address)))/16;
ia64_patch((uint64_t)location, 0x11ffffe000UL,
(((value & 0x100000UL) << 16) /* bit 20 -> 36 */
| ((value & 0x0fffffUL) << 13) /* bit 0 -> 13 */));
}
break;
case R_IA64_LTOFF22X:
if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF)
die("value out of gp relative range");
value -= gp_value;
ia64_patch((uint64_t)location, 0x01fffcfe000UL,
(((value & 0x200000UL) << 15) /* bit 21 -> 36 */
|((value & 0x1f0000UL) << 6) /* bit 16 -> 22 */
|((value & 0x00ff80UL) << 20) /* bit 7 -> 27 */
|((value & 0x00007fUL) << 13) /* bit 0 -> 13 */));
break;
case R_IA64_LDXMOV:
if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF)
die("value out of gp relative range");
ia64_patch((uint64_t)location, 0x1fff80fe000UL, 0x10000000000UL);
break;
case R_IA64_LTOFF22:
case R_IA64_SEGREL64LSB:

default:
die("Unknown rela relocation: %lu\n", r_type);
die("Unknown rela relocation: 0x%lx 0x%lx\n",
r_type, address);
break;
}
return;
overflow:
overflow:
die("overflow in relocation type %lu val %Lx\n",
r_type, value);
r_type, value);
}
Loading

0 comments on commit 2f646b5

Please sign in to comment.