diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/kernel/early.c | 1 | ||||
-rw-r--r-- | arch/s390/kernel/kprobes.c | 27 | ||||
-rw-r--r-- | arch/s390/kernel/vmlinux.lds.S | 3 | ||||
-rw-r--r-- | arch/s390/mm/init.c | 9 |
4 files changed, 29 insertions, 11 deletions
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 40dd47970a33..e518dd53eff5 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #define DEFSYS_CMD_SIZE 96 | 27 | #define DEFSYS_CMD_SIZE 96 |
28 | #define SAVESYS_CMD_SIZE 32 | 28 | #define SAVESYS_CMD_SIZE 32 |
29 | 29 | ||
30 | extern int _eshared; | ||
31 | char kernel_nss_name[NSS_NAME_SIZE + 1]; | 30 | char kernel_nss_name[NSS_NAME_SIZE + 1]; |
32 | 31 | ||
33 | #ifdef CONFIG_SHARED_KERNEL | 32 | #ifdef CONFIG_SHARED_KERNEL |
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index b2e1dc89a8c6..a466bab6677e 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -155,15 +155,34 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn) | |||
155 | static int __kprobes swap_instruction(void *aref) | 155 | static int __kprobes swap_instruction(void *aref) |
156 | { | 156 | { |
157 | struct ins_replace_args *args = aref; | 157 | struct ins_replace_args *args = aref; |
158 | u32 *addr; | ||
159 | u32 instr; | ||
158 | int err = -EFAULT; | 160 | int err = -EFAULT; |
159 | 161 | ||
162 | /* | ||
163 | * Text segment is read-only, hence we use stura to bypass dynamic | ||
164 | * address translation to exchange the instruction. Since stura | ||
165 | * always operates on four bytes, but we only want to exchange two | ||
166 | * bytes do some calculations to get things right. In addition we | ||
167 | * shall not cross any page boundaries (vmalloc area!) when writing | ||
168 | * the new instruction. | ||
169 | */ | ||
170 | addr = (u32 *)ALIGN((unsigned long)args->ptr, 4); | ||
171 | if ((unsigned long)args->ptr & 2) | ||
172 | instr = ((*addr) & 0xffff0000) | args->new; | ||
173 | else | ||
174 | instr = ((*addr) & 0x0000ffff) | args->new << 16; | ||
175 | |||
160 | asm volatile( | 176 | asm volatile( |
161 | "0: mvc 0(2,%2),0(%3)\n" | 177 | " lra %1,0(%1)\n" |
162 | "1: la %0,0\n" | 178 | "0: stura %2,%1\n" |
179 | "1: la %0,0\n" | ||
163 | "2:\n" | 180 | "2:\n" |
164 | EX_TABLE(0b,2b) | 181 | EX_TABLE(0b,2b) |
165 | : "+d" (err), "=m" (*args->ptr) | 182 | : "+d" (err) |
166 | : "a" (args->ptr), "a" (&args->new), "m" (args->new)); | 183 | : "a" (addr), "d" (instr) |
184 | : "memory", "cc"); | ||
185 | |||
167 | return err; | 186 | return err; |
168 | } | 187 | } |
169 | 188 | ||
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 8fedb1f9fc97..a48907392522 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S | |||
@@ -35,9 +35,10 @@ SECTIONS | |||
35 | 35 | ||
36 | #ifdef CONFIG_SHARED_KERNEL | 36 | #ifdef CONFIG_SHARED_KERNEL |
37 | . = ALIGN(1048576); /* VM shared segments are 1MB aligned */ | 37 | . = ALIGN(1048576); /* VM shared segments are 1MB aligned */ |
38 | #endif | ||
38 | 39 | ||
40 | . = ALIGN(4096); | ||
39 | _eshared = .; /* End of shareable data */ | 41 | _eshared = .; /* End of shareable data */ |
40 | #endif | ||
41 | 42 | ||
42 | . = ALIGN(16); /* Exception table */ | 43 | . = ALIGN(16); /* Exception table */ |
43 | __start___ex_table = .; | 44 | __start___ex_table = .; |
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 162a338a5575..b3e7c45efb63 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/pfn.h> | 26 | #include <linux/pfn.h> |
27 | #include <linux/poison.h> | 27 | #include <linux/poison.h> |
28 | #include <linux/initrd.h> | 28 | #include <linux/initrd.h> |
29 | |||
30 | #include <asm/processor.h> | 29 | #include <asm/processor.h> |
31 | #include <asm/system.h> | 30 | #include <asm/system.h> |
32 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
@@ -96,8 +95,8 @@ static void __init setup_ro_region(void) | |||
96 | pte_t new_pte; | 95 | pte_t new_pte; |
97 | unsigned long address, end; | 96 | unsigned long address, end; |
98 | 97 | ||
99 | address = ((unsigned long)&__start_rodata) & PAGE_MASK; | 98 | address = ((unsigned long)&_stext) & PAGE_MASK; |
100 | end = PFN_ALIGN((unsigned long)&__end_rodata); | 99 | end = PFN_ALIGN((unsigned long)&_eshared); |
101 | 100 | ||
102 | for (; address < end; address += PAGE_SIZE) { | 101 | for (; address < end; address += PAGE_SIZE) { |
103 | pgd = pgd_offset_k(address); | 102 | pgd = pgd_offset_k(address); |
@@ -173,8 +172,8 @@ void __init mem_init(void) | |||
173 | datasize >>10, | 172 | datasize >>10, |
174 | initsize >> 10); | 173 | initsize >> 10); |
175 | printk("Write protected kernel read-only data: %#lx - %#lx\n", | 174 | printk("Write protected kernel read-only data: %#lx - %#lx\n", |
176 | (unsigned long)&__start_rodata, | 175 | (unsigned long)&_stext, |
177 | PFN_ALIGN((unsigned long)&__end_rodata) - 1); | 176 | PFN_ALIGN((unsigned long)&_eshared) - 1); |
178 | } | 177 | } |
179 | 178 | ||
180 | void free_initmem(void) | 179 | void free_initmem(void) |