summaryrefslogtreecommitdiff
path: root/arch/ia64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r--arch/ia64/kernel/Makefile18
-rw-r--r--arch/ia64/kernel/acpi.c5
-rw-r--r--arch/ia64/kernel/asm-offsets.c31
-rw-r--r--arch/ia64/kernel/entry.S5
-rw-r--r--arch/ia64/kernel/ivt.S6
-rw-r--r--arch/ia64/kernel/nr-irqs.c1
-rw-r--r--arch/ia64/kernel/paravirt.c2
-rw-r--r--arch/ia64/kernel/paravirt_inst.h4
-rw-r--r--arch/ia64/kernel/perfmon.c7
-rw-r--r--arch/ia64/kernel/process.c22
-rw-r--r--arch/ia64/kernel/ptrace.c112
-rw-r--r--arch/ia64/kernel/signal.c8
12 files changed, 163 insertions, 58 deletions
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index af0e750..c381ea9 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -116,5 +116,23 @@ clean-files += $(objtree)/include/asm-ia64/nr-irqs.h
ASM_PARAVIRT_OBJS = ivt.o entry.o
define paravirtualized_native
AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_NATIVE
+AFLAGS_pvchk-sed-$(1) += -D__IA64_ASM_PARAVIRTUALIZED_PVCHECK
+extra-y += pvchk-$(1)
endef
$(foreach obj,$(ASM_PARAVIRT_OBJS),$(eval $(call paravirtualized_native,$(obj))))
+
+#
+# Checker for paravirtualizations of privileged operations.
+#
+quiet_cmd_pv_check_sed = PVCHK $@
+define cmd_pv_check_sed
+ sed -f $(srctree)/arch/$(SRCARCH)/scripts/pvcheck.sed $< > $@
+endef
+
+$(obj)/pvchk-sed-%.s: $(src)/%.S $(srctree)/arch/$(SRCARCH)/scripts/pvcheck.sed FORCE
+ $(call if_changed_dep,as_s_S)
+$(obj)/pvchk-%.s: $(obj)/pvchk-sed-%.s FORCE
+ $(call if_changed,pv_check_sed)
+$(obj)/pvchk-%.o: $(obj)/pvchk-%.s FORCE
+ $(call if_changed,as_o_S)
+.PRECIOUS: $(obj)/pvchk-sed-%.s $(obj)/pvchk-%.s $(obj)/pvchk-%.o
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 8cc2f8a..0635015 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -52,6 +52,7 @@
#include <asm/numa.h>
#include <asm/sal.h>
#include <asm/cyclone.h>
+#include <asm/xen/hypervisor.h>
#define BAD_MADT_ENTRY(entry, end) ( \
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
@@ -124,6 +125,8 @@ acpi_get_sysname(void)
return "uv";
else
return "sn2";
+ } else if (xen_pv_domain() && !strcmp(hdr->oem_id, "XEN")) {
+ return "xen";
}
#ifdef CONFIG_DMAR
@@ -152,6 +155,8 @@ acpi_get_sysname(void)
return "uv";
# elif defined (CONFIG_IA64_DIG)
return "dig";
+# elif defined (CONFIG_IA64_XEN_GUEST)
+ return "xen";
# elif defined(CONFIG_IA64_DIG_VTD)
return "dig_vtd";
# else
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
index 94c44b1..742dbb1 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
@@ -16,6 +16,9 @@
#include <asm/sigcontext.h>
#include <asm/mca.h>
+#include <asm/xen/interface.h>
+#include <asm/xen/hypervisor.h>
+
#include "../kernel/sigframe.h"
#include "../kernel/fsyscall_gtod_data.h"
@@ -286,4 +289,32 @@ void foo(void)
offsetof (struct itc_jitter_data_t, itc_jitter));
DEFINE(IA64_ITC_LASTCYCLE_OFFSET,
offsetof (struct itc_jitter_data_t, itc_lastcycle));
+
+#ifdef CONFIG_XEN
+ BLANK();
+
+ DEFINE(XEN_NATIVE_ASM, XEN_NATIVE);
+ DEFINE(XEN_PV_DOMAIN_ASM, XEN_PV_DOMAIN);
+
+#define DEFINE_MAPPED_REG_OFS(sym, field) \
+ DEFINE(sym, (XMAPPEDREGS_OFS + offsetof(struct mapped_regs, field)))
+
+ DEFINE_MAPPED_REG_OFS(XSI_PSR_I_ADDR_OFS, interrupt_mask_addr);
+ DEFINE_MAPPED_REG_OFS(XSI_IPSR_OFS, ipsr);
+ DEFINE_MAPPED_REG_OFS(XSI_IIP_OFS, iip);
+ DEFINE_MAPPED_REG_OFS(XSI_IFS_OFS, ifs);
+ DEFINE_MAPPED_REG_OFS(XSI_PRECOVER_IFS_OFS, precover_ifs);
+ DEFINE_MAPPED_REG_OFS(XSI_ISR_OFS, isr);
+ DEFINE_MAPPED_REG_OFS(XSI_IFA_OFS, ifa);
+ DEFINE_MAPPED_REG_OFS(XSI_IIPA_OFS, iipa);
+ DEFINE_MAPPED_REG_OFS(XSI_IIM_OFS, iim);
+ DEFINE_MAPPED_REG_OFS(XSI_IHA_OFS, iha);
+ DEFINE_MAPPED_REG_OFS(XSI_ITIR_OFS, itir);
+ DEFINE_MAPPED_REG_OFS(XSI_PSR_IC_OFS, interrupt_collection_enabled);
+ DEFINE_MAPPED_REG_OFS(XSI_BANKNUM_OFS, banknum);
+ DEFINE_MAPPED_REG_OFS(XSI_BANK0_R16_OFS, bank0_regs[0]);
+ DEFINE_MAPPED_REG_OFS(XSI_BANK1_R16_OFS, bank1_regs[0]);
+ DEFINE_MAPPED_REG_OFS(XSI_B0NATS_OFS, vbnat);
+ DEFINE_MAPPED_REG_OFS(XSI_B1NATS_OFS, vnat);
+#endif /* CONFIG_XEN */
}
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 0dd6c14..7ef0c59 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -534,6 +534,11 @@ GLOBAL_ENTRY(ia64_trace_syscall)
stf.spill [r16]=f10
stf.spill [r17]=f11
br.call.sptk.many rp=syscall_trace_enter // give parent a chance to catch syscall args
+ cmp.lt p6,p0=r8,r0 // check tracehook
+ adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
+ adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10
+ mov r10=0
+(p6) br.cond.sptk strace_error // syscall failed ->
adds r16=PT(F6)+16,sp
adds r17=PT(F7)+16,sp
;;
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index 416a952..f675d8e3 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -580,7 +580,7 @@ ENTRY(dirty_bit)
mov b0=r29 // restore b0
;;
st8 [r17]=r18 // store back updated PTE
- itc.d r18 // install updated PTE
+ ITC_D(p0, r18, r16) // install updated PTE
#endif
mov pr=r31,-1 // restore pr
RFI
@@ -646,7 +646,7 @@ ENTRY(iaccess_bit)
mov b0=r29 // restore b0
;;
st8 [r17]=r18 // store back updated PTE
- itc.i r18 // install updated PTE
+ ITC_I(p0, r18, r16) // install updated PTE
#endif /* !CONFIG_SMP */
mov pr=r31,-1
RFI
@@ -698,7 +698,7 @@ ENTRY(daccess_bit)
or r18=_PAGE_A,r18 // set the accessed bit
;;
st8 [r17]=r18 // store back updated PTE
- itc.d r18 // install updated PTE
+ ITC_D(p0, r18, r16) // install updated PTE
#endif
mov b0=r29 // restore b0
mov pr=r31,-1
diff --git a/arch/ia64/kernel/nr-irqs.c b/arch/ia64/kernel/nr-irqs.c
index 8273afc..ee56457 100644
--- a/arch/ia64/kernel/nr-irqs.c
+++ b/arch/ia64/kernel/nr-irqs.c
@@ -10,6 +10,7 @@
#include <linux/kbuild.h>
#include <linux/threads.h>
#include <asm/native/irq.h>
+#include <asm/xen/irq.h>
void foo(void)
{
diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c
index afaf5b9..de35d8e 100644
--- a/arch/ia64/kernel/paravirt.c
+++ b/arch/ia64/kernel/paravirt.c
@@ -332,7 +332,7 @@ ia64_native_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
struct pv_iosapic_ops pv_iosapic_ops = {
.pcat_compat_init = ia64_native_iosapic_pcat_compat_init,
- .get_irq_chip = ia64_native_iosapic_get_irq_chip,
+ .__get_irq_chip = ia64_native_iosapic_get_irq_chip,
.__read = ia64_native_iosapic_read,
.__write = ia64_native_iosapic_write,
diff --git a/arch/ia64/kernel/paravirt_inst.h b/arch/ia64/kernel/paravirt_inst.h
index 5cad6fb..64d6d81 100644
--- a/arch/ia64/kernel/paravirt_inst.h
+++ b/arch/ia64/kernel/paravirt_inst.h
@@ -20,7 +20,9 @@
*
*/
-#ifdef __IA64_ASM_PARAVIRTUALIZED_XEN
+#ifdef __IA64_ASM_PARAVIRTUALIZED_PVCHECK
+#include <asm/native/pvchk_inst.h>
+#elif defined(__IA64_ASM_PARAVIRTUALIZED_XEN)
#include <asm/xen/inst.h>
#include <asm/xen/minstate.h>
#else
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index fc8f350..ada4605 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -40,6 +40,7 @@
#include <linux/capability.h>
#include <linux/rcupdate.h>
#include <linux/completion.h>
+#include <linux/tracehook.h>
#include <asm/errno.h>
#include <asm/intrinsics.h>
@@ -3684,7 +3685,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
PFM_SET_WORK_PENDING(task, 1);
- tsk_set_notify_resume(task);
+ set_notify_resume(task);
/*
* XXX: send reschedule if task runs on another CPU
@@ -5044,8 +5045,6 @@ pfm_handle_work(void)
PFM_SET_WORK_PENDING(current, 0);
- tsk_clear_notify_resume(current);
-
regs = task_pt_regs(current);
/*
@@ -5414,7 +5413,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str
* when coming from ctxsw, current still points to the
* previous task, therefore we must work with task and not current.
*/
- tsk_set_notify_resume(task);
+ set_notify_resume(task);
}
/*
* defer until state is changed (shorten spin window). the context is locked
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 3ab8373..c571627 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/kdebug.h>
#include <linux/utsname.h>
+#include <linux/tracehook.h>
#include <asm/cpu.h>
#include <asm/delay.h>
@@ -160,21 +161,6 @@ show_regs (struct pt_regs *regs)
show_stack(NULL, NULL);
}
-void tsk_clear_notify_resume(struct task_struct *tsk)
-{
-#ifdef CONFIG_PERFMON
- if (tsk->thread.pfm_needs_checking)
- return;
-#endif
- if (test_ti_thread_flag(task_thread_info(tsk), TIF_RESTORE_RSE))
- return;
- clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME);
-}
-
-/*
- * do_notify_resume_user():
- * Called from notify_resume_user at entry.S, with interrupts disabled.
- */
void
do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall)
{
@@ -203,6 +189,11 @@ do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall)
ia64_do_signal(scr, in_syscall);
}
+ if (test_thread_flag(TIF_NOTIFY_RESUME)) {
+ clear_thread_flag(TIF_NOTIFY_RESUME);
+ tracehook_notify_resume(&scr->pt);
+ }
+
/* copy user rbs to kernel rbs */
if (unlikely(test_thread_flag(TIF_RESTORE_RSE))) {
local_irq_enable(); /* force interrupt enable */
@@ -251,7 +242,6 @@ default_idle (void)
/* We don't actually take CPU down, just spin without interrupts. */
static inline void play_dead(void)
{
- extern void ia64_cpu_local_tick (void);
unsigned int this_cpu = smp_processor_id();
/* Ack it */
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 2a9943b..92c9689 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -22,6 +22,7 @@
#include <linux/signal.h>
#include <linux/regset.h>
#include <linux/elf.h>
+#include <linux/tracehook.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
@@ -603,7 +604,7 @@ void ia64_ptrace_stop(void)
{
if (test_and_set_tsk_thread_flag(current, TIF_RESTORE_RSE))
return;
- tsk_set_notify_resume(current);
+ set_notify_resume(current);
unw_init_running(do_sync_rbs, ia64_sync_user_rbs);
}
@@ -613,7 +614,6 @@ void ia64_ptrace_stop(void)
void ia64_sync_krbs(void)
{
clear_tsk_thread_flag(current, TIF_RESTORE_RSE);
- tsk_clear_notify_resume(current);
unw_init_running(do_sync_rbs, ia64_sync_kernel_rbs);
}
@@ -644,7 +644,7 @@ ptrace_attach_sync_user_rbs (struct task_struct *child)
spin_lock_irq(&child->sighand->siglock);
if (child->state == TASK_STOPPED &&
!test_and_set_tsk_thread_flag(child, TIF_RESTORE_RSE)) {
- tsk_set_notify_resume(child);
+ set_notify_resume(child);
child->state = TASK_TRACED;
stopped = 1;
@@ -1232,37 +1232,16 @@ arch_ptrace (struct task_struct *child, long request, long addr, long data)
}
-static void
-syscall_trace (void)
-{
- /*
- * The 0x80 provides a way for the tracing parent to
- * distinguish between a syscall stop and SIGTRAP delivery.
- */
- ptrace_notify(SIGTRAP
- | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
-
- /*
- * This isn't the same as continuing with a signal, but it
- * will do for normal use. strace only continues with a
- * signal if the stopping signal is not SIGTRAP. -brl
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
- }
-}
-
/* "asmlinkage" so the input arguments are preserved... */
-asmlinkage void
+asmlinkage long
syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
long arg4, long arg5, long arg6, long arg7,
struct pt_regs regs)
{
- if (test_thread_flag(TIF_SYSCALL_TRACE)
- && (current->ptrace & PT_PTRACED))
- syscall_trace();
+ if (test_thread_flag(TIF_SYSCALL_TRACE))
+ if (tracehook_report_syscall_entry(&regs))
+ return -ENOSYS;
/* copy user rbs to kernel rbs */
if (test_thread_flag(TIF_RESTORE_RSE))
@@ -1283,6 +1262,7 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3);
}
+ return 0;
}
/* "asmlinkage" so the input arguments are preserved... */
@@ -1292,6 +1272,8 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
long arg4, long arg5, long arg6, long arg7,
struct pt_regs regs)
{
+ int step;
+
if (unlikely(current->audit_context)) {
int success = AUDITSC_RESULT(regs.r10);
long result = regs.r8;
@@ -1301,10 +1283,9 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
audit_syscall_exit(success, result);
}
- if ((test_thread_flag(TIF_SYSCALL_TRACE)
- || test_thread_flag(TIF_SINGLESTEP))
- && (current->ptrace & PT_PTRACED))
- syscall_trace();
+ step = test_thread_flag(TIF_SINGLESTEP);
+ if (step || test_thread_flag(TIF_SYSCALL_TRACE))
+ tracehook_report_syscall_exit(&regs, step);
/* copy user rbs to kernel rbs */
if (test_thread_flag(TIF_RESTORE_RSE))
@@ -1940,7 +1921,7 @@ gpregs_writeback(struct task_struct *target,
{
if (test_and_set_tsk_thread_flag(target, TIF_RESTORE_RSE))
return 0;
- tsk_set_notify_resume(target);
+ set_notify_resume(target);
return do_regset_call(do_gpregs_writeback, target, regset, 0, 0,
NULL, NULL);
}
@@ -2199,3 +2180,68 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *tsk)
#endif
return &user_ia64_view;
}
+
+struct syscall_get_set_args {
+ unsigned int i;
+ unsigned int n;
+ unsigned long *args;
+ struct pt_regs *regs;
+ int rw;
+};
+
+static void syscall_get_set_args_cb(struct unw_frame_info *info, void *data)
+{
+ struct syscall_get_set_args *args = data;
+ struct pt_regs *pt = args->regs;
+ unsigned long *krbs, cfm, ndirty;
+ int i, count;
+
+ if (unw_unwind_to_user(info) < 0)
+ return;
+
+ cfm = pt->cr_ifs;
+ krbs = (unsigned long *)info->task + IA64_RBS_OFFSET/8;
+ ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
+
+ count = 0;
+ if (in_syscall(pt))
+ count = min_t(int, args->n, cfm & 0x7f);
+
+ for (i = 0; i < count; i++) {
+ if (args->rw)
+ *ia64_rse_skip_regs(krbs, ndirty + i + args->i) =
+ args->args[i];
+ else
+ args->args[i] = *ia64_rse_skip_regs(krbs,
+ ndirty + i + args->i);
+ }
+
+ if (!args->rw) {
+ while (i < args->n) {
+ args->args[i] = 0;
+ i++;
+ }
+ }
+}
+
+void ia64_syscall_get_set_arguments(struct task_struct *task,
+ struct pt_regs *regs, unsigned int i, unsigned int n,
+ unsigned long *args, int rw)
+{
+ struct syscall_get_set_args data = {
+ .i = i,
+ .n = n,
+ .args = args,
+ .regs = regs,
+ .rw = rw,
+ };
+
+ if (task == current)
+ unw_init_running(syscall_get_set_args_cb, &data);
+ else {
+ struct unw_frame_info ufi;
+ memset(&ufi, 0, sizeof(ufi));
+ unw_init_from_blocked_task(&ufi, task);
+ syscall_get_set_args_cb(&ufi, &data);
+ }
+}
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 19c5a78..e12500a 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/ptrace.h>
+#include <linux/tracehook.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/smp.h>
@@ -439,6 +440,13 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
sigaddset(&current->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
+
+ /*
+ * Let tracing know that we've done the handler setup.
+ */
+ tracehook_signal_handler(sig, info, ka, &scr->pt,
+ test_thread_flag(TIF_SINGLESTEP));
+
return 1;
}