aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig4
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/entry-common.S4
-rw-r--r--arch/arm/kernel/sys_arm.c10
-rw-r--r--arch/arm/mach-pxa/time.c58
-rw-r--r--arch/arm/mach-sa1100/time.c68
-rw-r--r--arch/arm/mm/mm-armv.c26
7 files changed, 142 insertions, 30 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4bf0e8737e1f..68dfdba71d74 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -365,8 +365,8 @@ config NO_IDLE_HZ
365 365
366 Please note that dynamic tick may affect the accuracy of 366 Please note that dynamic tick may affect the accuracy of
367 timekeeping on some platforms depending on the implementation. 367 timekeeping on some platforms depending on the implementation.
368 Currently at least OMAP platform is known to have accurate 368 Currently at least OMAP, PXA2xx and SA11x0 platforms are known
369 timekeeping with dynamic tick. 369 to have accurate timekeeping with dynamic tick.
370 370
371config ARCH_DISCONTIGMEM_ENABLE 371config ARCH_DISCONTIGMEM_ENABLE
372 bool 372 bool
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 2b6b4c786e65..db07ce42b3b2 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -284,7 +284,7 @@ __syscall_start:
284 .long sys_fstatfs64 284 .long sys_fstatfs64
285 .long sys_tgkill 285 .long sys_tgkill
286 .long sys_utimes 286 .long sys_utimes
287/* 270 */ .long sys_fadvise64_64 287/* 270 */ .long sys_arm_fadvise64_64_wrapper
288 .long sys_pciconfig_iobase 288 .long sys_pciconfig_iobase
289 .long sys_pciconfig_read 289 .long sys_pciconfig_read
290 .long sys_pciconfig_write 290 .long sys_pciconfig_write
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 3f8d0e3aefab..6281d488ac97 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -265,6 +265,10 @@ sys_futex_wrapper:
265 str r5, [sp, #4] @ push sixth arg 265 str r5, [sp, #4] @ push sixth arg
266 b sys_futex 266 b sys_futex
267 267
268sys_arm_fadvise64_64_wrapper:
269 str r5, [sp, #4] @ push r5 to stack
270 b sys_arm_fadvise64_64
271
268/* 272/*
269 * Note: off_4k (r5) is always units of 4K. If we can't do the requested 273 * Note: off_4k (r5) is always units of 4K. If we can't do the requested
270 * offset, we return EINVAL. 274 * offset, we return EINVAL.
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index f897ce2ccf0d..42629ff84f5a 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -311,3 +311,13 @@ long execve(const char *filename, char **argv, char **envp)
311 return ret; 311 return ret;
312} 312}
313EXPORT_SYMBOL(execve); 313EXPORT_SYMBOL(execve);
314
315/*
316 * Since loff_t is a 64 bit type we avoid a lot of ABI hastle
317 * with a different argument ordering.
318 */
319asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
320 loff_t offset, loff_t len)
321{
322 return sys_fadvise64_64(fd, offset, len, advice);
323}
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 6e5202154f91..7dad3f1465e0 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -70,6 +70,11 @@ static unsigned long pxa_gettimeoffset (void)
70 return usec; 70 return usec;
71} 71}
72 72
73#ifdef CONFIG_NO_IDLE_HZ
74static unsigned long initial_match;
75static int match_posponed;
76#endif
77
73static irqreturn_t 78static irqreturn_t
74pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 79pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
75{ 80{
@@ -77,11 +82,19 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
77 82
78 write_seqlock(&xtime_lock); 83 write_seqlock(&xtime_lock);
79 84
85#ifdef CONFIG_NO_IDLE_HZ
86 if (match_posponed) {
87 match_posponed = 0;
88 OSMR0 = initial_match;
89 }
90#endif
91
80 /* Loop until we get ahead of the free running timer. 92 /* Loop until we get ahead of the free running timer.
81 * This ensures an exact clock tick count and time accuracy. 93 * This ensures an exact clock tick count and time accuracy.
82 * IRQs are disabled inside the loop to ensure coherence between 94 * Since IRQs are disabled at this point, coherence between
83 * lost_ticks (updated in do_timer()) and the match reg value, so we 95 * lost_ticks(updated in do_timer()) and the match reg value is
84 * can use do_gettimeofday() from interrupt handlers. 96 * ensured, hence we can use do_gettimeofday() from interrupt
97 * handlers.
85 * 98 *
86 * HACK ALERT: it seems that the PXA timer regs aren't updated right 99 * HACK ALERT: it seems that the PXA timer regs aren't updated right
87 * away in all cases when a write occurs. We therefore compare with 100 * away in all cases when a write occurs. We therefore compare with
@@ -126,6 +139,42 @@ static void __init pxa_timer_init(void)
126 OSCR = 0; /* initialize free-running timer, force first match */ 139 OSCR = 0; /* initialize free-running timer, force first match */
127} 140}
128 141
142#ifdef CONFIG_NO_IDLE_HZ
143static int pxa_dyn_tick_enable_disable(void)
144{
145 /* nothing to do */
146 return 0;
147}
148
149static void pxa_dyn_tick_reprogram(unsigned long ticks)
150{
151 if (ticks > 1) {
152 initial_match = OSMR0;
153 OSMR0 = initial_match + ticks * LATCH;
154 match_posponed = 1;
155 }
156}
157
158static irqreturn_t
159pxa_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
160{
161 if (match_posponed) {
162 match_posponed = 0;
163 OSMR0 = initial_match;
164 if ( (signed long)(initial_match - OSCR) <= 8 )
165 return pxa_timer_interrupt(irq, dev_id, regs);
166 }
167 return IRQ_NONE;
168}
169
170static struct dyn_tick_timer pxa_dyn_tick = {
171 .enable = pxa_dyn_tick_enable_disable,
172 .disable = pxa_dyn_tick_enable_disable,
173 .reprogram = pxa_dyn_tick_reprogram,
174 .handler = pxa_dyn_tick_handler,
175};
176#endif
177
129#ifdef CONFIG_PM 178#ifdef CONFIG_PM
130static unsigned long osmr[4], oier; 179static unsigned long osmr[4], oier;
131 180
@@ -161,4 +210,7 @@ struct sys_timer pxa_timer = {
161 .suspend = pxa_timer_suspend, 210 .suspend = pxa_timer_suspend,
162 .resume = pxa_timer_resume, 211 .resume = pxa_timer_resume,
163 .offset = pxa_gettimeoffset, 212 .offset = pxa_gettimeoffset,
213#ifdef CONFIG_NO_IDLE_HZ
214 .dyn_tick = &pxa_dyn_tick,
215#endif
164}; 216};
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 0eeb3616ffea..47e0420623fc 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -70,15 +70,11 @@ static unsigned long sa1100_gettimeoffset (void)
70 return usec; 70 return usec;
71} 71}
72 72
73/* 73#ifdef CONFIG_NO_IDLE_HZ
74 * We will be entered with IRQs enabled. 74static unsigned long initial_match;
75 * 75static int match_posponed;
76 * Loop until we get ahead of the free running timer. 76#endif
77 * This ensures an exact clock tick count and time accuracy. 77
78 * IRQs are disabled inside the loop to ensure coherence between
79 * lost_ticks (updated in do_timer()) and the match reg value, so we
80 * can use do_gettimeofday() from interrupt handlers.
81 */
82static irqreturn_t 78static irqreturn_t
83sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 79sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
84{ 80{
@@ -86,6 +82,21 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
86 82
87 write_seqlock(&xtime_lock); 83 write_seqlock(&xtime_lock);
88 84
85#ifdef CONFIG_NO_IDLE_HZ
86 if (match_posponed) {
87 match_posponed = 0;
88 OSMR0 = initial_match;
89 }
90#endif
91
92 /*
93 * Loop until we get ahead of the free running timer.
94 * This ensures an exact clock tick count and time accuracy.
95 * Since IRQs are disabled at this point, coherence between
96 * lost_ticks(updated in do_timer()) and the match reg value is
97 * ensured, hence we can use do_gettimeofday() from interrupt
98 * handlers.
99 */
89 do { 100 do {
90 timer_tick(regs); 101 timer_tick(regs);
91 OSSR = OSSR_M0; /* Clear match on timer 0 */ 102 OSSR = OSSR_M0; /* Clear match on timer 0 */
@@ -120,6 +131,42 @@ static void __init sa1100_timer_init(void)
120 OSCR = 0; /* initialize free-running timer, force first match */ 131 OSCR = 0; /* initialize free-running timer, force first match */
121} 132}
122 133
134#ifdef CONFIG_NO_IDLE_HZ
135static int sa1100_dyn_tick_enable_disable(void)
136{
137 /* nothing to do */
138 return 0;
139}
140
141static void sa1100_dyn_tick_reprogram(unsigned long ticks)
142{
143 if (ticks > 1) {
144 initial_match = OSMR0;
145 OSMR0 = initial_match + ticks * LATCH;
146 match_posponed = 1;
147 }
148}
149
150static irqreturn_t
151sa1100_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
152{
153 if (match_posponed) {
154 match_posponed = 0;
155 OSMR0 = initial_match;
156 if ((signed long)(initial_match - OSCR) <= 0)
157 return sa1100_timer_interrupt(irq, dev_id, regs);
158 }
159 return IRQ_NONE;
160}
161
162static struct dyn_tick_timer sa1100_dyn_tick = {
163 .enable = sa1100_dyn_tick_enable_disable,
164 .disable = sa1100_dyn_tick_enable_disable,
165 .reprogram = sa1100_dyn_tick_reprogram,
166 .handler = sa1100_dyn_tick_handler,
167};
168#endif
169
123#ifdef CONFIG_PM 170#ifdef CONFIG_PM
124unsigned long osmr[4], oier; 171unsigned long osmr[4], oier;
125 172
@@ -156,4 +203,7 @@ struct sys_timer sa1100_timer = {
156 .suspend = sa1100_timer_suspend, 203 .suspend = sa1100_timer_suspend,
157 .resume = sa1100_timer_resume, 204 .resume = sa1100_timer_resume,
158 .offset = sa1100_gettimeoffset, 205 .offset = sa1100_gettimeoffset,
206#ifdef CONFIG_NO_IDLE_HZ
207 .dyn_tick = &sa1100_dyn_tick,
208#endif
159}; 209};
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 4dae00bf7a56..d125a3dc061c 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -295,14 +295,10 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
295 pte_t *ptep; 295 pte_t *ptep;
296 296
297 if (pmd_none(*pmdp)) { 297 if (pmd_none(*pmdp)) {
298 unsigned long pmdval;
299 ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * 298 ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
300 sizeof(pte_t)); 299 sizeof(pte_t));
301 300
302 pmdval = __pa(ptep) | prot_l1; 301 __pmd_populate(pmdp, __pa(ptep) | prot_l1);
303 pmdp[0] = __pmd(pmdval);
304 pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
305 flush_pmd_entry(pmdp);
306 } 302 }
307 ptep = pte_offset_kernel(pmdp, virt); 303 ptep = pte_offset_kernel(pmdp, virt);
308 304
@@ -457,7 +453,7 @@ static void __init build_mem_type_table(void)
457 453
458 for (i = 0; i < 16; i++) { 454 for (i = 0; i < 16; i++) {
459 unsigned long v = pgprot_val(protection_map[i]); 455 unsigned long v = pgprot_val(protection_map[i]);
460 v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot; 456 v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
461 protection_map[i] = __pgprot(v); 457 protection_map[i] = __pgprot(v);
462 } 458 }
463 459
@@ -581,23 +577,23 @@ static void __init create_mapping(struct map_desc *md)
581 */ 577 */
582void setup_mm_for_reboot(char mode) 578void setup_mm_for_reboot(char mode)
583{ 579{
584 unsigned long pmdval; 580 unsigned long base_pmdval;
585 pgd_t *pgd; 581 pgd_t *pgd;
586 pmd_t *pmd;
587 int i; 582 int i;
588 int cpu_arch = cpu_architecture();
589 583
590 if (current->mm && current->mm->pgd) 584 if (current->mm && current->mm->pgd)
591 pgd = current->mm->pgd; 585 pgd = current->mm->pgd;
592 else 586 else
593 pgd = init_mm.pgd; 587 pgd = init_mm.pgd;
594 588
595 for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) { 589 base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
596 pmdval = (i << PGDIR_SHIFT) | 590 if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ)
597 PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | 591 base_pmdval |= PMD_BIT4;
598 PMD_TYPE_SECT; 592
599 if (cpu_arch <= CPU_ARCH_ARMv5TEJ) 593 for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
600 pmdval |= PMD_BIT4; 594 unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
595 pmd_t *pmd;
596
601 pmd = pmd_off(pgd, i << PGDIR_SHIFT); 597 pmd = pmd_off(pgd, i << PGDIR_SHIFT);
602 pmd[0] = __pmd(pmdval); 598 pmd[0] = __pmd(pmdval);
603 pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1))); 599 pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));