Merge branch 'iommu/largepages' into amd-iommu/2.6.35
[pandora-kernel.git] / arch / x86 / kernel / ptrace.c
index 0c1033d..2e9b550 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/errno.h>
+#include <linux/slab.h>
 #include <linux/ptrace.h>
 #include <linux/regset.h>
 #include <linux/tracehook.h>
@@ -48,6 +49,7 @@ enum x86_regset {
        REGSET_FP,
        REGSET_XFP,
        REGSET_IOPERM64 = REGSET_XFP,
+       REGSET_XSTATE,
        REGSET_TLS,
        REGSET_IOPERM32,
 };
@@ -140,30 +142,6 @@ static const int arg_offs_table[] = {
 #endif
 };
 
-/**
- * regs_get_argument_nth() - get Nth argument at function call
- * @regs:      pt_regs which contains registers at function entry.
- * @n:         argument number.
- *
- * regs_get_argument_nth() returns @n th argument of a function call.
- * Since usually the kernel stack will be changed right after function entry,
- * you must use this at function entry. If the @n th entry is NOT in the
- * kernel stack or pt_regs, this returns 0.
- */
-unsigned long regs_get_argument_nth(struct pt_regs *regs, unsigned int n)
-{
-       if (n < ARRAY_SIZE(arg_offs_table))
-               return *(unsigned long *)((char *)regs + arg_offs_table[n]);
-       else {
-               /*
-                * The typical case: arg n is on the stack.
-                * (Note: stack[0] = return address, so skip it)
-                */
-               n -= ARRAY_SIZE(arg_offs_table);
-               return regs_get_kernel_stack_nth(regs, 1 + n);
-       }
-}
-
 /*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -604,7 +582,7 @@ ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
        struct perf_event_attr attr;
 
        /*
-        * We shoud have at least an inactive breakpoint at this
+        * We should have at least an inactive breakpoint at this
         * slot. It means the user is writing dr7 without having
         * written the address register first
         */
@@ -1587,7 +1565,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
 #ifdef CONFIG_X86_64
 
-static const struct user_regset x86_64_regsets[] = {
+static struct user_regset x86_64_regsets[] __read_mostly = {
        [REGSET_GENERAL] = {
                .core_note_type = NT_PRSTATUS,
                .n = sizeof(struct user_regs_struct) / sizeof(long),
@@ -1600,6 +1578,12 @@ static const struct user_regset x86_64_regsets[] = {
                .size = sizeof(long), .align = sizeof(long),
                .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set
        },
+       [REGSET_XSTATE] = {
+               .core_note_type = NT_X86_XSTATE,
+               .size = sizeof(u64), .align = sizeof(u64),
+               .active = xstateregs_active, .get = xstateregs_get,
+               .set = xstateregs_set
+       },
        [REGSET_IOPERM64] = {
                .core_note_type = NT_386_IOPERM,
                .n = IO_BITMAP_LONGS,
@@ -1625,7 +1609,7 @@ static const struct user_regset_view user_x86_64_view = {
 #endif /* CONFIG_X86_64 */
 
 #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
-static const struct user_regset x86_32_regsets[] = {
+static struct user_regset x86_32_regsets[] __read_mostly = {
        [REGSET_GENERAL] = {
                .core_note_type = NT_PRSTATUS,
                .n = sizeof(struct user_regs_struct32) / sizeof(u32),
@@ -1644,6 +1628,12 @@ static const struct user_regset x86_32_regsets[] = {
                .size = sizeof(u32), .align = sizeof(u32),
                .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set
        },
+       [REGSET_XSTATE] = {
+               .core_note_type = NT_X86_XSTATE,
+               .size = sizeof(u64), .align = sizeof(u64),
+               .active = xstateregs_active, .get = xstateregs_get,
+               .set = xstateregs_set
+       },
        [REGSET_TLS] = {
                .core_note_type = NT_386_TLS,
                .n = GDT_ENTRY_TLS_ENTRIES, .bias = GDT_ENTRY_TLS_MIN,
@@ -1666,6 +1656,23 @@ static const struct user_regset_view user_x86_32_view = {
 };
 #endif
 
+/*
+ * This represents bytes 464..511 in the memory layout exported through
+ * the REGSET_XSTATE interface.
+ */
+u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS];
+
+void update_regset_xstate_info(unsigned int size, u64 xstate_mask)
+{
+#ifdef CONFIG_X86_64
+       x86_64_regsets[REGSET_XSTATE].n = size / sizeof(u64);
+#endif
+#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
+       x86_32_regsets[REGSET_XSTATE].n = size / sizeof(u64);
+#endif
+       xstate_fx_sw_bytes[USER_XSTATE_XCR0_WORD] = xstate_mask;
+}
+
 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 {
 #ifdef CONFIG_IA32_EMULATION