From 213eca7f4888e9817e8076cdab6b9f7295c181f6 Mon Sep 17 00:00:00 2001 From: Greg KH Date: Wed, 30 Jan 2008 13:29:58 +0100 Subject: [PATCH 001/890] kobj: fix threshold_init_device/kobject_uevent_env oops the logic in this function is just crazy. It's recursive, but we can circumvent the creation for the kobject and whole creation of the threshold_block if some conditions are met. That's why we see the allocate_threshold_blocks so many times in the callstack, yet only a few kobjects created. Then we blow up in kobject_uevent_env() on the first debug printk. Which means that we are just passing in garbage. Man, this is one time that comments in code would have been very nice to have, and why forward goto's into major code blocks are just evil... Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/mcheck/mce_amd_64.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c index 753588755fee..073afa7dd89a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c @@ -450,7 +450,8 @@ recurse: if (err) goto out_free; - kobject_uevent(&b->kobj, KOBJ_ADD); + if (b) + kobject_uevent(&b->kobj, KOBJ_ADD); return err; From a6fa8e5a6172a5a5bc06ed04f34e50b36c978127 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 30 Jan 2008 13:30:00 +0100 Subject: [PATCH 002/890] time: clean hungarian notation from timers Clean up hungarian notation from timer code. Signed-off-by: Pavel Machek Cc: john stultz Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- include/linux/timer.h | 6 ++-- kernel/timer.c | 80 +++++++++++++++++++++---------------------- 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/include/linux/timer.h b/include/linux/timer.h index 78cf899b4409..de0e71359ede 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -5,7 +5,7 @@ #include #include -struct tvec_t_base_s; +struct tvec_base; struct timer_list { struct list_head entry; @@ -14,7 +14,7 @@ struct timer_list { void (*function)(unsigned long); unsigned long data; - struct tvec_t_base_s *base; + struct tvec_base *base; #ifdef CONFIG_TIMER_STATS void *start_site; char start_comm[16]; @@ -22,7 +22,7 @@ struct timer_list { #endif }; -extern struct tvec_t_base_s boot_tvec_bases; +extern struct tvec_base boot_tvec_bases; #define TIMER_INITIALIZER(_function, _expires, _data) { \ .function = (_function), \ diff --git a/kernel/timer.c b/kernel/timer.c index f739dfb539ce..aadfbc8367f5 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -58,59 +58,57 @@ EXPORT_SYMBOL(jiffies_64); #define TVN_MASK (TVN_SIZE - 1) #define TVR_MASK (TVR_SIZE - 1) -typedef struct tvec_s { +struct tvec { struct list_head vec[TVN_SIZE]; -} tvec_t; +}; -typedef struct tvec_root_s { +struct tvec_root { struct list_head vec[TVR_SIZE]; -} tvec_root_t; +}; -struct tvec_t_base_s { +struct tvec_base { spinlock_t lock; struct timer_list *running_timer; unsigned long timer_jiffies; - tvec_root_t tv1; - tvec_t tv2; - tvec_t tv3; - tvec_t tv4; - tvec_t tv5; + struct tvec_root tv1; + struct tvec tv2; + struct tvec tv3; + struct tvec tv4; + struct tvec tv5; } ____cacheline_aligned; -typedef struct tvec_t_base_s tvec_base_t; - -tvec_base_t boot_tvec_bases; +struct tvec_base boot_tvec_bases; EXPORT_SYMBOL(boot_tvec_bases); -static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = &boot_tvec_bases; +static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases; /* - * Note that all tvec_bases is 2 byte aligned and lower bit of + * Note that all tvec_bases are 2 byte aligned and lower bit of * base in timer_list is guaranteed to be zero. Use the LSB for * the new flag to indicate whether the timer is deferrable */ #define TBASE_DEFERRABLE_FLAG (0x1) /* Functions below help us manage 'deferrable' flag */ -static inline unsigned int tbase_get_deferrable(tvec_base_t *base) +static inline unsigned int tbase_get_deferrable(struct tvec_base *base) { return ((unsigned int)(unsigned long)base & TBASE_DEFERRABLE_FLAG); } -static inline tvec_base_t *tbase_get_base(tvec_base_t *base) +static inline struct tvec_base *tbase_get_base(struct tvec_base *base) { - return ((tvec_base_t *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG)); + return ((struct tvec_base *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG)); } static inline void timer_set_deferrable(struct timer_list *timer) { - timer->base = ((tvec_base_t *)((unsigned long)(timer->base) | + timer->base = ((struct tvec_base *)((unsigned long)(timer->base) | TBASE_DEFERRABLE_FLAG)); } static inline void -timer_set_base(struct timer_list *timer, tvec_base_t *new_base) +timer_set_base(struct timer_list *timer, struct tvec_base *new_base) { - timer->base = (tvec_base_t *)((unsigned long)(new_base) | + timer->base = (struct tvec_base *)((unsigned long)(new_base) | tbase_get_deferrable(timer->base)); } @@ -246,7 +244,7 @@ unsigned long round_jiffies_relative(unsigned long j) EXPORT_SYMBOL_GPL(round_jiffies_relative); -static inline void set_running_timer(tvec_base_t *base, +static inline void set_running_timer(struct tvec_base *base, struct timer_list *timer) { #ifdef CONFIG_SMP @@ -254,7 +252,7 @@ static inline void set_running_timer(tvec_base_t *base, #endif } -static void internal_add_timer(tvec_base_t *base, struct timer_list *timer) +static void internal_add_timer(struct tvec_base *base, struct timer_list *timer) { unsigned long expires = timer->expires; unsigned long idx = expires - base->timer_jiffies; @@ -371,14 +369,14 @@ static inline void detach_timer(struct timer_list *timer, * possible to set timer->base = NULL and drop the lock: the timer remains * locked. */ -static tvec_base_t *lock_timer_base(struct timer_list *timer, +static struct tvec_base *lock_timer_base(struct timer_list *timer, unsigned long *flags) __acquires(timer->base->lock) { - tvec_base_t *base; + struct tvec_base *base; for (;;) { - tvec_base_t *prelock_base = timer->base; + struct tvec_base *prelock_base = timer->base; base = tbase_get_base(prelock_base); if (likely(base != NULL)) { spin_lock_irqsave(&base->lock, *flags); @@ -393,7 +391,7 @@ static tvec_base_t *lock_timer_base(struct timer_list *timer, int __mod_timer(struct timer_list *timer, unsigned long expires) { - tvec_base_t *base, *new_base; + struct tvec_base *base, *new_base; unsigned long flags; int ret = 0; @@ -445,7 +443,7 @@ EXPORT_SYMBOL(__mod_timer); */ void add_timer_on(struct timer_list *timer, int cpu) { - tvec_base_t *base = per_cpu(tvec_bases, cpu); + struct tvec_base *base = per_cpu(tvec_bases, cpu); unsigned long flags; timer_stats_timer_set_start_info(timer); @@ -508,7 +506,7 @@ EXPORT_SYMBOL(mod_timer); */ int del_timer(struct timer_list *timer) { - tvec_base_t *base; + struct tvec_base *base; unsigned long flags; int ret = 0; @@ -539,7 +537,7 @@ EXPORT_SYMBOL(del_timer); */ int try_to_del_timer_sync(struct timer_list *timer) { - tvec_base_t *base; + struct tvec_base *base; unsigned long flags; int ret = -1; @@ -591,7 +589,7 @@ int del_timer_sync(struct timer_list *timer) EXPORT_SYMBOL(del_timer_sync); #endif -static int cascade(tvec_base_t *base, tvec_t *tv, int index) +static int cascade(struct tvec_base *base, struct tvec *tv, int index) { /* cascade all the timers from tv up one level */ struct timer_list *timer, *tmp; @@ -620,7 +618,7 @@ static int cascade(tvec_base_t *base, tvec_t *tv, int index) * This function cascades all vectors and executes all expired timer * vectors. */ -static inline void __run_timers(tvec_base_t *base) +static inline void __run_timers(struct tvec_base *base) { struct timer_list *timer; @@ -678,13 +676,13 @@ static inline void __run_timers(tvec_base_t *base) * is used on S/390 to stop all activity when a cpus is idle. * This functions needs to be called disabled. */ -static unsigned long __next_timer_interrupt(tvec_base_t *base) +static unsigned long __next_timer_interrupt(struct tvec_base *base) { unsigned long timer_jiffies = base->timer_jiffies; unsigned long expires = timer_jiffies + NEXT_TIMER_MAX_DELTA; int index, slot, array, found = 0; struct timer_list *nte; - tvec_t *varray[4]; + struct tvec *varray[4]; /* Look for timer events in tv1. */ index = slot = timer_jiffies & TVR_MASK; @@ -716,7 +714,7 @@ cascade: varray[3] = &base->tv5; for (array = 0; array < 4; array++) { - tvec_t *varp = varray[array]; + struct tvec *varp = varray[array]; index = slot = timer_jiffies & TVN_MASK; do { @@ -795,7 +793,7 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now, */ unsigned long get_next_timer_interrupt(unsigned long now) { - tvec_base_t *base = __get_cpu_var(tvec_bases); + struct tvec_base *base = __get_cpu_var(tvec_bases); unsigned long expires; spin_lock(&base->lock); @@ -894,7 +892,7 @@ static inline void calc_load(unsigned long ticks) */ static void run_timer_softirq(struct softirq_action *h) { - tvec_base_t *base = __get_cpu_var(tvec_bases); + struct tvec_base *base = __get_cpu_var(tvec_bases); hrtimer_run_pending(); @@ -1223,7 +1221,7 @@ static struct lock_class_key base_lock_keys[NR_CPUS]; static int __cpuinit init_timers_cpu(int cpu) { int j; - tvec_base_t *base; + struct tvec_base *base; static char __cpuinitdata tvec_base_done[NR_CPUS]; if (!tvec_base_done[cpu]) { @@ -1278,7 +1276,7 @@ static int __cpuinit init_timers_cpu(int cpu) } #ifdef CONFIG_HOTPLUG_CPU -static void migrate_timer_list(tvec_base_t *new_base, struct list_head *head) +static void migrate_timer_list(struct tvec_base *new_base, struct list_head *head) { struct timer_list *timer; @@ -1292,8 +1290,8 @@ static void migrate_timer_list(tvec_base_t *new_base, struct list_head *head) static void __cpuinit migrate_timers(int cpu) { - tvec_base_t *old_base; - tvec_base_t *new_base; + struct tvec_base *old_base; + struct tvec_base *new_base; int i; BUG_ON(cpu_online(cpu)); From 4c9dc6412247abf4972080c51cd16a58c4009c19 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 30 Jan 2008 13:30:00 +0100 Subject: [PATCH 003/890] time: timer cleanups Small cleanups to tick-related code. Wrong preempt count is followed by BUG(), so it is hardly KERN_WARNING. Signed-off-by: Pavel Machek Cc: john stultz Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- kernel/time/tick-sched.c | 4 ++-- kernel/timer.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 1a21b6fdb674..d36ee2fd1a3b 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -296,7 +296,7 @@ void tick_nohz_stop_sched_tick(void) /* Check, if the timer was already in the past */ if (hrtimer_active(&ts->sched_timer)) goto out; - } else if(!tick_program_event(expires, 0)) + } else if (!tick_program_event(expires, 0)) goto out; /* * We are past the event already. So we crossed a @@ -507,7 +507,7 @@ static inline void tick_nohz_switch_to_nohz(void) { } */ #ifdef CONFIG_HIGH_RES_TIMERS /* - * We rearm the timer until we get disabled by the idle code + * We rearm the timer until we get disabled by the idle code. * Called with interrupts disabled and timer->base->cpu_base->lock held. */ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer) diff --git a/kernel/timer.c b/kernel/timer.c index aadfbc8367f5..23f7ead78fae 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -655,7 +655,7 @@ static inline void __run_timers(struct tvec_base *base) int preempt_count = preempt_count(); fn(data); if (preempt_count != preempt_count()) { - printk(KERN_WARNING "huh, entered %p " + printk(KERN_ERR "huh, entered %p " "with preempt_count %08x, exited" " with %08x?\n", fn, preempt_count, From b10db7f0d2b589a7f88dc3026e150756cb437a28 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 30 Jan 2008 13:30:00 +0100 Subject: [PATCH 004/890] time: more timer related cleanups I was confused by FSEC = 10^15 NSEC statement, plus small whitespace fixes. When there's copyright, there should be GPL. Signed-off-by: Pavel Machek Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/hpet.c | 3 ++- arch/x86/kernel/process_64.c | 2 +- kernel/softirq.c | 4 +++- kernel/time/tick-sched.c | 2 +- kernel/time/timer_stats.c | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 2f99ee206b95..9ec2ab793042 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -16,7 +16,8 @@ #define HPET_MASK CLOCKSOURCE_MASK(32) #define HPET_SHIFT 22 -/* FSEC = 10^-15 NSEC = 10^-9 */ +/* FSEC = 10^-15 + NSEC = 10^-9 */ #define FSEC_PER_NSEC 1000000 /* diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index ab79e1dfa023..c2db7ef93565 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -207,7 +207,7 @@ static inline void play_dead(void) * low exit latency (ie sit in a loop waiting for * somebody to say that they'd like to reschedule) */ -void cpu_idle (void) +void cpu_idle(void) { current_thread_info()->status |= TS_POLLING; /* endless idle loop with no priority at all */ diff --git a/kernel/softirq.c b/kernel/softirq.c index bd89bc4eb0b9..8fe1ff40102d 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -3,7 +3,9 @@ * * Copyright (C) 1992 Linus Torvalds * - * Rewritten. Old one was good in 2.2, but in 2.3 it was immoral. --ANK (990903) + * Distribute under GPLv2. + * + * Rewritten. Old one was good in 2.2, but in 2.3 it was immoral. --ANK (990903) */ #include diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index d36ee2fd1a3b..49e12f6a4bab 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -9,7 +9,7 @@ * * Started by: Thomas Gleixner and Ingo Molnar * - * For licencing details see kernel-base/COPYING + * Distribute under GPLv2. */ #include #include diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c index c36bb7ed0301..417da8c5bc72 100644 --- a/kernel/time/timer_stats.c +++ b/kernel/time/timer_stats.c @@ -26,7 +26,7 @@ * the pid and cmdline from the owner process if applicable. * * Start/stop data collection: - * # echo 1[0] >/proc/timer_stats + * # echo [1|0] >/proc/timer_stats * * Display the information collected so far: * # cat /proc/timer_stats From 186e3cb8a465bac010ee3b020768d2fa2b505aef Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:01 +0100 Subject: [PATCH 005/890] timer: clean up tick-broadcast.c clean up tick-broadcast.c Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- kernel/time/tick-broadcast.c | 7 ++----- kernel/time/tick-internal.h | 2 -- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 5b86698faa0b..e1bd50cbbf5d 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -126,9 +126,9 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) /* * Broadcast the event to the cpus, which are set in the mask */ -int tick_do_broadcast(cpumask_t mask) +static void tick_do_broadcast(cpumask_t mask) { - int ret = 0, cpu = smp_processor_id(); + int cpu = smp_processor_id(); struct tick_device *td; /* @@ -138,7 +138,6 @@ int tick_do_broadcast(cpumask_t mask) cpu_clear(cpu, mask); td = &per_cpu(tick_cpu_device, cpu); td->evtdev->event_handler(td->evtdev); - ret = 1; } if (!cpus_empty(mask)) { @@ -151,9 +150,7 @@ int tick_do_broadcast(cpumask_t mask) cpu = first_cpu(mask); td = &per_cpu(tick_cpu_device, cpu); td->evtdev->broadcast(mask); - ret = 1; } - return ret; } /* diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index bb13f2724905..f13f2b7f4fd4 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -70,8 +70,6 @@ static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc) * Broadcasting support */ #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST -extern int tick_do_broadcast(cpumask_t mask); - extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu); extern int tick_check_broadcast_device(struct clock_event_device *dev); extern int tick_is_broadcast_device(struct clock_event_device *dev); From 1d76c2622813fbc692b0d323028cfef9ee36051a Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Wed, 30 Jan 2008 13:30:01 +0100 Subject: [PATCH 006/890] clocksource: make CLOCKSOURCE_MASK bullet-proof Signed-off-by: Atsushi Nemoto Cc: john stultz Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- include/linux/clocksource.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 107787aacb64..07b42153de24 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -103,7 +103,7 @@ struct clocksource { #define CLOCK_SOURCE_VALID_FOR_HRES 0x20 /* simplify initialization of mask field */ -#define CLOCKSOURCE_MASK(bits) (cycle_t)(bits<64 ? ((1ULL< Date: Wed, 30 Jan 2008 13:30:01 +0100 Subject: [PATCH 007/890] time: fold __get_realtime_clock_ts() into getnstimeofday() - getnstimeofday() was just a wrapper around __get_realtime_clock_ts() - Replace calls to __get_realtime_clock_ts() by calls to getnstimeofday() - Fix bogus reference to get_realtime_clock_ts(), which never existed Signed-off-by: Geert Uytterhoeven Cc: john stultz Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- kernel/time/timekeeping.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index ab46ae8c062b..77680195cf84 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -82,13 +82,12 @@ static inline s64 __get_nsec_offset(void) } /** - * __get_realtime_clock_ts - Returns the time of day in a timespec + * getnstimeofday - Returns the time of day in a timespec * @ts: pointer to the timespec to be set * - * Returns the time of day in a timespec. Used by - * do_gettimeofday() and get_realtime_clock_ts(). + * Returns the time of day in a timespec. */ -static inline void __get_realtime_clock_ts(struct timespec *ts) +void getnstimeofday(struct timespec *ts) { unsigned long seq; s64 nsecs; @@ -104,30 +103,19 @@ static inline void __get_realtime_clock_ts(struct timespec *ts) timespec_add_ns(ts, nsecs); } -/** - * getnstimeofday - Returns the time of day in a timespec - * @ts: pointer to the timespec to be set - * - * Returns the time of day in a timespec. - */ -void getnstimeofday(struct timespec *ts) -{ - __get_realtime_clock_ts(ts); -} - EXPORT_SYMBOL(getnstimeofday); /** * do_gettimeofday - Returns the time of day in a timeval * @tv: pointer to the timeval to be set * - * NOTE: Users should be converted to using get_realtime_clock_ts() + * NOTE: Users should be converted to using getnstimeofday() */ void do_gettimeofday(struct timeval *tv) { struct timespec now; - __get_realtime_clock_ts(&now); + getnstimeofday(&now); tv->tv_sec = now.tv_sec; tv->tv_usec = now.tv_nsec/1000; } From 1077f5a917b7c630231037826b344b2f7f5b903f Mon Sep 17 00:00:00 2001 From: Parag Warudkar Date: Wed, 30 Jan 2008 13:30:01 +0100 Subject: [PATCH 008/890] clocksource.c: use init_timer_deferrable for clocksource_watchdog clocksource_watchdog can use a deferrable timer - reduces wakeups from idle per second. Signed-off-by: Parag Warudkar Cc: john stultz Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- kernel/time/clocksource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 8d6125ad2cf0..cabfa193efb3 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -175,7 +175,7 @@ static void clocksource_check_watchdog(struct clocksource *cs) if (watchdog) del_timer(&watchdog_timer); watchdog = cs; - init_timer(&watchdog_timer); + init_timer_deferrable(&watchdog_timer); watchdog_timer.function = clocksource_watchdog; /* Reset watchdog cycles */ From 1ada5cba6a0318f90e45b38557e7b5206a9cba38 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 30 Jan 2008 13:30:02 +0100 Subject: [PATCH 009/890] clocksource: make clocksource watchdog cycle through online CPUs This way it checks if the clocks are synchronized between CPUs too. This might be able to detect slowly drifting TSCs which only go wrong over longer time. Signed-off-by: Andi Kleen Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- kernel/time/clocksource.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index cabfa193efb3..edd5ef8e1765 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -142,8 +142,13 @@ static void clocksource_watchdog(unsigned long data) } if (!list_empty(&watchdog_list)) { - __mod_timer(&watchdog_timer, - watchdog_timer.expires + WATCHDOG_INTERVAL); + /* Cycle through CPUs to check if the CPUs stay synchronized to + * each other. */ + int next_cpu = next_cpu(raw_smp_processor_id(), cpu_online_map); + if (next_cpu >= NR_CPUS) + next_cpu = first_cpu(cpu_online_map); + watchdog_timer.expires += WATCHDOG_INTERVAL; + add_timer_on(&watchdog_timer, next_cpu); } spin_unlock(&watchdog_lock); } @@ -165,7 +170,7 @@ static void clocksource_check_watchdog(struct clocksource *cs) if (!started && watchdog) { watchdog_last = watchdog->read(); watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL; - add_timer(&watchdog_timer); + add_timer_on(&watchdog_timer, first_cpu(cpu_online_map)); } } else { if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) @@ -186,7 +191,8 @@ static void clocksource_check_watchdog(struct clocksource *cs) watchdog_last = watchdog->read(); watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL; - add_timer(&watchdog_timer); + add_timer_on(&watchdog_timer, + first_cpu(cpu_online_map)); } } } From df619e6bafeb8e129aba3173d384544d7fa6e3c2 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:02 +0100 Subject: [PATCH 010/890] x86: offer is_hpet_enabled() on !CONFIG_HPET_TIMER too offer is_hpet_enabled() on !CONFIG_HPET_TIMER too. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- include/asm-x86/hpet.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/asm-x86/hpet.h b/include/asm-x86/hpet.h index ad8d6e758785..624f600f7161 100644 --- a/include/asm-x86/hpet.h +++ b/include/asm-x86/hpet.h @@ -80,10 +80,11 @@ extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); #endif /* CONFIG_HPET_EMULATE_RTC */ -#else +#else /* CONFIG_HPET_TIMER */ static inline int hpet_enable(void) { return 0; } static inline unsigned long hpet_readl(unsigned long a) { return 0; } +static inline int is_hpet_enabled(void) { return 0; } -#endif /* CONFIG_HPET_TIMER */ +#endif #endif /* ASM_X86_HPET_H */ From 316da3b3fc8efa9a5d2c99e0d449f01ff38c6aba Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:02 +0100 Subject: [PATCH 011/890] x86: restrict PIT clocksource usage PIT clocksource is registered unconditionally even when HPET is enabled or when PIT is replaced by the local APIC timer. In both cases PIT can not be used as it is stopped and the readout would be stale. Prevent registering PIT in those cases. patch depends on: x86: offer is_hpet_enabled() on !CONFIG_HPET_TIMER too Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/i8253.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index a42c80745325..0f8f35458a8f 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c @@ -197,7 +197,15 @@ static struct clocksource clocksource_pit = { static int __init init_pit_clocksource(void) { - if (num_possible_cpus() > 1) /* PIT does not scale! */ + /* + * Several reasons not to register PIT as a clocksource: + * + * - On SMP PIT does not scale due to i8253_lock + * - when HPET is enabled + * - when local APIC timer is active (PIT is switched off) + */ + if (num_possible_cpus() > 1 || is_hpet_enabled() || + pit_clockevent.mode != CLOCK_EVT_MODE_PERIODIC) return 0; clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20); From 4713e22ce81eb8b3353e16435362eb3d0ec95640 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:02 +0100 Subject: [PATCH 012/890] clocksource: add unregister function to disable unusable clocksources On x86 the PIT might become an unusable clocksource. Add an unregister function to provide a possibilty to remove the PIT from the list of available clock sources. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/i8253.c | 1 + include/linux/clocksource.h | 1 + kernel/time/clocksource.c | 15 +++++++++++++++ 3 files changed, 17 insertions(+) diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index 0f8f35458a8f..decc5d294d76 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c @@ -13,6 +13,7 @@ #include #include #include +#include DEFINE_SPINLOCK(i8253_lock); EXPORT_SYMBOL(i8253_lock); diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 07b42153de24..85778a4b1209 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -215,6 +215,7 @@ static inline void clocksource_calculate_interval(struct clocksource *c, /* used to install a new clocksource */ extern int clocksource_register(struct clocksource*); +extern void clocksource_unregister(struct clocksource*); extern struct clocksource* clocksource_get_next(void); extern void clocksource_change_rating(struct clocksource *cs, int rating); extern void clocksource_resume(void); diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index edd5ef8e1765..6e9259a5d501 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -337,6 +337,21 @@ void clocksource_change_rating(struct clocksource *cs, int rating) spin_unlock_irqrestore(&clocksource_lock, flags); } +/** + * clocksource_unregister - remove a registered clocksource + */ +void clocksource_unregister(struct clocksource *cs) +{ + unsigned long flags; + + spin_lock_irqsave(&clocksource_lock, flags); + list_del(&cs->list); + if (clocksource_override == cs) + clocksource_override = NULL; + next_clocksource = select_clocksource(); + spin_unlock_irqrestore(&clocksource_lock, flags); +} + #ifdef CONFIG_SYSFS /** * sysfs_show_current_clocksources - sysfs interface for current clocksource From 1a0c009ac53de4a7664a1239936f0bc258133156 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:03 +0100 Subject: [PATCH 013/890] x86: unregister PIT clocksource when PIT is disabled The following scenario might leave PIT as a disfunctional clock source: PIT is registered as clocksource PM_TIMER is registered as clocksource and enables highres/dyntick mode PIT is switched to oneshot mode -> now the readout of PIT is bogus, but the user might select PIT via the sysfs override, which would break the box as the time readout is unusable. Unregister the PIT clocksource when the PIT clock event device is switched into shutdown / oneshot mode. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/i8253.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index decc5d294d76..377c3f8411f8 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c @@ -18,6 +18,12 @@ DEFINE_SPINLOCK(i8253_lock); EXPORT_SYMBOL(i8253_lock); +#ifdef CONFIG_X86_32 +static void pit_disable_clocksource(void); +#else +static inline void pit_disable_clocksource(void) { } +#endif + /* * HPET replaces the PIT, when enabled. So we need to know, which of * the two timers is used @@ -52,11 +58,13 @@ static void init_pit_timer(enum clock_event_mode mode, outb_p(0, PIT_CH0); outb_p(0, PIT_CH0); } + pit_disable_clocksource(); break; case CLOCK_EVT_MODE_ONESHOT: /* One shot setup */ outb_p(0x38, PIT_MODE); + pit_disable_clocksource(); break; case CLOCK_EVT_MODE_RESUME: @@ -196,6 +204,17 @@ static struct clocksource clocksource_pit = { .shift = 20, }; +static void pit_disable_clocksource(void) +{ + /* + * Use mult to check whether it is registered or not + */ + if (clocksource_pit.mult) { + clocksource_unregister(&clocksource_pit); + clocksource_pit.mult = 0; + } +} + static int __init init_pit_clocksource(void) { /* From 45fe4fe19120a22f7339f5bb110447170c25fca9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:03 +0100 Subject: [PATCH 014/890] x86: make clockevents more robust detect zero event-device multiplicators - they then cause division-by-zero crashes if a clockevent has been initialized incorrectly. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- kernel/time/clockevents.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 5fb139fef9fa..3e59fce6dd43 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -41,6 +41,11 @@ unsigned long clockevent_delta2ns(unsigned long latch, { u64 clc = ((u64) latch << evt->shift); + if (unlikely(!evt->mult)) { + evt->mult = 1; + WARN_ON(1); + } + do_div(clc, evt->mult); if (clc < 1000) clc = 1000; @@ -151,6 +156,14 @@ static void clockevents_notify_released(void) void clockevents_register_device(struct clock_event_device *dev) { BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); + /* + * A nsec2cyc multiplicator of 0 is invalid and we'd crash + * on it, so fix it up and emit a warning: + */ + if (unlikely(!dev->mult)) { + dev->mult = 1; + WARN_ON(1); + } spin_lock(&clockevents_lock); From e3f37a54f690d3e64995ea7ecea08c5ab3070faf Mon Sep 17 00:00:00 2001 From: Balaji Rao Date: Wed, 30 Jan 2008 13:30:03 +0100 Subject: [PATCH 015/890] x86: assign IRQs to HPET timers The userspace API for the HPET (see Documentation/hpet.txt) did not work. The HPET_IE_ON ioctl was failing as there was no IRQ assigned to the timer device. This patch fixes it by allocating IRQs to timer blocks in the HPET. arch/x86/kernel/hpet.c | 13 +++++-------- drivers/char/hpet.c | 45 ++++++++++++++++++++++++++++++++++++++------- include/linux/hpet.h | 2 +- 3 files changed, 44 insertions(+), 16 deletions(-) Signed-off-by: Balaji Rao Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/hpet.c | 13 +++++------- drivers/char/hpet.c | 47 +++++++++++++++++++++++++++++++++++------- include/linux/hpet.h | 2 +- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 9ec2ab793042..786aa227afdf 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -117,8 +117,7 @@ int is_hpet_enabled(void) static void hpet_reserve_platform_timers(unsigned long id) { struct hpet __iomem *hpet = hpet_virt_address; - struct hpet_timer __iomem *timer = &hpet->hpet_timers[2]; - unsigned int nrtimers, i; + unsigned int nrtimers; struct hpet_data hd; nrtimers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1; @@ -133,16 +132,14 @@ static void hpet_reserve_platform_timers(unsigned long id) #ifdef CONFIG_HPET_EMULATE_RTC hpet_reserve_timer(&hd, 1); #endif - hd.hd_irq[0] = HPET_LEGACY_8254; hd.hd_irq[1] = HPET_LEGACY_RTC; - for (i = 2; i < nrtimers; timer++, i++) - hd.hd_irq[i] = (timer->hpet_config & Tn_INT_ROUTE_CNF_MASK) >> - Tn_INT_ROUTE_CNF_SHIFT; - + /* + * IRQs for the other timers are assigned dynamically + * in hpet_alloc + */ hpet_alloc(&hd); - } #else static void hpet_reserve_platform_timers(unsigned long id) { } diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 4c16778e3f84..593b32cfbc33 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -806,14 +806,14 @@ static unsigned long hpet_calibrate(struct hpets *hpetp) int hpet_alloc(struct hpet_data *hdp) { - u64 cap, mcfg; + u64 cap, mcfg, hpet_config; struct hpet_dev *devp; - u32 i, ntimer; + u32 i, ntimer, irq; struct hpets *hpetp; size_t siz; struct hpet __iomem *hpet; static struct hpets *last = NULL; - unsigned long period; + unsigned long period, irq_bitmap; unsigned long long temp; /* @@ -840,12 +840,42 @@ int hpet_alloc(struct hpet_data *hdp) hpetp->hp_hpet_phys = hdp->hd_phys_address; hpetp->hp_ntimer = hdp->hd_nirqs; - - for (i = 0; i < hdp->hd_nirqs; i++) - hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i]; - hpet = hpetp->hp_hpet; + /* Assign IRQs statically for legacy devices */ + hpetp->hp_dev[0].hd_hdwirq = hdp->hd_irq[0]; + hpetp->hp_dev[1].hd_hdwirq = hdp->hd_irq[1]; + + /* Assign IRQs dynamically for the others */ + for (i = 2, devp = &hpetp->hp_dev[2]; i < hdp->hd_nirqs; i++, devp++) { + struct hpet_timer __iomem *timer; + + timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; + + hpet_config = readq(&timer->hpet_config); + irq_bitmap = (hpet_config & Tn_INT_ROUTE_CAP_MASK) + >> Tn_INT_ROUTE_CAP_SHIFT; + if (!irq_bitmap) + irq = 0; /* No valid IRQ Assignable */ + else { + irq = find_first_bit(&irq_bitmap, 32); + do { + hpet_config |= irq << Tn_INT_ROUTE_CNF_SHIFT; + writeq(hpet_config, &timer->hpet_config); + + /* + * Verify whether we have written a valid + * IRQ number by reading it back again + */ + hpet_config = readq(&timer->hpet_config); + if (irq == (hpet_config & Tn_INT_ROUTE_CNF_MASK) + >> Tn_INT_ROUTE_CNF_SHIFT) + break; /* Success */ + } while ((irq = (find_next_bit(&irq_bitmap, 32, irq)))); + } + hpetp->hp_dev[i].hd_hdwirq = irq; + } + cap = readq(&hpet->hpet_cap); ntimer = ((cap & HPET_NUM_TIM_CAP_MASK) >> HPET_NUM_TIM_CAP_SHIFT) + 1; @@ -875,7 +905,8 @@ int hpet_alloc(struct hpet_data *hdp) hpetp->hp_which, hdp->hd_phys_address, hpetp->hp_ntimer > 1 ? "s" : ""); for (i = 0; i < hpetp->hp_ntimer; i++) - printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); + printk("%s %d", i > 0 ? "," : "", + hpetp->hp_dev[i].hd_hdwirq); printk("\n"); printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n", diff --git a/include/linux/hpet.h b/include/linux/hpet.h index 707f7cb9e795..e3c0b2aa944c 100644 --- a/include/linux/hpet.h +++ b/include/linux/hpet.h @@ -64,7 +64,7 @@ struct hpet { */ #define Tn_INT_ROUTE_CAP_MASK (0xffffffff00000000ULL) -#define Tn_INI_ROUTE_CAP_SHIFT (32UL) +#define Tn_INT_ROUTE_CAP_SHIFT (32UL) #define Tn_FSB_INT_DELCAP_MASK (0x8000UL) #define Tn_FSB_INT_DELCAP_SHIFT (15) #define Tn_FSB_EN_CNF_MASK (0x4000UL) From 37a47db8d7f0f38dac5acf5a13abbc8f401707fa Mon Sep 17 00:00:00 2001 From: Balaji Rao Date: Wed, 30 Jan 2008 13:30:03 +0100 Subject: [PATCH 016/890] x86: assign IRQs to HPET timers, fix Looks like IRQ 31 is assigned to timer 3, even without the patch! I wonder who wrote the number 31. But the manual says that it is zero by default. I think we should check whether the timer has been allocated an IRQ before proceeding to assign one to it. Here is a patch that does this. Signed-off-by: Balaji Rao Tested-by: Yinghai Lu Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/hpet.c | 10 +++++----- drivers/char/hpet.c | 6 ++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 786aa227afdf..a3c56c9b8a02 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -117,7 +117,8 @@ int is_hpet_enabled(void) static void hpet_reserve_platform_timers(unsigned long id) { struct hpet __iomem *hpet = hpet_virt_address; - unsigned int nrtimers; + struct hpet_timer __iomem *timer = &hpet->hpet_timers[2]; + unsigned int nrtimers, i; struct hpet_data hd; nrtimers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1; @@ -135,10 +136,9 @@ static void hpet_reserve_platform_timers(unsigned long id) hd.hd_irq[0] = HPET_LEGACY_8254; hd.hd_irq[1] = HPET_LEGACY_RTC; - /* - * IRQs for the other timers are assigned dynamically - * in hpet_alloc - */ + for (i = 2; i < nrtimers; timer++, i++) + hd.hd_irq[i] = (timer->hpet_config & Tn_INT_ROUTE_CNF_MASK) >> + Tn_INT_ROUTE_CNF_SHIFT; hpet_alloc(&hd); } #else diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 593b32cfbc33..22f5fd02ea87 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -852,6 +852,12 @@ int hpet_alloc(struct hpet_data *hdp) timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; + /* Check if there's already an IRQ assigned to the timer */ + if (hdp->hd_irq[i]) { + hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i]; + continue; + } + hpet_config = readq(&timer->hpet_config); irq_bitmap = (hpet_config & Tn_INT_ROUTE_CAP_MASK) >> Tn_INT_ROUTE_CAP_SHIFT; From bbe4d18ac2e058c56adb0cd71f49d9ed3216a405 Mon Sep 17 00:00:00 2001 From: john stultz Date: Wed, 30 Jan 2008 13:30:03 +0100 Subject: [PATCH 017/890] NTP: correct inconsistent ntp interval/tick_length usage I recently noticed on one of my boxes that when synched with an NTP server, the drift value reported for the system was ~283ppm. While in some cases, clock hardware can be that bad, it struck me as unusual as the system was using the acpi_pm clocksource, which is one of the more trustworthy and accurate clocksources on x86 hardware. I brought up another system and let it sync to the same NTP server, and I noticed a similar 280some ppm drift. In looking at the code, I found that the acpi_pm's constant frequency was being computed correctly at boot-up, however once the system was up, even without the ntp daemon running, the clocksource's frequency was being modified by the clocksource_adjust() function. Digging deeper, I realized that in the code that keeps track of how much the clocksource is skewing from the ntp desired time, we were using different lengths to establish how long an time interval was. The clocksource was being setup with the following interval: NTP_INTERVAL_LENGTH = NSEC_PER_SEC/NTP_INTERVAL_FREQ While the ntp code was using the tick_length_base value: tick_length_base ~= (tick_usec * NSEC_PER_USEC * USER_HZ) /NTP_INTERVAL_FREQ The subtle difference is: (tick_usec * NSEC_PER_USEC * USER_HZ) != NSEC_PER_SEC This difference in calculation was causing the clocksource correction code to apply a correction factor to the clocksource so the two intervals were the same, however this results in the actual frequency of the clocksource to be made incorrect. I believe this difference would affect all clocksources, although to differing degrees depending on the clocksource resolution. The issue was introduced when my HZ free ntp patch landed in 2.6.21-rc1, so my apologies for the mistake, and for not noticing it until now. The following patch, corrects the clocksource's initialization code so it uses the same interval length as the code in ntp.c. After applying this patch, the drift value for the same system went from ~283ppm to only 2.635ppm. I believe this patch to be good, however it does affect all arches and I've only tested on x86, so some caution is advised. I do think it would be a likely candidate for a stable 2.6.24.x release. Any thoughts or feedback would be appreciated. Signed-off-by: John Stultz Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- kernel/time/timekeeping.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 77680195cf84..092a2366b5a9 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -186,7 +186,8 @@ static void change_clocksource(void) clock->error = 0; clock->xtime_nsec = 0; - clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH); + clocksource_calculate_interval(clock, + (unsigned long)(current_tick_length()>>TICK_LENGTH_SHIFT)); tick_clock_notify(); @@ -243,7 +244,8 @@ void __init timekeeping_init(void) ntp_clear(); clock = clocksource_get_next(); - clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH); + clocksource_calculate_interval(clock, + (unsigned long)(current_tick_length()>>TICK_LENGTH_SHIFT)); clock->cycle_last = clocksource_read(clock); xtime.tv_sec = sec; From 6378ddb592158db4b42197f1bc8666228800e379 Mon Sep 17 00:00:00 2001 From: Venki Pallipadi Date: Wed, 30 Jan 2008 13:30:04 +0100 Subject: [PATCH 018/890] time: track accurate idle time with tick_sched.idle_sleeptime Current idle time in kstat is based on jiffies and is coarse grained. tick_sched.idle_sleeptime is making some attempt to keep track of idle time in a fine grained manner. But, it is not handling the time spent in interrupts fully. Make tick_sched.idle_sleeptime accurate with respect to time spent on handling interrupts and also add tick_sched.idle_lastupdate, which keeps track of last time when idle_sleeptime was updated. This statistics will be crucial for cpufreq-ondemand governor, which can shed some conservative gaurd band that is uses today while setting the frequency. The ondemand changes that uses the exact idle time is coming soon. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- include/linux/tick.h | 6 ++++ kernel/softirq.c | 7 +++- kernel/time/tick-sched.c | 74 +++++++++++++++++++++++++++------------- 3 files changed, 62 insertions(+), 25 deletions(-) diff --git a/include/linux/tick.h b/include/linux/tick.h index f4a1395e05ff..0fadf95debe1 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -51,8 +51,10 @@ struct tick_sched { unsigned long idle_jiffies; unsigned long idle_calls; unsigned long idle_sleeps; + int idle_active; ktime_t idle_entrytime; ktime_t idle_sleeptime; + ktime_t idle_lastupdate; ktime_t sleep_length; unsigned long last_jiffies; unsigned long next_jiffies; @@ -103,6 +105,8 @@ extern void tick_nohz_stop_sched_tick(void); extern void tick_nohz_restart_sched_tick(void); extern void tick_nohz_update_jiffies(void); extern ktime_t tick_nohz_get_sleep_length(void); +extern void tick_nohz_stop_idle(int cpu); +extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time); # else static inline void tick_nohz_stop_sched_tick(void) { } static inline void tick_nohz_restart_sched_tick(void) { } @@ -113,6 +117,8 @@ static inline ktime_t tick_nohz_get_sleep_length(void) return len; } +static inline void tick_nohz_stop_idle(int cpu) { } +static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return 0; } # endif /* !NO_HZ */ #endif diff --git a/kernel/softirq.c b/kernel/softirq.c index 8fe1ff40102d..d7837d45419e 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -280,9 +280,14 @@ asmlinkage void do_softirq(void) */ void irq_enter(void) { +#ifdef CONFIG_NO_HZ + int cpu = smp_processor_id(); + if (idle_cpu(cpu) && !in_interrupt()) + tick_nohz_stop_idle(cpu); +#endif __irq_enter(); #ifdef CONFIG_NO_HZ - if (idle_cpu(smp_processor_id())) + if (idle_cpu(cpu)) tick_nohz_update_jiffies(); #endif } diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 49e12f6a4bab..63f24b550695 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -143,6 +143,44 @@ void tick_nohz_update_jiffies(void) local_irq_restore(flags); } +void tick_nohz_stop_idle(int cpu) +{ + struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); + + if (ts->idle_active) { + ktime_t now, delta; + now = ktime_get(); + delta = ktime_sub(now, ts->idle_entrytime); + ts->idle_lastupdate = now; + ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); + ts->idle_active = 0; + } +} + +static ktime_t tick_nohz_start_idle(int cpu) +{ + struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); + ktime_t now, delta; + + now = ktime_get(); + if (ts->idle_active) { + delta = ktime_sub(now, ts->idle_entrytime); + ts->idle_lastupdate = now; + ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); + } + ts->idle_entrytime = now; + ts->idle_active = 1; + return now; +} + +u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time) +{ + struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); + + *last_update_time = ktime_to_us(ts->idle_lastupdate); + return ktime_to_us(ts->idle_sleeptime); +} + /** * tick_nohz_stop_sched_tick - stop the idle tick from the idle task * @@ -155,13 +193,14 @@ void tick_nohz_stop_sched_tick(void) unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags; unsigned long rt_jiffies; struct tick_sched *ts; - ktime_t last_update, expires, now, delta; + ktime_t last_update, expires, now; struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; int cpu; local_irq_save(flags); cpu = smp_processor_id(); + now = tick_nohz_start_idle(cpu); ts = &per_cpu(tick_cpu_sched, cpu); /* @@ -193,19 +232,7 @@ void tick_nohz_stop_sched_tick(void) } } - now = ktime_get(); - /* - * When called from irq_exit we need to account the idle sleep time - * correctly. - */ - if (ts->tick_stopped) { - delta = ktime_sub(now, ts->idle_entrytime); - ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); - } - - ts->idle_entrytime = now; ts->idle_calls++; - /* Read jiffies and the time when jiffies were updated last */ do { seq = read_seqbegin(&xtime_lock); @@ -337,23 +364,22 @@ void tick_nohz_restart_sched_tick(void) int cpu = smp_processor_id(); struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); unsigned long ticks; - ktime_t now, delta; - - if (!ts->tick_stopped) - return; - - /* Update jiffies first */ - now = ktime_get(); + ktime_t now; local_irq_disable(); + tick_nohz_stop_idle(cpu); + + if (!ts->tick_stopped) { + local_irq_enable(); + return; + } + + /* Update jiffies first */ select_nohz_load_balancer(0); + now = ktime_get(); tick_do_update_jiffies64(now); cpu_clear(cpu, nohz_cpu_mask); - /* Account the idle time */ - delta = ktime_sub(now, ts->idle_entrytime); - ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); - /* * We stopped the tick in idle. Update process times would miss the * time we slept as update_process_times does only a 1 tick From 9484b1eb4d05957d3114dc63026448eb66106c06 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Wed, 30 Jan 2008 13:30:04 +0100 Subject: [PATCH 019/890] x86: fix make mrproper Michael Opdenacker reported: For backward compatibility with earlier (< 2.6.24) kernels, arch/i386/boot/bzImage or arch/x86_64/boot/bzImage symbolic links to arch/x86/boot/bzImage are created when you build an x86 kernel. The arch/i386 or arch/x86_64 directories are then created for this only purpose. Issue: these generated directories and symbolic links are *not cleaned up* when you run "make mrproper" (and thus "make distclean"). This disturbs the production of patches, because the source tree is left with generated files and directories. Sam has an alternative fix: The directory is killed during make clean as opposed to make mrproper. Reported-by: Michael Opdenacker Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/Makefile_32 | 3 ++- arch/x86/Makefile_64 | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/Makefile_32 b/arch/x86/Makefile_32 index 50394da2f6c1..f806ceccff7a 100644 --- a/arch/x86/Makefile_32 +++ b/arch/x86/Makefile_32 @@ -156,7 +156,8 @@ install: $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install archclean: - $(Q)rm -rf $(objtree)/arch/i386/boot + $(Q)rm -rf $(objtree)/arch/i386 + $(Q)rm -rf $(objtree)/arch/x86_64 $(Q)$(MAKE) $(clean)=arch/x86/boot define archhelp diff --git a/arch/x86/Makefile_64 b/arch/x86/Makefile_64 index a804860022e6..93cf17769ff5 100644 --- a/arch/x86/Makefile_64 +++ b/arch/x86/Makefile_64 @@ -123,7 +123,8 @@ endif $(Q)$(MAKE) $(build)=arch/x86/vdso $@ archclean: - $(Q)rm -rf $(objtree)/arch/x86_64/boot + $(Q)rm -rf $(objtree)/arch/i386 + $(Q)rm -rf $(objtree)/arch/x86_64 $(Q)$(MAKE) $(clean)=$(boot) define archhelp From 5c9c9bec0589be696c70c5efb448b17d5ab720e2 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 30 Jan 2008 13:30:04 +0100 Subject: [PATCH 020/890] x86: hibernation: document __save_processor_state() on x86 Document the fact that __save_processor_state() has to save all CPU registers referred to by the kernel in case a different kernel is used to load and restore a hibernation image containing it. Sigend-off-by: Rafael J. Wysocki Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/suspend_64.c | 20 ++++++++++++++++++++ include/asm-x86/suspend_64.h | 9 ++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/suspend_64.c b/arch/x86/kernel/suspend_64.c index 2e5efaaf8800..569f1b540e36 100644 --- a/arch/x86/kernel/suspend_64.c +++ b/arch/x86/kernel/suspend_64.c @@ -19,6 +19,21 @@ extern const void __nosave_begin, __nosave_end; struct saved_context saved_context; +/** + * __save_processor_state - save CPU registers before creating a + * hibernation image and before restoring the memory state from it + * @ctxt - structure to store the registers contents in + * + * NOTE: If there is a CPU register the modification of which by the + * boot kernel (ie. the kernel used for loading the hibernation image) + * might affect the operations of the restored target kernel (ie. the one + * saved in the hibernation image), then its contents must be saved by this + * function. In other words, if kernel A is hibernated and different + * kernel B is used for loading the hibernation image into memory, the + * kernel A's __save_processor_state() function must save all registers + * needed by kernel A, so that it can operate correctly after the resume + * regardless of what kernel B does in the meantime. + */ void __save_processor_state(struct saved_context *ctxt) { kernel_fpu_begin(); @@ -69,6 +84,11 @@ static void do_fpu_end(void) kernel_fpu_end(); } +/** + * __restore_processor_state - restore the contents of CPU registers saved + * by __save_processor_state() + * @ctxt - structure to load the registers contents from + */ void __restore_processor_state(struct saved_context *ctxt) { /* diff --git a/include/asm-x86/suspend_64.h b/include/asm-x86/suspend_64.h index c505a76bcf6e..4404668f9aa4 100644 --- a/include/asm-x86/suspend_64.h +++ b/include/asm-x86/suspend_64.h @@ -15,7 +15,14 @@ arch_prepare_suspend(void) return 0; } -/* Image of the saved processor state. If you touch this, fix acpi/wakeup.S. */ +/* + * Image of the saved processor state, used by the low level ACPI suspend to + * RAM code and by the low level hibernation code. + * + * If you modify it, fix arch/x86/kernel/acpi/wakeup_64.S and make sure that + * __save/__restore_processor_state(), defined in arch/x86/kernel/suspend_64.c, + * still work as required. + */ struct saved_context { struct pt_regs regs; u16 ds, es, fs, gs, ss; From 4c6b8b4d62fb4cb843c32db71e0a8301039908f3 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Wed, 30 Jan 2008 13:30:04 +0100 Subject: [PATCH 021/890] x86: fix: s2ram + P4 + tsc = annoyance s2ram recently became useful here, except for the kernel's annoying habit of disabling my P4's perfectly good TSC. [ 107.894470] CPU 1 is now offline [ 107.894474] SMP alternatives: switching to UP code [ 107.895832] CPU0 attaching sched-domain: [ 107.895836] domain 0: span 1 [ 107.895838] groups: 1 [ 107.896097] CPU1 is down [ 3.726156] Intel machine check architecture supported. [ 3.726165] Intel machine check reporting enabled on CPU#0. [ 3.726167] CPU0: Intel P4/Xeon Extended MCE MSRs (12) available [ 3.726170] CPU0: Thermal monitoring enabled [ 3.726175] Back to C! [ 3.726708] Force enabled HPET at resume [ 3.726775] Enabling non-boot CPUs ... [ 3.727049] CPU0 attaching NULL sched-domain. [ 3.727165] SMP alternatives: switching to SMP code [ 3.727858] Booting processor 1/1 eip 3000 [ 3.727862] CPU 1 irqstacks, hard=b042f000 soft=b042d000 [ 3.738173] Initializing CPU#1 [ 3.798912] Calibrating delay using timer specific routine.. 5986.12 BogoMIPS (lpj=2993061) [ 3.798920] CPU: After generic identify, caps: bfebfbff 00000000 00000000 00000000 00004400 00000000 00000000 00000000 [ 3.798931] CPU: Trace cache: 12K uops, L1 D cache: 8K [ 3.798934] CPU: L2 cache: 512K [ 3.798936] CPU: Physical Processor ID: 0 [ 3.798938] CPU: After all inits, caps: bfebfbff 00000000 00000000 0000b080 00004400 00000000 00000000 00000000 [ 3.798946] Intel machine check architecture supported. [ 3.798952] Intel machine check reporting enabled on CPU#1. [ 3.798955] CPU1: Intel P4/Xeon Extended MCE MSRs (12) available [ 3.798959] CPU1: Thermal monitoring enabled [ 3.799161] CPU1: Intel(R) Pentium(R) 4 CPU 3.00GHz stepping 09 [ 3.799187] checking TSC synchronization [CPU#0 -> CPU#1]: [ 3.819181] Measured 63588552840 cycles TSC warp between CPUs, turning off TSC clock. [ 3.819184] Marking TSC unstable due to: check_tsc_sync_source failed. If check_tsc_warp() is called after initial boot, and the TSC has in the meantime been set (BIOS, user, silicon, elves) to a value lower than the last stored/stale value, we blame the TSC. Reset to pristine condition after every test. Signed-off-by: Mike Galbraith Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/tsc_sync.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index 9125efe66a06..05d8f25de6ae 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c @@ -129,23 +129,23 @@ void __cpuinit check_tsc_sync_source(int cpu) while (atomic_read(&stop_count) != cpus-1) cpu_relax(); - /* - * Reset it - just in case we boot another CPU later: - */ - atomic_set(&start_count, 0); - if (nr_warps) { printk("\n"); printk(KERN_WARNING "Measured %Ld cycles TSC warp between CPUs," " turning off TSC clock.\n", max_warp); mark_tsc_unstable("check_tsc_sync_source failed"); - nr_warps = 0; - max_warp = 0; - last_tsc = 0; } else { printk(" passed.\n"); } + /* + * Reset it - just in case we boot another CPU later: + */ + atomic_set(&start_count, 0); + nr_warps = 0; + max_warp = 0; + last_tsc = 0; + /* * Let the target continue with the bootup: */ From b02aae9cf52956dfe1bec73f77f81a3d05d3902b Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Wed, 30 Jan 2008 13:30:05 +0100 Subject: [PATCH 022/890] x86: provide a DMI based port 0x80 I/O delay override. x86: provide a DMI based port 0x80 I/O delay override. Certain (HP) laptops experience trouble from our port 0x80 I/O delay writes. This patch provides for a DMI based switch to the "alternate diagnostic port" 0xed (as used by some BIOSes as well) for these. David P. Reed confirmed that port 0xed works for him and provides a proper delay. The symptoms of _not_ working are a hanging machine, with "hwclock" use being a direct trigger. Earlier versions of this attempted to simply use udelay(2), with the 2 being a value tested to be a nicely conservative upper-bound with help from many on the linux-kernel mailinglist but that approach has two problems. First, pre-loops_per_jiffy calibration (which is post PIT init while some implementations of the PIT are actually one of the historically problematic devices that need the delay) udelay() isn't particularly well-defined. We could initialise loops_per_jiffy conservatively (and based on CPU family so as to not unduly delay old machines) which would sort of work, but... Second, delaying isn't the only effect that a write to port 0x80 has. It's also a PCI posting barrier which some devices may be explicitly or implicitly relying on. Alan Cox did a survey and found evidence that additionally some drivers may be racy on SMP without the bus locking outb. Switching to an inb() makes the timing too unpredictable and as such, this DMI based switch should be the safest approach for now. Any more invasive changes should get more rigid testing first. It's moreover only very few machines with the problem and a DMI based hack seems to fit that situation. This also introduces a command-line parameter "io_delay" to override the DMI based choice again: io_delay= where "standard" means using the standard port 0x80 and "alternate" port 0xed. This retains the udelay method as a config (CONFIG_UDELAY_IO_DELAY) and command-line ("io_delay=udelay") choice for testing purposes as well. This does not change the io_delay() in the boot code which is using the same port 0x80 I/O delay but those do not appear to be a problem as David P. Reed reported the problem was already gone after using the udelay version. He moreover reported that booting with "acpi=off" also fixed things and seeing as how ACPI isn't touched until after this DMI based I/O port switch I believe it's safe to leave the ones in the boot code be. The DMI strings from David's HP Pavilion dv9000z are in there already and we need to get/verify the DMI info from other machines with the problem, notably the HP Pavilion dv6000z. This patch is partly based on earlier patches from Pavel Machek and David P. Reed. Signed-off-by: Rene Herman Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- Documentation/kernel-parameters.txt | 8 +++ arch/x86/Kconfig.debug | 9 +++ arch/x86/boot/compressed/misc_32.c | 8 +-- arch/x86/boot/compressed/misc_64.c | 8 +-- arch/x86/kernel/Makefile_32 | 2 +- arch/x86/kernel/Makefile_64 | 2 +- arch/x86/kernel/io_delay.c | 106 ++++++++++++++++++++++++++++ arch/x86/kernel/setup_32.c | 2 + arch/x86/kernel/setup_64.c | 2 + include/asm-x86/io_32.h | 8 ++- include/asm-x86/io_64.h | 35 +++++---- 11 files changed, 166 insertions(+), 24 deletions(-) create mode 100644 arch/x86/kernel/io_delay.c diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 880f882160e2..9e6056058425 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -794,6 +794,14 @@ and is between 256 and 4096 characters. It is defined in the file for translation below 32 bit and if not available then look in the higher range. + io_delay= [X86-32,X86-64] I/O delay method + standard + Standard port 0x80 delay + alternate + Alternate port 0xed delay + udelay + Simple two microsecond delay + io7= [HW] IO7 for Marvel based alpha systems See comment before marvel_specify_io7 in arch/alpha/kernel/core_marvel.c. diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 761ca7b5f120..40aba670fb37 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -112,4 +112,13 @@ config IOMMU_LEAK Add a simple leak tracer to the IOMMU code. This is useful when you are debugging a buggy device driver that leaks IOMMU mappings. +config UDELAY_IO_DELAY + bool "Delay I/O through udelay instead of outb" + depends on DEBUG_KERNEL + help + Make inb_p/outb_p use udelay() based delays by default. Please note + that udelay() does not have the same bus-level side-effects that + the normal outb based delay does meaning this could cause drivers + to change behaviour and/or bugs to surface. + endmenu diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c index b74d60d1b2fa..288e16283ef9 100644 --- a/arch/x86/boot/compressed/misc_32.c +++ b/arch/x86/boot/compressed/misc_32.c @@ -276,10 +276,10 @@ static void putstr(const char *s) RM_SCREEN_INFO.orig_y = y; pos = (x + cols * y) * 2; /* Update cursor position */ - outb_p(14, vidport); - outb_p(0xff & (pos >> 9), vidport+1); - outb_p(15, vidport); - outb_p(0xff & (pos >> 1), vidport+1); + outb(14, vidport); + outb(0xff & (pos >> 9), vidport+1); + outb(15, vidport); + outb(0xff & (pos >> 1), vidport+1); } static void* memset(void* s, int c, unsigned n) diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c index 6ea015aa65e4..43e5fcc37be9 100644 --- a/arch/x86/boot/compressed/misc_64.c +++ b/arch/x86/boot/compressed/misc_64.c @@ -269,10 +269,10 @@ static void putstr(const char *s) RM_SCREEN_INFO.orig_y = y; pos = (x + cols * y) * 2; /* Update cursor position */ - outb_p(14, vidport); - outb_p(0xff & (pos >> 9), vidport+1); - outb_p(15, vidport); - outb_p(0xff & (pos >> 1), vidport+1); + outb(14, vidport); + outb(0xff & (pos >> 9), vidport+1); + outb(15, vidport); + outb(0xff & (pos >> 1), vidport+1); } static void* memset(void* s, int c, unsigned n) diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32 index a7bc93c27662..0cc1981d1e38 100644 --- a/arch/x86/kernel/Makefile_32 +++ b/arch/x86/kernel/Makefile_32 @@ -8,7 +8,7 @@ CPPFLAGS_vmlinux.lds += -Ui386 obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \ ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \ pci-dma_32.o i386_ksyms_32.o i387_32.o bootflag.o e820_32.o\ - quirks.o i8237.o topology.o alternative.o i8253.o tsc_32.o + quirks.o i8237.o topology.o alternative.o i8253.o tsc_32.o io_delay.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-y += cpu/ diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64 index 5a88890d8ee9..08a68f0d8fda 100644 --- a/arch/x86/kernel/Makefile_64 +++ b/arch/x86/kernel/Makefile_64 @@ -11,7 +11,7 @@ obj-y := process_64.o signal_64.o entry_64.o traps_64.o irq_64.o \ x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \ setup64.o bootflag.o e820_64.o reboot_64.o quirks.o i8237.o \ pci-dma_64.o pci-nommu_64.o alternative.o hpet.o tsc_64.o bugs_64.o \ - i8253.o + i8253.o io_delay.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-y += cpu/ diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c new file mode 100644 index 000000000000..4d955e74b974 --- /dev/null +++ b/arch/x86/kernel/io_delay.c @@ -0,0 +1,106 @@ +/* + * I/O delay strategies for inb_p/outb_p + */ +#include +#include +#include +#include +#include +#include + +/* + * Allow for a DMI based override of port 0x80 needed for certain HP laptops + */ +#define IO_DELAY_PORT_STD 0x80 +#define IO_DELAY_PORT_ALT 0xed + +static void standard_io_delay(void) +{ + asm volatile ("outb %%al, %0" : : "N" (IO_DELAY_PORT_STD)); +} + +static void alternate_io_delay(void) +{ + asm volatile ("outb %%al, %0" : : "N" (IO_DELAY_PORT_ALT)); +} + +/* + * 2 usecs is an upper-bound for the outb delay but note that udelay doesn't + * have the bus-level side-effects that outb does + */ +#define IO_DELAY_USECS 2 + +/* + * High on a hill was a lonely goatherd + */ +static void udelay_io_delay(void) +{ + udelay(IO_DELAY_USECS); +} + +#ifndef CONFIG_UDELAY_IO_DELAY +static void (*io_delay)(void) = standard_io_delay; +#else +static void (*io_delay)(void) = udelay_io_delay; +#endif + +/* + * Paravirt wants native_io_delay to be a constant. + */ +void native_io_delay(void) +{ + io_delay(); +} +EXPORT_SYMBOL(native_io_delay); + +#ifndef CONFIG_UDELAY_IO_DELAY +static int __init dmi_alternate_io_delay_port(const struct dmi_system_id *id) +{ + printk(KERN_NOTICE "%s: using alternate I/O delay port\n", id->ident); + io_delay = alternate_io_delay; + return 0; +} + +static struct dmi_system_id __initdata alternate_io_delay_port_dmi_table[] = { + { + .callback = dmi_alternate_io_delay_port, + .ident = "HP Pavilion dv9000z", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"), + DMI_MATCH(DMI_BOARD_NAME, "30B9") + } + }, + { + } +}; + +static int __initdata io_delay_override; + +void __init io_delay_init(void) +{ + if (!io_delay_override) + dmi_check_system(alternate_io_delay_port_dmi_table); +} +#endif + +static int __init io_delay_param(char *s) +{ + if (!s) + return -EINVAL; + + if (!strcmp(s, "standard")) + io_delay = standard_io_delay; + else if (!strcmp(s, "alternate")) + io_delay = alternate_io_delay; + else if (!strcmp(s, "udelay")) + io_delay = udelay_io_delay; + else + return -EINVAL; + +#ifndef CONFIG_UDELAY_IO_DELAY + io_delay_override = 1; +#endif + return 0; +} + +early_param("io_delay", io_delay_param); diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index 9c24b45b513c..51bdc0b1b72e 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -648,6 +648,8 @@ void __init setup_arch(char **cmdline_p) dmi_scan_machine(); + io_delay_init();; + #ifdef CONFIG_X86_GENERICARCH generic_apic_probe(); #endif diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 30d94d1d5f5f..ec976edf0399 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -311,6 +311,8 @@ void __init setup_arch(char **cmdline_p) dmi_scan_machine(); + io_delay_init(); + #ifdef CONFIG_SMP /* setup to use the static apicid table during kernel startup */ x86_cpu_to_apicid_ptr = (void *)&x86_cpu_to_apicid_init; diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h index fe881cd1e6f4..a8d25c38b91c 100644 --- a/include/asm-x86/io_32.h +++ b/include/asm-x86/io_32.h @@ -250,10 +250,14 @@ static inline void flush_write_buffers(void) #endif /* __KERNEL__ */ -static inline void native_io_delay(void) +#ifndef CONFIG_UDELAY_IO_DELAY +extern void io_delay_init(void); +#else +static inline void io_delay_init(void) { - asm volatile("outb %%al,$0x80" : : : "memory"); } +#endif +extern void native_io_delay(void); #if defined(CONFIG_PARAVIRT) #include diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h index a037b0794332..5bebaf961692 100644 --- a/include/asm-x86/io_64.h +++ b/include/asm-x86/io_64.h @@ -35,13 +35,24 @@ * - Arnaldo Carvalho de Melo */ -#define __SLOW_DOWN_IO "\noutb %%al,$0x80" - -#ifdef REALLY_SLOW_IO -#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO +#ifndef CONFIG_UDELAY_IO_DELAY +extern void io_delay_init(void); #else -#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO +static inline void io_delay_init(void) +{ +} #endif +extern void native_io_delay(void); + +static inline void slow_down_io(void) +{ + native_io_delay(); +#ifdef REALLY_SLOW_IO + native_io_delay(); + native_io_delay(); + native_io_delay(); +#endif +} /* * Talk about misusing macros.. @@ -50,21 +61,21 @@ static inline void out##s(unsigned x value, unsigned short port) { #define __OUT2(s,s1,s2) \ -__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" +__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" : : "a" (value), "Nd" (port)) #define __OUT(s,s1,x) \ -__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \ -__OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} \ +__OUT1(s,x) __OUT2(s,s1,"w"); } \ +__OUT1(s##_p,x) __OUT2(s,s1,"w"); slow_down_io(); } #define __IN1(s) \ static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v; #define __IN2(s,s1,s2) \ -__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" +__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" : "=a" (_v) : "Nd" (port)) -#define __IN(s,s1,i...) \ -__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \ -__IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \ +#define __IN(s,s1) \ +__IN1(s) __IN2(s,s1,"w"); return _v; } \ +__IN1(s##_p) __IN2(s,s1,"w"); slow_down_io(); return _v; } #define __INS(s) \ static inline void ins##s(unsigned short port, void * addr, unsigned long count) \ From 6e7c402590b75b6b45138792445ee0f0315a8473 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:05 +0100 Subject: [PATCH 023/890] x86: various changes and cleanups to in_p/out_p delay details various changes to the in_p/out_p delay details: - add the io_delay=none method - make each method selectable from the kernel config - simplify the delay code a bit by getting rid of an indirect function call - add the /proc/sys/kernel/io_delay_type sysctl - change 'io_delay=standard|alternate' to io_delay=0x80 and io_delay=0xed - make the io delay config not depend on CONFIG_DEBUG_KERNEL Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner Tested-by: "David P. Reed" --- Documentation/kernel-parameters.txt | 12 ++-- arch/x86/Kconfig.debug | 79 +++++++++++++++++++-- arch/x86/kernel/io_delay.c | 106 +++++++++++++--------------- include/asm-x86/io_32.h | 10 +-- include/asm-x86/io_64.h | 10 +-- kernel/sysctl.c | 9 +++ 6 files changed, 143 insertions(+), 83 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 9e6056058425..b427b7c0e5d0 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -795,12 +795,14 @@ and is between 256 and 4096 characters. It is defined in the file then look in the higher range. io_delay= [X86-32,X86-64] I/O delay method - standard - Standard port 0x80 delay - alternate - Alternate port 0xed delay + 0x80 + Standard port 0x80 based delay + 0xed + Alternate port 0xed based delay (needed on some systems) udelay - Simple two microsecond delay + Simple two microseconds delay + none + No delay io7= [HW] IO7 for Marvel based alpha systems See comment before marvel_specify_io7 in diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 40aba670fb37..77eda46f97b8 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -112,13 +112,78 @@ config IOMMU_LEAK Add a simple leak tracer to the IOMMU code. This is useful when you are debugging a buggy device driver that leaks IOMMU mappings. -config UDELAY_IO_DELAY - bool "Delay I/O through udelay instead of outb" - depends on DEBUG_KERNEL +# +# IO delay types: +# + +config IO_DELAY_TYPE_0X80 + int + default "0" + +config IO_DELAY_TYPE_0XED + int + default "1" + +config IO_DELAY_TYPE_UDELAY + int + default "2" + +config IO_DELAY_TYPE_NONE + int + default "3" + +choice + prompt "IO delay type" + default IO_DELAY_0X80 + +config IO_DELAY_0X80 + bool "port 0x80 based port-IO delay [recommended]" help - Make inb_p/outb_p use udelay() based delays by default. Please note - that udelay() does not have the same bus-level side-effects that - the normal outb based delay does meaning this could cause drivers - to change behaviour and/or bugs to surface. + This is the traditional Linux IO delay used for in/out_p. + It is the most tested hence safest selection here. + +config IO_DELAY_0XED + bool "port 0xed based port-IO delay" + help + Use port 0xed as the IO delay. This frees up port 0x80 which is + often used as a hardware-debug port. + +config IO_DELAY_UDELAY + bool "udelay based port-IO delay" + help + Use udelay(2) as the IO delay method. This provides the delay + while not having any side-effect on the IO port space. + +config IO_DELAY_NONE + bool "no port-IO delay" + help + No port-IO delay. Will break on old boxes that require port-IO + delay for certain operations. Should work on most new machines. + +endchoice + +if IO_DELAY_0X80 +config DEFAULT_IO_DELAY_TYPE + int + default IO_DELAY_TYPE_0X80 +endif + +if IO_DELAY_0XED +config DEFAULT_IO_DELAY_TYPE + int + default IO_DELAY_TYPE_0XED +endif + +if IO_DELAY_UDELAY +config DEFAULT_IO_DELAY_TYPE + int + default IO_DELAY_TYPE_UDELAY +endif + +if IO_DELAY_NONE +config DEFAULT_IO_DELAY_TYPE + int + default IO_DELAY_TYPE_NONE +endif endmenu diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c index 4d955e74b974..f052e34dc94c 100644 --- a/arch/x86/kernel/io_delay.c +++ b/arch/x86/kernel/io_delay.c @@ -1,5 +1,9 @@ /* * I/O delay strategies for inb_p/outb_p + * + * Allow for a DMI based override of port 0x80, needed for certain HP laptops + * and possibly other systems. Also allow for the gradual elimination of + * outb_p/inb_p API uses. */ #include #include @@ -8,98 +12,86 @@ #include #include -/* - * Allow for a DMI based override of port 0x80 needed for certain HP laptops - */ -#define IO_DELAY_PORT_STD 0x80 -#define IO_DELAY_PORT_ALT 0xed +int io_delay_type __read_mostly = CONFIG_DEFAULT_IO_DELAY_TYPE; +EXPORT_SYMBOL_GPL(io_delay_type); -static void standard_io_delay(void) -{ - asm volatile ("outb %%al, %0" : : "N" (IO_DELAY_PORT_STD)); -} - -static void alternate_io_delay(void) -{ - asm volatile ("outb %%al, %0" : : "N" (IO_DELAY_PORT_ALT)); -} - -/* - * 2 usecs is an upper-bound for the outb delay but note that udelay doesn't - * have the bus-level side-effects that outb does - */ -#define IO_DELAY_USECS 2 - -/* - * High on a hill was a lonely goatherd - */ -static void udelay_io_delay(void) -{ - udelay(IO_DELAY_USECS); -} - -#ifndef CONFIG_UDELAY_IO_DELAY -static void (*io_delay)(void) = standard_io_delay; -#else -static void (*io_delay)(void) = udelay_io_delay; -#endif +static int __initdata io_delay_override; /* * Paravirt wants native_io_delay to be a constant. */ void native_io_delay(void) { - io_delay(); + switch (io_delay_type) { + default: + case CONFIG_IO_DELAY_TYPE_0X80: + asm volatile ("outb %al, $0x80"); + break; + case CONFIG_IO_DELAY_TYPE_0XED: + asm volatile ("outb %al, $0xed"); + break; + case CONFIG_IO_DELAY_TYPE_UDELAY: + /* + * 2 usecs is an upper-bound for the outb delay but + * note that udelay doesn't have the bus-level + * side-effects that outb does, nor does udelay() have + * precise timings during very early bootup (the delays + * are shorter until calibrated): + */ + udelay(2); + case CONFIG_IO_DELAY_TYPE_NONE: + break; + } } EXPORT_SYMBOL(native_io_delay); -#ifndef CONFIG_UDELAY_IO_DELAY -static int __init dmi_alternate_io_delay_port(const struct dmi_system_id *id) +static int __init dmi_io_delay_0xed_port(const struct dmi_system_id *id) { - printk(KERN_NOTICE "%s: using alternate I/O delay port\n", id->ident); - io_delay = alternate_io_delay; + if (io_delay_type == CONFIG_IO_DELAY_TYPE_0X80) { + printk(KERN_NOTICE "%s: using 0xed I/O delay port\n", + id->ident); + io_delay_type = CONFIG_IO_DELAY_TYPE_0XED; + } + return 0; } -static struct dmi_system_id __initdata alternate_io_delay_port_dmi_table[] = { +/* + * Quirk table for systems that misbehave (lock up, etc.) if port + * 0x80 is used: + */ +static struct dmi_system_id __initdata io_delay_0xed_port_dmi_table[] = { { - .callback = dmi_alternate_io_delay_port, + .callback = dmi_io_delay_0xed_port, .ident = "HP Pavilion dv9000z", .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"), DMI_MATCH(DMI_BOARD_NAME, "30B9") } }, - { - } + { } }; -static int __initdata io_delay_override; - void __init io_delay_init(void) { if (!io_delay_override) - dmi_check_system(alternate_io_delay_port_dmi_table); + dmi_check_system(io_delay_0xed_port_dmi_table); } -#endif static int __init io_delay_param(char *s) { - if (!s) - return -EINVAL; - - if (!strcmp(s, "standard")) - io_delay = standard_io_delay; - else if (!strcmp(s, "alternate")) - io_delay = alternate_io_delay; + if (!strcmp(s, "0x80")) + io_delay_type = CONFIG_IO_DELAY_TYPE_0X80; + else if (!strcmp(s, "0xed")) + io_delay_type = CONFIG_IO_DELAY_TYPE_0XED; else if (!strcmp(s, "udelay")) - io_delay = udelay_io_delay; + io_delay_type = CONFIG_IO_DELAY_TYPE_UDELAY; + else if (!strcmp(s, "none")) + io_delay_type = CONFIG_IO_DELAY_TYPE_NONE; else return -EINVAL; -#ifndef CONFIG_UDELAY_IO_DELAY io_delay_override = 1; -#endif return 0; } diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h index a8d25c38b91c..2a04bd17eac5 100644 --- a/include/asm-x86/io_32.h +++ b/include/asm-x86/io_32.h @@ -250,15 +250,11 @@ static inline void flush_write_buffers(void) #endif /* __KERNEL__ */ -#ifndef CONFIG_UDELAY_IO_DELAY -extern void io_delay_init(void); -#else -static inline void io_delay_init(void) -{ -} -#endif extern void native_io_delay(void); +extern int io_delay_type; +extern void io_delay_init(void); + #if defined(CONFIG_PARAVIRT) #include #else diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h index 5bebaf961692..dbcc03aa1c6a 100644 --- a/include/asm-x86/io_64.h +++ b/include/asm-x86/io_64.h @@ -35,15 +35,11 @@ * - Arnaldo Carvalho de Melo */ -#ifndef CONFIG_UDELAY_IO_DELAY -extern void io_delay_init(void); -#else -static inline void io_delay_init(void) -{ -} -#endif extern void native_io_delay(void); +extern int io_delay_type; +extern void io_delay_init(void); + static inline void slow_down_io(void) { native_io_delay(); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4bc8e48434a7..357b68ba23ec 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -53,6 +53,7 @@ #ifdef CONFIG_X86 #include #include +#include #endif static int deprecated_sysctl_warning(struct __sysctl_args *args); @@ -727,6 +728,14 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "io_delay_type", + .data = &io_delay_type, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, #endif #if defined(CONFIG_MMU) { From d0049e71c6e14a3b0a5b8cedaa1325a1a91fecb0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:05 +0100 Subject: [PATCH 024/890] x86: make io_delay=0xed the default make io_delay=0xed the default. This frees up port 0x80 which is a debug port on some machines and locks up certain laptops. Testing only for now. Try the io_delay=0x80 boot option if this does not work for you. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 77eda46f97b8..b747ab38814d 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -134,7 +134,7 @@ config IO_DELAY_TYPE_NONE choice prompt "IO delay type" - default IO_DELAY_0X80 + default IO_DELAY_0XED config IO_DELAY_0X80 bool "port 0x80 based port-IO delay [recommended]" From f9fc58910ebc448b0b7d37af1bf57a896a78e9c4 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:05 +0100 Subject: [PATCH 025/890] x86: add DMI quirk for io-delay hangs on Compaq Presario V6000 laptops add the DMI strings provided by Islam Amer , for the Compaq Presario V6000 (Quanta/30B7). Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/io_delay.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c index f052e34dc94c..bd49321034db 100644 --- a/arch/x86/kernel/io_delay.c +++ b/arch/x86/kernel/io_delay.c @@ -61,6 +61,14 @@ static int __init dmi_io_delay_0xed_port(const struct dmi_system_id *id) * 0x80 is used: */ static struct dmi_system_id __initdata io_delay_0xed_port_dmi_table[] = { + { + .callback = dmi_io_delay_0xed_port, + .ident = "Compaq Presario V6000", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"), + DMI_MATCH(DMI_BOARD_NAME, "30B7") + } + }, { .callback = dmi_io_delay_0xed_port, .ident = "HP Pavilion dv9000z", @@ -69,6 +77,14 @@ static struct dmi_system_id __initdata io_delay_0xed_port_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "30B9") } }, + { + .callback = dmi_io_delay_0xed_port, + .ident = "HP Pavilion tx1000", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"), + DMI_MATCH(DMI_BOARD_NAME, "30BF") + } + }, { } }; From 83bd01024b1fdfc41d9b758e5669e80fca72df66 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 30 Jan 2008 13:30:06 +0100 Subject: [PATCH 026/890] x86: protect against sigaltstack wraparound cf http://lkml.org/lkml/2007/10/3/41 To summarize: on Linux, SA_ONSTACK decides whether you are already on the signal stack based on the value of the SP at the time of a signal. If you are not already inside the range, you are not "on the signal stack" and so the new signal handler frame starts over at the base of the signal stack. sigaltstack (and sigstack before it) was invented in BSD. There, the SA_ONSTACK behavior has always been different. It uses a kernel state flag to decide, rather than the SP value. When you first take an SA_ONSTACK signal and switch to the alternate signal stack, it sets the SS_ONSTACK flag in the thread's sigaltstack state in the kernel. Thereafter you are "on the signal stack" and don't switch SP before pushing a handler frame no matter what the SP value is. Only when you sigreturn from the original handler context do you clear the SS_ONSTACK flag so that a new handler frame will start over at the base of the alternate signal stack. The undesireable effect of the Linux behavior is that an overflow of the alternate signal stack can not only go undetected, but lead to a ring buffer effect of clobbering the original handler frame at the base of the signal stack for each successive signal that comes just after the overflow. This is what Shi Weihua's test case demonstrates. Normally this does not come up because of the signal mask, but the test case uses SA_NODEFER for its SIGSEGV handler. The other subtle part of the existing Linux semantics is that a simple longjmp out of a signal handler serves to take you off the signal stack in a safe and reliable fashion without having used sigreturn (nor having just returned from the handler normally, which means the same). After the longjmp (or even informal stack switching not via any proper libc or kernel interface), the alternate signal stack stands ready to be used again. A paranoid program would allocate a PROT_NONE red zone around its alternate signal stack. Then a small overflow would trigger a SIGSEGV in handler setup, and be fatal (core dump) whether or not SIGSEGV is blocked. As with thread stack red zones, that cannot catch all overflows (or underflows). e.g., a local array as large as page size allocated in a function called from a handler, but not actually touched before more calls push more stack, could cause an overflow that silently pushes into some unrelated allocated pages. The BSD behavior does not do anything in particular about overflow. But it does at least avoid the wraparound or "ring buffer effect", so you'll just get a straightforward all-out overflow down your address space past the low end of the alternate signal stack. I don't know what the BSD behavior is for longjmp out of an SA_ONSTACK handler. The POSIX wording relating to sigaltstack is pretty minimal. I don't think it speaks to this issue one way or another. (The program that overflows its stack is clearly in undefined behavior territory of one sort or another anyhow.) Given the longjmp issue and the potential for highly subtle complications in existing programs relying on this in arcane ways deep in their code, I am very dubious about changing the behavior to the BSD style persistent flag. I think Shi Weihua's patches have a similar effect by tracking the SP used in the last handler setup. I think it would be sensible for the signal handler setup code to detect when it would itself be causing a stack overflow. Maybe something like the following patch (untested). This issue exists in the same way on all machines, so ideally they would all do a similar check. When it's the handler function itself or its callees that cause the overflow, rather than the signal handler frame setup alone crossing the boundary, this still won't help. But I don't see any way to distinguish that from the valid longjmp case. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/signal_32.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 20f29e4c1d33..5c6170c44b00 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -295,6 +295,13 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) /* Default to using normal stack */ esp = regs->esp; + /* + * If we are on the alternate signal stack and would overflow it, don't. + * Return an always-bogus address instead so we will die with SIGSEGV. + */ + if (on_sig_stack(esp) && !likely(on_sig_stack(esp - frame_size))) + return (void __user *) -1L; + /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (sas_ss_flags(esp) == 0) From 53d517cdbaac704352b3d0c10fecb99e0b54572e Mon Sep 17 00:00:00 2001 From: Guillaume Chazarain Date: Wed, 30 Jan 2008 13:30:06 +0100 Subject: [PATCH 027/890] x86: scale cyc_2_nsec according to CPU frequency scale the sched_clock() cyc_2_nsec scaling factor according to CPU frequency changes. [ mingo@elte.hu: simplified it and fixed it for SMP. ] Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/tsc_32.c | 43 +++++++++++++++++++++++++----- arch/x86/kernel/tsc_64.c | 57 +++++++++++++++++++++++++++++++++------- include/asm-x86/timer.h | 23 ++++++++++++---- 3 files changed, 102 insertions(+), 21 deletions(-) diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c index 9ebc0dab66b4..00bb4c1c0593 100644 --- a/arch/x86/kernel/tsc_32.c +++ b/arch/x86/kernel/tsc_32.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -80,13 +81,31 @@ EXPORT_SYMBOL_GPL(check_tsc_unstable); * * -johnstul@us.ibm.com "math is hard, lets go shopping!" */ -unsigned long cyc2ns_scale __read_mostly; -#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ +DEFINE_PER_CPU(unsigned long, cyc2ns); -static inline void set_cyc2ns_scale(unsigned long cpu_khz) +static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu) { - cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; + unsigned long flags, prev_scale, *scale; + unsigned long long tsc_now, ns_now; + + local_irq_save(flags); + sched_clock_idle_sleep_event(); + + scale = &per_cpu(cyc2ns, cpu); + + rdtscll(tsc_now); + ns_now = __cycles_2_ns(tsc_now); + + prev_scale = *scale; + if (cpu_khz) + *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz; + + /* + * Start smoothly with the new frequency: + */ + sched_clock_idle_wakeup_event(0); + local_irq_restore(flags); } /* @@ -239,7 +258,9 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) ref_freq, freq->new); if (!(freq->flags & CPUFREQ_CONST_LOOPS)) { tsc_khz = cpu_khz; - set_cyc2ns_scale(cpu_khz); + preempt_disable(); + set_cyc2ns_scale(cpu_khz, smp_processor_id()); + preempt_enable(); /* * TSC based sched_clock turns * to junk w/ cpufreq @@ -367,6 +388,8 @@ static inline void check_geode_tsc_reliable(void) { } void __init tsc_init(void) { + int cpu; + if (!cpu_has_tsc || tsc_disable) goto out_no_tsc; @@ -380,7 +403,15 @@ void __init tsc_init(void) (unsigned long)cpu_khz / 1000, (unsigned long)cpu_khz % 1000); - set_cyc2ns_scale(cpu_khz); + /* + * Secondary CPUs do not run through tsc_init(), so set up + * all the scale factors for all CPUs, assuming the same + * speed as the bootup CPU. (cpufreq notifiers will fix this + * up if their speed diverges) + */ + for_each_possible_cpu(cpu) + set_cyc2ns_scale(cpu_khz, cpu); + use_tsc_delay(); /* Check and install the TSC clocksource */ diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c index 9c70af45b42b..32edd2c50e94 100644 --- a/arch/x86/kernel/tsc_64.c +++ b/arch/x86/kernel/tsc_64.c @@ -10,6 +10,7 @@ #include #include +#include static int notsc __initdata = 0; @@ -18,16 +19,48 @@ EXPORT_SYMBOL(cpu_khz); unsigned int tsc_khz; EXPORT_SYMBOL(tsc_khz); -static unsigned int cyc2ns_scale __read_mostly; +/* Accelerators for sched_clock() + * convert from cycles(64bits) => nanoseconds (64bits) + * basic equation: + * ns = cycles / (freq / ns_per_sec) + * ns = cycles * (ns_per_sec / freq) + * ns = cycles * (10^9 / (cpu_khz * 10^3)) + * ns = cycles * (10^6 / cpu_khz) + * + * Then we use scaling math (suggested by george@mvista.com) to get: + * ns = cycles * (10^6 * SC / cpu_khz) / SC + * ns = cycles * cyc2ns_scale / SC + * + * And since SC is a constant power of two, we can convert the div + * into a shift. + * + * We can use khz divisor instead of mhz to keep a better precision, since + * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits. + * (mathieu.desnoyers@polymtl.ca) + * + * -johnstul@us.ibm.com "math is hard, lets go shopping!" + */ +DEFINE_PER_CPU(unsigned long, cyc2ns); -static inline void set_cyc2ns_scale(unsigned long khz) +static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu) { - cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / khz; -} + unsigned long flags, prev_scale, *scale; + unsigned long long tsc_now, ns_now; -static unsigned long long cycles_2_ns(unsigned long long cyc) -{ - return (cyc * cyc2ns_scale) >> NS_SCALE; + local_irq_save(flags); + sched_clock_idle_sleep_event(); + + scale = &per_cpu(cyc2ns, cpu); + + rdtscll(tsc_now); + ns_now = __cycles_2_ns(tsc_now); + + prev_scale = *scale; + if (cpu_khz) + *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz; + + sched_clock_idle_wakeup_event(0); + local_irq_restore(flags); } unsigned long long sched_clock(void) @@ -100,7 +133,9 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, mark_tsc_unstable("cpufreq changes"); } - set_cyc2ns_scale(tsc_khz_ref); + preempt_disable(); + set_cyc2ns_scale(tsc_khz_ref, smp_processor_id()); + preempt_enable(); return 0; } @@ -151,7 +186,7 @@ static unsigned long __init tsc_read_refs(unsigned long *pm, void __init tsc_calibrate(void) { unsigned long flags, tsc1, tsc2, tr1, tr2, pm1, pm2, hpet1, hpet2; - int hpet = is_hpet_enabled(); + int hpet = is_hpet_enabled(), cpu; local_irq_save(flags); @@ -206,7 +241,9 @@ void __init tsc_calibrate(void) } tsc_khz = tsc2 / tsc1; - set_cyc2ns_scale(tsc_khz); + + for_each_possible_cpu(cpu) + set_cyc2ns_scale(tsc_khz, cpu); } /* diff --git a/include/asm-x86/timer.h b/include/asm-x86/timer.h index 0db7e994fb8b..4f6fcb050c11 100644 --- a/include/asm-x86/timer.h +++ b/include/asm-x86/timer.h @@ -2,6 +2,7 @@ #define _ASMi386_TIMER_H #include #include +#include #define TICK_SIZE (tick_nsec / 1000) @@ -16,7 +17,7 @@ extern int recalibrate_cpu_khz(void); #define calculate_cpu_khz() native_calculate_cpu_khz() #endif -/* Accellerators for sched_clock() +/* Accelerators for sched_clock() * convert from cycles(64bits) => nanoseconds (64bits) * basic equation: * ns = cycles / (freq / ns_per_sec) @@ -31,20 +32,32 @@ extern int recalibrate_cpu_khz(void); * And since SC is a constant power of two, we can convert the div * into a shift. * - * We can use khz divisor instead of mhz to keep a better percision, since + * We can use khz divisor instead of mhz to keep a better precision, since * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits. * (mathieu.desnoyers@polymtl.ca) * * -johnstul@us.ibm.com "math is hard, lets go shopping!" */ -extern unsigned long cyc2ns_scale __read_mostly; + +DECLARE_PER_CPU(unsigned long, cyc2ns); #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ -static inline unsigned long long cycles_2_ns(unsigned long long cyc) +static inline unsigned long long __cycles_2_ns(unsigned long long cyc) { - return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; + return cyc * per_cpu(cyc2ns, smp_processor_id()) >> CYC2NS_SCALE_FACTOR; } +static inline unsigned long long cycles_2_ns(unsigned long long cyc) +{ + unsigned long long ns; + unsigned long flags; + + local_irq_save(flags); + ns = __cycles_2_ns(cyc); + local_irq_restore(flags); + + return ns; +} #endif From 5ee613b6751cd91db4b6bd7c1dc9d2f9cf65cde2 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:06 +0100 Subject: [PATCH 028/890] x86: idle wakeup event in the HLT loop do a proper idle-wakeup event on HLT as well - some CPUs stop the TSC in HLT too, not just when going through the ACPI methods. (the ACPI idle code already does this.) [ update the 64-bit side too, as noticed by Jiri Slaby. ] Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/process_32.c | 15 ++++++++++++--- arch/x86/kernel/process_64.c | 13 ++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 46d391d49de8..a63d2d2556ee 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -113,10 +113,19 @@ void default_idle(void) smp_mb(); local_irq_disable(); - if (!need_resched()) + if (!need_resched()) { + ktime_t t0, t1; + u64 t0n, t1n; + + t0 = ktime_get(); + t0n = ktime_to_ns(t0); safe_halt(); /* enables interrupts racelessly */ - else - local_irq_enable(); + local_irq_disable(); + t1 = ktime_get(); + t1n = ktime_to_ns(t1); + sched_clock_idle_wakeup_event(t1n - t0n); + } + local_irq_enable(); current_thread_info()->status |= TS_POLLING; } else { /* loop is done by the caller */ diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index c2db7ef93565..40fed477f3e5 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -116,9 +116,16 @@ static void default_idle(void) smp_mb(); local_irq_disable(); if (!need_resched()) { - /* Enables interrupts one instruction before HLT. - x86 special cases this so there is no race. */ - safe_halt(); + ktime_t t0, t1; + u64 t0n, t1n; + + t0 = ktime_get(); + t0n = ktime_to_ns(t0); + safe_halt(); /* enables interrupts racelessly */ + local_irq_disable(); + t1 = ktime_get(); + t1n = ktime_to_ns(t1); + sched_clock_idle_wakeup_event(t1n - t0n); } else local_irq_enable(); current_thread_info()->status |= TS_POLLING; From 39d44a51474a52bec6d72d30ebc76f5159101d90 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Wed, 30 Jan 2008 13:30:06 +0100 Subject: [PATCH 029/890] x86: enable irq in default_idle on 64-bit local_irq_enable() is missing after sched_clock_idle_wakeup_event(). Signed-off-by: Hiroshi Shimamoto Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/process_64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 40fed477f3e5..2c9e59448f4c 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -126,8 +126,8 @@ static void default_idle(void) t1 = ktime_get(); t1n = ktime_to_ns(t1); sched_clock_idle_wakeup_event(t1n - t0n); - } else - local_irq_enable(); + } + local_irq_enable(); current_thread_info()->status |= TS_POLLING; } From e845c06bced7f5f325e0f9aefd3207cd45c21ff2 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 30 Jan 2008 13:30:06 +0100 Subject: [PATCH 030/890] x86: add Create , with common definitions suitable for assembly unification. Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- include/asm-x86/asm.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 include/asm-x86/asm.h diff --git a/include/asm-x86/asm.h b/include/asm-x86/asm.h new file mode 100644 index 000000000000..b5006eb9acba --- /dev/null +++ b/include/asm-x86/asm.h @@ -0,0 +1,18 @@ +#ifndef _ASM_X86_ASM_H +#define _ASM_X86_ASM_H + +#ifdef CONFIG_X86_32 +/* 32 bits */ + +# define _ASM_PTR " .long " +# define _ASM_ALIGN " .balign 4 " + +#else +/* 64 bits */ + +# define _ASM_PTR " .quad " +# define _ASM_ALIGN " .balign 8 " + +#endif /* CONFIG_X86_32 */ + +#endif /* _ASM_X86_ASM_H */ From 7b11fb51567dedeaf6dc03f0135c0a8bb2399818 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 30 Jan 2008 13:30:07 +0100 Subject: [PATCH 031/890] x86: unify asm/cpufeature.h asm/cpufeature.h was already almost unified; this completes the job. Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- include/asm-x86/cpufeature.h | 191 +++++++++++++++++++++++++++++++- include/asm-x86/cpufeature_32.h | 176 ----------------------------- include/asm-x86/cpufeature_64.h | 30 ----- 3 files changed, 187 insertions(+), 210 deletions(-) delete mode 100644 include/asm-x86/cpufeature_32.h delete mode 100644 include/asm-x86/cpufeature_64.h diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index b7160a4598d7..4c7875554d01 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h @@ -1,5 +1,188 @@ -#ifdef CONFIG_X86_32 -# include "cpufeature_32.h" -#else -# include "cpufeature_64.h" +/* + * Defines x86 CPU feature bits + */ +#ifndef _ASM_X86_CPUFEATURE_H +#define _ASM_X86_CPUFEATURE_H + +#ifndef __ASSEMBLY__ +#include #endif +#include + +#define NCAPINTS 8 /* N 32-bit words worth of info */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ +#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ +#define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */ +#define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */ +#define X86_FEATURE_PSE (0*32+ 3) /* Page Size Extensions */ +#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */ +#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */ +#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ +#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */ +#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */ +#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */ +#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */ +#define X86_FEATURE_MTRR (0*32+12) /* Memory Type Range Registers */ +#define X86_FEATURE_PGE (0*32+13) /* Page Global Enable */ +#define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */ +#define X86_FEATURE_CMOV (0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */ +#define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */ +#define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */ +#define X86_FEATURE_PN (0*32+18) /* Processor serial number */ +#define X86_FEATURE_CLFLSH (0*32+19) /* Supports the CLFLUSH instruction */ +#define X86_FEATURE_DS (0*32+21) /* Debug Store */ +#define X86_FEATURE_ACPI (0*32+22) /* ACPI via MSR */ +#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */ + /* of FPU context), and CR4.OSFXSR available */ +#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */ +#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */ +#define X86_FEATURE_SELFSNOOP (0*32+27) /* CPU self snoop */ +#define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */ +#define X86_FEATURE_ACC (0*32+29) /* Automatic clock control */ +#define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */ + +/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ +/* Don't duplicate feature flags which are redundant with Intel! */ +#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */ +#define X86_FEATURE_MP (1*32+19) /* MP Capable. */ +#define X86_FEATURE_NX (1*32+20) /* Execute Disable */ +#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ +#define X86_FEATURE_RDTSCP (1*32+27) /* RDTSCP */ +#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ +#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ +#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */ + +/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ +#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */ +#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */ +#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */ + +/* Other features, Linux-defined mapping, word 3 */ +/* This range is used for feature bits which conflict or are synthesized */ +#define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */ +#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */ +#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */ +#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */ +/* cpu types for specific tunings: */ +#define X86_FEATURE_K8 (3*32+ 4) /* Opteron, Athlon64 */ +#define X86_FEATURE_K7 (3*32+ 5) /* Athlon */ +#define X86_FEATURE_P3 (3*32+ 6) /* P3 */ +#define X86_FEATURE_P4 (3*32+ 7) /* P4 */ +#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */ +#define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */ +#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */ +#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */ +#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */ +#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */ +/* 14 free */ +#define X86_FEATURE_SYNC_RDTSC (3*32+15) /* RDTSC synchronizes the CPU */ +#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ +#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ +#define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */ +#define X86_FEATURE_DSCPL (4*32+ 4) /* CPL Qualified Debug Store */ +#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */ +#define X86_FEATURE_CID (4*32+10) /* Context ID */ +#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ +#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ +#define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */ + +/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ +#define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ +#define X86_FEATURE_XSTORE_EN (5*32+ 3) /* on-CPU RNG enabled */ +#define X86_FEATURE_XCRYPT (5*32+ 6) /* on-CPU crypto (xcrypt insn) */ +#define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */ +#define X86_FEATURE_ACE2 (5*32+ 8) /* Advanced Cryptography Engine v2 */ +#define X86_FEATURE_ACE2_EN (5*32+ 9) /* ACE v2 enabled */ +#define X86_FEATURE_PHE (5*32+ 10) /* PadLock Hash Engine */ +#define X86_FEATURE_PHE_EN (5*32+ 11) /* PHE enabled */ +#define X86_FEATURE_PMM (5*32+ 12) /* PadLock Montgomery Multiplier */ +#define X86_FEATURE_PMM_EN (5*32+ 13) /* PMM enabled */ + +/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ +#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ +#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */ + +/* + * Auxiliary flags: Linux defined - For features scattered in various + * CPUID levels like 0x6, 0xA etc + */ +#define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */ + +#define cpu_has(c, bit) \ + (__builtin_constant_p(bit) && \ + ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) || \ + (((bit)>>5)==1 && (1UL<<((bit)&31) & REQUIRED_MASK1)) || \ + (((bit)>>5)==2 && (1UL<<((bit)&31) & REQUIRED_MASK2)) || \ + (((bit)>>5)==3 && (1UL<<((bit)&31) & REQUIRED_MASK3)) || \ + (((bit)>>5)==4 && (1UL<<((bit)&31) & REQUIRED_MASK4)) || \ + (((bit)>>5)==5 && (1UL<<((bit)&31) & REQUIRED_MASK5)) || \ + (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) || \ + (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) ) \ + ? 1 : \ + test_bit(bit, (c)->x86_capability)) +#define boot_cpu_has(bit) cpu_has(&boot_cpu_data, bit) + +#define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU) +#define cpu_has_vme boot_cpu_has(X86_FEATURE_VME) +#define cpu_has_de boot_cpu_has(X86_FEATURE_DE) +#define cpu_has_pse boot_cpu_has(X86_FEATURE_PSE) +#define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC) +#define cpu_has_pae boot_cpu_has(X86_FEATURE_PAE) +#define cpu_has_pge boot_cpu_has(X86_FEATURE_PGE) +#define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) +#define cpu_has_sep boot_cpu_has(X86_FEATURE_SEP) +#define cpu_has_mtrr boot_cpu_has(X86_FEATURE_MTRR) +#define cpu_has_mmx boot_cpu_has(X86_FEATURE_MMX) +#define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) +#define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) +#define cpu_has_xmm2 boot_cpu_has(X86_FEATURE_XMM2) +#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3) +#define cpu_has_ht boot_cpu_has(X86_FEATURE_HT) +#define cpu_has_mp boot_cpu_has(X86_FEATURE_MP) +#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX) +#define cpu_has_k6_mtrr boot_cpu_has(X86_FEATURE_K6_MTRR) +#define cpu_has_cyrix_arr boot_cpu_has(X86_FEATURE_CYRIX_ARR) +#define cpu_has_centaur_mcr boot_cpu_has(X86_FEATURE_CENTAUR_MCR) +#define cpu_has_xstore boot_cpu_has(X86_FEATURE_XSTORE) +#define cpu_has_xstore_enabled boot_cpu_has(X86_FEATURE_XSTORE_EN) +#define cpu_has_xcrypt boot_cpu_has(X86_FEATURE_XCRYPT) +#define cpu_has_xcrypt_enabled boot_cpu_has(X86_FEATURE_XCRYPT_EN) +#define cpu_has_ace2 boot_cpu_has(X86_FEATURE_ACE2) +#define cpu_has_ace2_enabled boot_cpu_has(X86_FEATURE_ACE2_EN) +#define cpu_has_phe boot_cpu_has(X86_FEATURE_PHE) +#define cpu_has_phe_enabled boot_cpu_has(X86_FEATURE_PHE_EN) +#define cpu_has_pmm boot_cpu_has(X86_FEATURE_PMM) +#define cpu_has_pmm_enabled boot_cpu_has(X86_FEATURE_PMM_EN) +#define cpu_has_ds boot_cpu_has(X86_FEATURE_DS) +#define cpu_has_pebs boot_cpu_has(X86_FEATURE_PEBS) +#define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLSH) +#define cpu_has_bts boot_cpu_has(X86_FEATURE_BTS) + +#ifdef CONFIG_X86_64 + +#undef cpu_has_vme +#define cpu_has_vme 0 + +#undef cpu_has_pae +#define cpu_has_pae ___BUG___ + +#undef cpu_has_mp +#define cpu_has_mp 1 + +#undef cpu_has_k6_mtrr +#define cpu_has_k6_mtrr 0 + +#undef cpu_has_cyrix_arr +#define cpu_has_cyrix_arr 0 + +#undef cpu_has_centaur_mcr +#define cpu_has_centaur_mcr 0 + +#endif /* CONFIG_X86_64 */ + +#endif /* _ASM_X86_CPUFEATURE_H */ diff --git a/include/asm-x86/cpufeature_32.h b/include/asm-x86/cpufeature_32.h deleted file mode 100644 index f17e688dfb05..000000000000 --- a/include/asm-x86/cpufeature_32.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * cpufeature.h - * - * Defines x86 CPU feature bits - */ - -#ifndef __ASM_I386_CPUFEATURE_H -#define __ASM_I386_CPUFEATURE_H - -#ifndef __ASSEMBLY__ -#include -#endif -#include - -#define NCAPINTS 8 /* N 32-bit words worth of info */ - -/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ -#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ -#define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */ -#define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */ -#define X86_FEATURE_PSE (0*32+ 3) /* Page Size Extensions */ -#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */ -#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */ -#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ -#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */ -#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */ -#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */ -#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */ -#define X86_FEATURE_MTRR (0*32+12) /* Memory Type Range Registers */ -#define X86_FEATURE_PGE (0*32+13) /* Page Global Enable */ -#define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */ -#define X86_FEATURE_CMOV (0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */ -#define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */ -#define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */ -#define X86_FEATURE_PN (0*32+18) /* Processor serial number */ -#define X86_FEATURE_CLFLSH (0*32+19) /* Supports the CLFLUSH instruction */ -#define X86_FEATURE_DS (0*32+21) /* Debug Store */ -#define X86_FEATURE_ACPI (0*32+22) /* ACPI via MSR */ -#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ -#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */ - /* of FPU context), and CR4.OSFXSR available */ -#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */ -#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */ -#define X86_FEATURE_SELFSNOOP (0*32+27) /* CPU self snoop */ -#define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */ -#define X86_FEATURE_ACC (0*32+29) /* Automatic clock control */ -#define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */ - -/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ -/* Don't duplicate feature flags which are redundant with Intel! */ -#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */ -#define X86_FEATURE_MP (1*32+19) /* MP Capable. */ -#define X86_FEATURE_NX (1*32+20) /* Execute Disable */ -#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ -#define X86_FEATURE_RDTSCP (1*32+27) /* RDTSCP */ -#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ -#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ -#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */ - -/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ -#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */ -#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */ -#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */ - -/* Other features, Linux-defined mapping, word 3 */ -/* This range is used for feature bits which conflict or are synthesized */ -#define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */ -#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */ -#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */ -#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */ -/* cpu types for specific tunings: */ -#define X86_FEATURE_K8 (3*32+ 4) /* Opteron, Athlon64 */ -#define X86_FEATURE_K7 (3*32+ 5) /* Athlon */ -#define X86_FEATURE_P3 (3*32+ 6) /* P3 */ -#define X86_FEATURE_P4 (3*32+ 7) /* P4 */ -#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */ -#define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */ -#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */ -#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */ -#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */ -#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */ -/* 14 free */ -#define X86_FEATURE_SYNC_RDTSC (3*32+15) /* RDTSC synchronizes the CPU */ -#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */ - -/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ -#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ -#define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */ -#define X86_FEATURE_DSCPL (4*32+ 4) /* CPL Qualified Debug Store */ -#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ -#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */ -#define X86_FEATURE_CID (4*32+10) /* Context ID */ -#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ -#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ -#define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */ - -/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ -#define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ -#define X86_FEATURE_XSTORE_EN (5*32+ 3) /* on-CPU RNG enabled */ -#define X86_FEATURE_XCRYPT (5*32+ 6) /* on-CPU crypto (xcrypt insn) */ -#define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */ -#define X86_FEATURE_ACE2 (5*32+ 8) /* Advanced Cryptography Engine v2 */ -#define X86_FEATURE_ACE2_EN (5*32+ 9) /* ACE v2 enabled */ -#define X86_FEATURE_PHE (5*32+ 10) /* PadLock Hash Engine */ -#define X86_FEATURE_PHE_EN (5*32+ 11) /* PHE enabled */ -#define X86_FEATURE_PMM (5*32+ 12) /* PadLock Montgomery Multiplier */ -#define X86_FEATURE_PMM_EN (5*32+ 13) /* PMM enabled */ - -/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ -#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ -#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */ - -/* - * Auxiliary flags: Linux defined - For features scattered in various - * CPUID levels like 0x6, 0xA etc - */ -#define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */ - -#define cpu_has(c, bit) \ - (__builtin_constant_p(bit) && \ - ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) || \ - (((bit)>>5)==1 && (1UL<<((bit)&31) & REQUIRED_MASK1)) || \ - (((bit)>>5)==2 && (1UL<<((bit)&31) & REQUIRED_MASK2)) || \ - (((bit)>>5)==3 && (1UL<<((bit)&31) & REQUIRED_MASK3)) || \ - (((bit)>>5)==4 && (1UL<<((bit)&31) & REQUIRED_MASK4)) || \ - (((bit)>>5)==5 && (1UL<<((bit)&31) & REQUIRED_MASK5)) || \ - (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) || \ - (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) ) \ - ? 1 : \ - test_bit(bit, (c)->x86_capability)) -#define boot_cpu_has(bit) cpu_has(&boot_cpu_data, bit) - -#define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU) -#define cpu_has_vme boot_cpu_has(X86_FEATURE_VME) -#define cpu_has_de boot_cpu_has(X86_FEATURE_DE) -#define cpu_has_pse boot_cpu_has(X86_FEATURE_PSE) -#define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC) -#define cpu_has_pae boot_cpu_has(X86_FEATURE_PAE) -#define cpu_has_pge boot_cpu_has(X86_FEATURE_PGE) -#define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) -#define cpu_has_sep boot_cpu_has(X86_FEATURE_SEP) -#define cpu_has_mtrr boot_cpu_has(X86_FEATURE_MTRR) -#define cpu_has_mmx boot_cpu_has(X86_FEATURE_MMX) -#define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) -#define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) -#define cpu_has_xmm2 boot_cpu_has(X86_FEATURE_XMM2) -#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3) -#define cpu_has_ht boot_cpu_has(X86_FEATURE_HT) -#define cpu_has_mp boot_cpu_has(X86_FEATURE_MP) -#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX) -#define cpu_has_k6_mtrr boot_cpu_has(X86_FEATURE_K6_MTRR) -#define cpu_has_cyrix_arr boot_cpu_has(X86_FEATURE_CYRIX_ARR) -#define cpu_has_centaur_mcr boot_cpu_has(X86_FEATURE_CENTAUR_MCR) -#define cpu_has_xstore boot_cpu_has(X86_FEATURE_XSTORE) -#define cpu_has_xstore_enabled boot_cpu_has(X86_FEATURE_XSTORE_EN) -#define cpu_has_xcrypt boot_cpu_has(X86_FEATURE_XCRYPT) -#define cpu_has_xcrypt_enabled boot_cpu_has(X86_FEATURE_XCRYPT_EN) -#define cpu_has_ace2 boot_cpu_has(X86_FEATURE_ACE2) -#define cpu_has_ace2_enabled boot_cpu_has(X86_FEATURE_ACE2_EN) -#define cpu_has_phe boot_cpu_has(X86_FEATURE_PHE) -#define cpu_has_phe_enabled boot_cpu_has(X86_FEATURE_PHE_EN) -#define cpu_has_pmm boot_cpu_has(X86_FEATURE_PMM) -#define cpu_has_pmm_enabled boot_cpu_has(X86_FEATURE_PMM_EN) -#define cpu_has_ds boot_cpu_has(X86_FEATURE_DS) -#define cpu_has_pebs boot_cpu_has(X86_FEATURE_PEBS) -#define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLSH) -#define cpu_has_bts boot_cpu_has(X86_FEATURE_BTS) - -#endif /* __ASM_I386_CPUFEATURE_H */ - -/* - * Local Variables: - * mode:c - * comment-column:42 - * End: - */ diff --git a/include/asm-x86/cpufeature_64.h b/include/asm-x86/cpufeature_64.h deleted file mode 100644 index e18496b7b850..000000000000 --- a/include/asm-x86/cpufeature_64.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * cpufeature_32.h - * - * Defines x86 CPU feature bits - */ - -#ifndef __ASM_X8664_CPUFEATURE_H -#define __ASM_X8664_CPUFEATURE_H - -#include "cpufeature_32.h" - -#undef cpu_has_vme -#define cpu_has_vme 0 - -#undef cpu_has_pae -#define cpu_has_pae ___BUG___ - -#undef cpu_has_mp -#define cpu_has_mp 1 /* XXX */ - -#undef cpu_has_k6_mtrr -#define cpu_has_k6_mtrr 0 - -#undef cpu_has_cyrix_arr -#define cpu_has_cyrix_arr 0 - -#undef cpu_has_centaur_mcr -#define cpu_has_centaur_mcr 0 - -#endif /* __ASM_X8664_CPUFEATURE_H */ From d94448b1fdc91ee1d235607f6bbe595464e4fbb9 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:07 +0100 Subject: [PATCH 032/890] x86: clean up arch/x86/ia32/fpu32.c White space and coding style clenaup. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/ia32/fpu32.c | 134 +++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/arch/x86/ia32/fpu32.c b/arch/x86/ia32/fpu32.c index 2c8209a3605a..459bf743128f 100644 --- a/arch/x86/ia32/fpu32.c +++ b/arch/x86/ia32/fpu32.c @@ -1,8 +1,8 @@ -/* +/* * Copyright 2002 Andi Kleen, SuSE Labs. * FXSAVE<->i387 conversion support. Based on code by Gareth Hughes. * This is used for ptrace, signals and coredumps in 32bit emulation. - */ + */ #include #include @@ -13,96 +13,97 @@ static inline unsigned short twd_i387_to_fxsr(unsigned short twd) { unsigned int tmp; /* to avoid 16 bit prefixes in the code */ - + /* Transform each pair of bits into 01 (valid) or 00 (empty) */ - tmp = ~twd; - tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ - /* and move the valid bits to the lower byte. */ - tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ - tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ - tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ - return tmp; + tmp = ~twd; + tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ + /* and move the valid bits to the lower byte. */ + tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ + tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ + tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ + return tmp; } +#define FPREG_ADDR(f, n) ((void *)&(f)->st_space + (n) * 16); +#define FP_EXP_TAG_VALID 0 +#define FP_EXP_TAG_ZERO 1 +#define FP_EXP_TAG_SPECIAL 2 +#define FP_EXP_TAG_EMPTY 3 + static inline unsigned long twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave) { - struct _fpxreg *st = NULL; + struct _fpxreg *st; unsigned long tos = (fxsave->swd >> 11) & 7; unsigned long twd = (unsigned long) fxsave->twd; unsigned long tag; unsigned long ret = 0xffff0000; int i; -#define FPREG_ADDR(f, n) ((void *)&(f)->st_space + (n) * 16); - - for (i = 0 ; i < 8 ; i++) { + for (i = 0; i < 8; i++, twd >>= 1) { if (twd & 0x1) { - st = FPREG_ADDR( fxsave, (i - tos) & 7 ); + st = FPREG_ADDR(fxsave, (i - tos) & 7); switch (st->exponent & 0x7fff) { case 0x7fff: - tag = 2; /* Special */ + tag = FP_EXP_TAG_SPECIAL; break; case 0x0000: - if ( !st->significand[0] && - !st->significand[1] && - !st->significand[2] && - !st->significand[3] ) { - tag = 1; /* Zero */ - } else { - tag = 2; /* Special */ - } + if (!st->significand[0] && + !st->significand[1] && + !st->significand[2] && + !st->significand[3]) + tag = FP_EXP_TAG_ZERO; + else + tag = FP_EXP_TAG_SPECIAL; break; default: - if (st->significand[3] & 0x8000) { - tag = 0; /* Valid */ - } else { - tag = 2; /* Special */ - } + if (st->significand[3] & 0x8000) + tag = FP_EXP_TAG_VALID; + else + tag = FP_EXP_TAG_SPECIAL; break; } } else { - tag = 3; /* Empty */ + tag = FP_EXP_TAG_EMPTY; } - ret |= (tag << (2 * i)); - twd = twd >> 1; + ret |= tag << (2 * i); } return ret; } +#define G(num, val) err |= __get_user(val, num + (u32 __user *)buf) static inline int convert_fxsr_from_user(struct i387_fxsave_struct *fxsave, struct _fpstate_ia32 __user *buf) { struct _fpxreg *to; struct _fpreg __user *from; - int i; + int i, err = 0; u32 v; - int err = 0; -#define G(num,val) err |= __get_user(val, num + (u32 __user *)buf) G(0, fxsave->cwd); G(1, fxsave->swd); G(2, fxsave->twd); fxsave->twd = twd_i387_to_fxsr(fxsave->twd); G(3, fxsave->rip); G(4, v); - fxsave->fop = v>>16; /* cs ignored */ + /* cs ignored */ + fxsave->fop = v>>16; G(5, fxsave->rdp); /* 6: ds ignored */ -#undef G - if (err) - return -1; + if (err) + return -1; to = (struct _fpxreg *)&fxsave->st_space[0]; from = &buf->_st[0]; - for (i = 0 ; i < 8 ; i++, to++, from++) { + for (i = 0; i < 8; i++, to++, from++) { if (__copy_from_user(to, from, sizeof(*from))) return -1; } return 0; } +#define P(num, val) err |= __put_user(val, num + (u32 __user *)buf) static inline int convert_fxsr_to_user(struct _fpstate_ia32 __user *buf, struct i387_fxsave_struct *fxsave, @@ -111,60 +112,59 @@ static inline int convert_fxsr_to_user(struct _fpstate_ia32 __user *buf, { struct _fpreg __user *to; struct _fpxreg *from; - int i; - u16 cs,ds; - int err = 0; + int i, err = 0; + u16 cs, ds; if (tsk == current) { - /* should be actually ds/cs at fpu exception time, - but that information is not available in 64bit mode. */ - asm("movw %%ds,%0 " : "=r" (ds)); - asm("movw %%cs,%0 " : "=r" (cs)); - } else { /* ptrace. task has stopped. */ + /* + * should be actually ds/cs at fpu exception time, but + * that information is not available in 64bit mode. + */ + asm("movw %%ds,%0 " : "=r" (ds)); + asm("movw %%cs,%0 " : "=r" (cs)); + } else { + /* ptrace. task has stopped. */ ds = tsk->thread.ds; cs = regs->cs; - } + } -#define P(num,val) err |= __put_user(val, num + (u32 __user *)buf) P(0, (u32)fxsave->cwd | 0xffff0000); P(1, (u32)fxsave->swd | 0xffff0000); P(2, twd_fxsr_to_i387(fxsave)); P(3, (u32)fxsave->rip); - P(4, cs | ((u32)fxsave->fop) << 16); + P(4, cs | ((u32)fxsave->fop) << 16); P(5, fxsave->rdp); P(6, 0xffff0000 | ds); -#undef P - if (err) - return -1; + if (err) + return -1; to = &buf->_st[0]; from = (struct _fpxreg *) &fxsave->st_space[0]; - for ( i = 0 ; i < 8 ; i++, to++, from++ ) { + for (i = 0; i < 8; i++, to++, from++) { if (__copy_to_user(to, from, sizeof(*to))) return -1; } return 0; } -int restore_i387_ia32(struct task_struct *tsk, struct _fpstate_ia32 __user *buf, int fsave) -{ +int restore_i387_ia32(struct task_struct *tsk, + struct _fpstate_ia32 __user *buf, int fsave) +{ clear_fpu(tsk); - if (!fsave) { - if (__copy_from_user(&tsk->thread.i387.fxsave, + if (!fsave) { + if (__copy_from_user(&tsk->thread.i387.fxsave, &buf->_fxsr_env[0], sizeof(struct i387_fxsave_struct))) return -1; tsk->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask; set_stopped_child_used_math(tsk); - } + } return convert_fxsr_from_user(&tsk->thread.i387.fxsave, buf); -} +} -int save_i387_ia32(struct task_struct *tsk, - struct _fpstate_ia32 __user *buf, - struct pt_regs *regs, - int fsave) +int save_i387_ia32(struct task_struct *tsk, struct _fpstate_ia32 __user *buf, + struct pt_regs *regs, int fsave) { int err = 0; @@ -174,8 +174,8 @@ int save_i387_ia32(struct task_struct *tsk, if (fsave) return 0; err |= __put_user(tsk->thread.i387.fxsave.swd, &buf->status); - if (fsave) - return err ? -1 : 1; + if (fsave) + return err ? -1 : 1; err |= __put_user(X86_FXSR_MAGIC, &buf->magic); err |= __copy_to_user(&buf->_fxsr_env[0], &tsk->thread.i387.fxsave, sizeof(struct i387_fxsave_struct)); From 8edf8bee889a3d13ae2db0f7992821fb5dc78bfa Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:07 +0100 Subject: [PATCH 033/890] x86: clean up arch/x86/ia32/aout32.c White space and coding style clenaup. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_aout.c | 210 +++++++++++++++++++++----------------- 1 file changed, 114 insertions(+), 96 deletions(-) diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index f82e1a94fcb7..a764e4e95314 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -36,38 +36,44 @@ #undef WARN_OLD #undef CORE_DUMP /* probably broken */ -static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); -static int load_aout_library(struct file*); +static int load_aout_binary(struct linux_binprm *, struct pt_regs *regs); +static int load_aout_library(struct file *); #ifdef CORE_DUMP -static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit); +static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, + unsigned long limit); /* * fill in the user structure for a core dump.. */ -static void dump_thread32(struct pt_regs * regs, struct user32 * dump) +static void dump_thread32(struct pt_regs *regs, struct user32 *dump) { - u32 fs,gs; + u32 fs, gs; /* changed the size calculations - should hopefully work better. lbt */ dump->magic = CMAGIC; dump->start_code = 0; dump->start_stack = regs->rsp & ~(PAGE_SIZE - 1); dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; - dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; + dump->u_dsize = ((unsigned long) + (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; dump->u_dsize -= dump->u_tsize; dump->u_ssize = 0; - dump->u_debugreg[0] = current->thread.debugreg0; - dump->u_debugreg[1] = current->thread.debugreg1; - dump->u_debugreg[2] = current->thread.debugreg2; - dump->u_debugreg[3] = current->thread.debugreg3; - dump->u_debugreg[4] = 0; - dump->u_debugreg[5] = 0; - dump->u_debugreg[6] = current->thread.debugreg6; - dump->u_debugreg[7] = current->thread.debugreg7; + dump->u_debugreg[0] = current->thread.debugreg0; + dump->u_debugreg[1] = current->thread.debugreg1; + dump->u_debugreg[2] = current->thread.debugreg2; + dump->u_debugreg[3] = current->thread.debugreg3; + dump->u_debugreg[4] = 0; + dump->u_debugreg[5] = 0; + dump->u_debugreg[6] = current->thread.debugreg6; + dump->u_debugreg[7] = current->thread.debugreg7; - if (dump->start_stack < 0xc0000000) - dump->u_ssize = ((unsigned long) (0xc0000000 - dump->start_stack)) >> PAGE_SHIFT; + if (dump->start_stack < 0xc0000000) { + unsigned long tmp; + + tmp = (unsigned long) (0xc0000000 - dump->start_stack); + dump->u_ssize = tmp >> PAGE_SHIFT; + } dump->regs.ebx = regs->rbx; dump->regs.ecx = regs->rcx; @@ -79,7 +85,7 @@ static void dump_thread32(struct pt_regs * regs, struct user32 * dump) dump->regs.ds = current->thread.ds; dump->regs.es = current->thread.es; asm("movl %%fs,%0" : "=r" (fs)); dump->regs.fs = fs; - asm("movl %%gs,%0" : "=r" (gs)); dump->regs.gs = gs; + asm("movl %%gs,%0" : "=r" (gs)); dump->regs.gs = gs; dump->regs.orig_eax = regs->orig_rax; dump->regs.eip = regs->rip; dump->regs.cs = regs->cs; @@ -90,7 +96,7 @@ static void dump_thread32(struct pt_regs * regs, struct user32 * dump) #if 1 /* FIXME */ dump->u_fpvalid = 0; #else - dump->u_fpvalid = dump_fpu (regs, &dump->i387); + dump->u_fpvalid = dump_fpu(regs, &dump->i387); #endif } @@ -128,15 +134,19 @@ static int dump_write(struct file *file, const void *addr, int nr) return file->f_op->write(file, addr, nr, &file->f_pos) == nr; } -#define DUMP_WRITE(addr, nr) \ +#define DUMP_WRITE(addr, nr) \ if (!dump_write(file, (void *)(addr), (nr))) \ goto end_coredump; -#define DUMP_SEEK(offset) \ -if (file->f_op->llseek) { \ - if (file->f_op->llseek(file,(offset),0) != (offset)) \ - goto end_coredump; \ -} else file->f_pos = (offset) +#define DUMP_SEEK(offset) \ + if (file->f_op->llseek) { \ + if (file->f_op->llseek(file, (offset), 0) != (offset)) \ + goto end_coredump; \ + } else \ + file->f_pos = (offset) + +#define START_DATA() (u.u_tsize << PAGE_SHIFT) +#define START_STACK(u) (u.start_stack) /* * Routine writes a core dump image in the current directory. @@ -148,62 +158,70 @@ if (file->f_op->llseek) { \ * dumping of the process results in another error.. */ -static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit) +static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, + unsigned long limit) { mm_segment_t fs; int has_dumped = 0; unsigned long dump_start, dump_size; struct user32 dump; -# define START_DATA(u) (u.u_tsize << PAGE_SHIFT) -# define START_STACK(u) (u.start_stack) fs = get_fs(); set_fs(KERNEL_DS); has_dumped = 1; current->flags |= PF_DUMPCORE; - strncpy(dump.u_comm, current->comm, sizeof(current->comm)); - dump.u_ar0 = (u32)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump))); + strncpy(dump.u_comm, current->comm, sizeof(current->comm)); + dump.u_ar0 = (u32)(((unsigned long)(&dump.regs)) - + ((unsigned long)(&dump))); dump.signal = signr; dump_thread32(regs, &dump); -/* If the size of the dump file exceeds the rlimit, then see what would happen - if we wrote the stack, but not the data area. */ + /* + * If the size of the dump file exceeds the rlimit, then see + * what would happen if we wrote the stack, but not the data + * area. + */ if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > limit) dump.u_dsize = 0; -/* Make sure we have enough room to write the stack and data areas. */ + /* Make sure we have enough room to write the stack and data areas. */ if ((dump.u_ssize + 1) * PAGE_SIZE > limit) dump.u_ssize = 0; -/* make sure we actually have a data and stack area to dump */ + /* make sure we actually have a data and stack area to dump */ set_fs(USER_DS); - if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_DATA(dump), dump.u_dsize << PAGE_SHIFT)) + if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_DATA(dump), + dump.u_dsize << PAGE_SHIFT)) dump.u_dsize = 0; - if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_STACK(dump), dump.u_ssize << PAGE_SHIFT)) + if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_STACK(dump), + dump.u_ssize << PAGE_SHIFT)) dump.u_ssize = 0; set_fs(KERNEL_DS); -/* struct user */ - DUMP_WRITE(&dump,sizeof(dump)); -/* Now dump all of the user data. Include malloced stuff as well */ + /* struct user */ + DUMP_WRITE(&dump, sizeof(dump)); + /* Now dump all of the user data. Include malloced stuff as well */ DUMP_SEEK(PAGE_SIZE); -/* now we start writing out the user space info */ + /* now we start writing out the user space info */ set_fs(USER_DS); -/* Dump the data area */ + /* Dump the data area */ if (dump.u_dsize != 0) { dump_start = START_DATA(dump); dump_size = dump.u_dsize << PAGE_SHIFT; - DUMP_WRITE(dump_start,dump_size); + DUMP_WRITE(dump_start, dump_size); } -/* Now prepare to dump the stack area */ + /* Now prepare to dump the stack area */ if (dump.u_ssize != 0) { dump_start = START_STACK(dump); dump_size = dump.u_ssize << PAGE_SHIFT; - DUMP_WRITE(dump_start,dump_size); + DUMP_WRITE(dump_start, dump_size); } -/* Finally dump the task struct. Not be used by gdb, but could be useful */ + /* + * Finally dump the task struct. Not be used by gdb, but + * could be useful + */ set_fs(KERNEL_DS); - DUMP_WRITE(current,sizeof(*current)); + DUMP_WRITE(current, sizeof(*current)); end_coredump: set_fs(fs); return has_dumped; @@ -217,35 +235,34 @@ end_coredump: */ static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm) { - u32 __user *argv; - u32 __user *envp; - u32 __user *sp; - int argc = bprm->argc; - int envc = bprm->envc; + u32 __user *argv, *envp, *sp; + int argc = bprm->argc, envc = bprm->envc; sp = (u32 __user *) ((-(unsigned long)sizeof(u32)) & (unsigned long) p); sp -= envc+1; envp = sp; sp -= argc+1; argv = sp; - put_user((unsigned long) envp,--sp); - put_user((unsigned long) argv,--sp); - put_user(argc,--sp); + put_user((unsigned long) envp, --sp); + put_user((unsigned long) argv, --sp); + put_user(argc, --sp); current->mm->arg_start = (unsigned long) p; - while (argc-->0) { + while (argc-- > 0) { char c; - put_user((u32)(unsigned long)p,argv++); + + put_user((u32)(unsigned long)p, argv++); do { - get_user(c,p++); + get_user(c, p++); } while (c); } put_user(0, argv); current->mm->arg_end = current->mm->env_start = (unsigned long) p; - while (envc-->0) { + while (envc-- > 0) { char c; - put_user((u32)(unsigned long)p,envp++); + + put_user((u32)(unsigned long)p, envp++); do { - get_user(c,p++); + get_user(c, p++); } while (c); } put_user(0, envp); @@ -257,20 +274,18 @@ static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm) * These are the functions used to load a.out style executables and shared * libraries. There is no binary dependent code anywhere else. */ - -static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) +static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) { + unsigned long error, fd_offset, rlim; struct exec ex; - unsigned long error; - unsigned long fd_offset; - unsigned long rlim; int retval; ex = *((struct exec *) bprm->buf); /* exec-header */ if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || - i_size_read(bprm->file->f_path.dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { + i_size_read(bprm->file->f_path.dentry->d_inode) < + ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { return -ENOEXEC; } @@ -291,13 +306,13 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (retval) return retval; - regs->cs = __USER32_CS; + regs->cs = __USER32_CS; regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0; /* OK, This is the point of no return */ set_personality(PER_LINUX); - set_thread_flag(TIF_IA32); + set_thread_flag(TIF_IA32); clear_thread_flag(TIF_ABI_PENDING); current->mm->end_code = ex.a_text + @@ -311,7 +326,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) current->mm->mmap = NULL; compute_creds(bprm); - current->flags &= ~PF_FORKNOEXEC; + current->flags &= ~PF_FORKNOEXEC; if (N_MAGIC(ex) == OMAGIC) { unsigned long text_addr, map_size; @@ -338,30 +353,30 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) send_sig(SIGKILL, current, 0); return error; } - + flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data); } else { #ifdef WARN_OLD static unsigned long error_time, error_time2; if ((ex.a_text & 0xfff || ex.a_data & 0xfff) && - (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time2) > 5*HZ) - { + (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time2) > 5*HZ) { printk(KERN_NOTICE "executable not page aligned\n"); error_time2 = jiffies; } if ((fd_offset & ~PAGE_MASK) != 0 && - (jiffies-error_time) > 5*HZ) - { - printk(KERN_WARNING - "fd_offset is not page aligned. Please convert program: %s\n", + (jiffies - error_time) > 5*HZ) { + printk(KERN_WARNING + "fd_offset is not page aligned. Please convert " + "program: %s\n", bprm->file->f_path.dentry->d_name.name); error_time = jiffies; } #endif - if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) { + if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) { loff_t pos = fd_offset; + down_write(¤t->mm->mmap_sem); do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); up_write(¤t->mm->mmap_sem); @@ -376,9 +391,10 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, - PROT_READ | PROT_EXEC, - MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | MAP_32BIT, - fd_offset); + PROT_READ | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | + MAP_EXECUTABLE | MAP_32BIT, + fd_offset); up_write(¤t->mm->mmap_sem); if (error != N_TXTADDR(ex)) { @@ -387,9 +403,10 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) } down_write(¤t->mm->mmap_sem); - error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, + error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE | MAP_32BIT, + MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | + MAP_EXECUTABLE | MAP_32BIT, fd_offset + ex.a_text); up_write(¤t->mm->mmap_sem); if (error != N_DATADDR(ex)) { @@ -403,9 +420,9 @@ beyond_if: set_brk(current->mm->start_brk, current->mm->brk); retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); - if (retval < 0) { - /* Someone check-me: is this error path enough? */ - send_sig(SIGKILL, current, 0); + if (retval < 0) { + /* Someone check-me: is this error path enough? */ + send_sig(SIGKILL, current, 0); return retval; } @@ -414,7 +431,7 @@ beyond_if: /* start thread */ asm volatile("movl %0,%%fs" :: "r" (0)); \ asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); - load_gs_index(0); + load_gs_index(0); (regs)->rip = ex.a_entry; (regs)->rsp = current->mm->start_stack; (regs)->eflags = 0x200; @@ -425,7 +442,7 @@ beyond_if: set_fs(USER_DS); if (unlikely(current->ptrace & PT_PTRACED)) { if (current->ptrace & PT_TRACE_EXEC) - ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP); + ptrace_notify((PTRACE_EVENT_EXEC << 8) | SIGTRAP); else send_sig(SIGTRAP, current, 0); } @@ -434,9 +451,8 @@ beyond_if: static int load_aout_library(struct file *file) { - struct inode * inode; - unsigned long bss, start_addr, len; - unsigned long error; + struct inode *inode; + unsigned long bss, start_addr, len, error; int retval; struct exec ex; @@ -450,7 +466,8 @@ static int load_aout_library(struct file *file) /* We come in here for the regular a.out style of shared libraries */ if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) || - i_size_read(inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { + i_size_read(inode) < + ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { goto out; } @@ -467,10 +484,10 @@ static int load_aout_library(struct file *file) #ifdef WARN_OLD static unsigned long error_time; - if ((jiffies-error_time) > 5*HZ) - { - printk(KERN_WARNING - "N_TXTOFF is not page aligned. Please convert library: %s\n", + if ((jiffies-error_time) > 5*HZ) { + printk(KERN_WARNING + "N_TXTOFF is not page aligned. Please convert " + "library: %s\n", file->f_path.dentry->d_name.name); error_time = jiffies; } @@ -478,11 +495,12 @@ static int load_aout_library(struct file *file) down_write(¤t->mm->mmap_sem); do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); up_write(¤t->mm->mmap_sem); - + file->f_op->read(file, (char __user *)start_addr, ex.a_text + ex.a_data, &pos); flush_icache_range((unsigned long) start_addr, - (unsigned long) start_addr + ex.a_text + ex.a_data); + (unsigned long) start_addr + ex.a_text + + ex.a_data); retval = 0; goto out; From 99b9cdf758af7004a716cf304dd5cd41af7db227 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:07 +0100 Subject: [PATCH 034/890] x86: clean up arch/x86/ia32/ia32_signal.c White space and coding style clenaup. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32_signal.c | 367 ++++++++++++++++++------------------ 1 file changed, 181 insertions(+), 186 deletions(-) diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 6ea19c25f90d..0fc5d8563e19 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -43,7 +43,8 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where); int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) { int err; - if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t))) + + if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) return -EFAULT; /* If you change siginfo_t structure, please make sure that @@ -53,16 +54,19 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) 3 ints plus the relevant union member. */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); + err |= __put_user((short)from->si_code, &to->si_code); if (from->si_code < 0) { err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr); + err |= __put_user(from->si_uid, &to->si_uid); + err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr); } else { - /* First 32bits of unions are always present: - * si_pid === si_band === si_tid === si_addr(LS half) */ - err |= __put_user(from->_sifields._pad[0], &to->_sifields._pad[0]); + /* + * First 32bits of unions are always present: + * si_pid === si_band === si_tid === si_addr(LS half) + */ + err |= __put_user(from->_sifields._pad[0], + &to->_sifields._pad[0]); switch (from->si_code >> 16) { case __SI_FAULT >> 16: break; @@ -76,14 +80,15 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) err |= __put_user(from->si_uid, &to->si_uid); break; case __SI_POLL >> 16: - err |= __put_user(from->si_fd, &to->si_fd); + err |= __put_user(from->si_fd, &to->si_fd); break; case __SI_TIMER >> 16: - err |= __put_user(from->si_overrun, &to->si_overrun); + err |= __put_user(from->si_overrun, &to->si_overrun); err |= __put_user(ptr_to_compat(from->si_ptr), - &to->si_ptr); + &to->si_ptr); break; - case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ + /* This is not generated by the kernel as of now. */ + case __SI_RT >> 16: case __SI_MESGQ >> 16: err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_int, &to->si_int); @@ -97,7 +102,8 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) { int err; u32 ptr32; - if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t))) + + if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t))) return -EFAULT; err = __get_user(to->si_signo, &from->si_signo); @@ -112,8 +118,7 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) return err; } -asmlinkage long -sys32_sigsuspend(int history0, int history1, old_sigset_t mask) +asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask) { mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); @@ -128,36 +133,37 @@ sys32_sigsuspend(int history0, int history1, old_sigset_t mask) return -ERESTARTNOHAND; } -asmlinkage long -sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, - stack_ia32_t __user *uoss_ptr, - struct pt_regs *regs) +asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, + stack_ia32_t __user *uoss_ptr, + struct pt_regs *regs) { - stack_t uss,uoss; + stack_t uss, uoss; int ret; - mm_segment_t seg; - if (uss_ptr) { + mm_segment_t seg; + + if (uss_ptr) { u32 ptr; - memset(&uss,0,sizeof(stack_t)); - if (!access_ok(VERIFY_READ,uss_ptr,sizeof(stack_ia32_t)) || + + memset(&uss, 0, sizeof(stack_t)); + if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)) || __get_user(ptr, &uss_ptr->ss_sp) || __get_user(uss.ss_flags, &uss_ptr->ss_flags) || __get_user(uss.ss_size, &uss_ptr->ss_size)) return -EFAULT; uss.ss_sp = compat_ptr(ptr); } - seg = get_fs(); - set_fs(KERNEL_DS); + seg = get_fs(); + set_fs(KERNEL_DS); ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->rsp); - set_fs(seg); + set_fs(seg); if (ret >= 0 && uoss_ptr) { - if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) || + if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) || __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) || __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || __put_user(uoss.ss_size, &uoss_ptr->ss_size)) ret = -EFAULT; - } - return ret; + } + return ret; } /* @@ -186,18 +192,6 @@ struct rt_sigframe char retcode[8]; }; -static int -ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc, unsigned int *peax) -{ - unsigned int err = 0; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - -#if DEBUG_SIG - printk("SIG restore_sigcontext: sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n", - sc, sc->err, sc->eip, sc->cs, sc->eflags); -#endif #define COPY(x) { \ unsigned int reg; \ err |= __get_user(reg, &sc->e ##x); \ @@ -205,68 +199,78 @@ ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc, } #define RELOAD_SEG(seg,mask) \ - { unsigned int cur; \ + { unsigned int cur; \ unsigned short pre; \ err |= __get_user(pre, &sc->seg); \ - asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \ - pre |= mask; \ - if (pre != cur) loadsegment(seg,pre); } + asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \ + pre |= mask; \ + if (pre != cur) loadsegment(seg, pre); } - /* Reload fs and gs if they have changed in the signal handler. - This does not handle long fs/gs base changes in the handler, but - does not clobber them at least in the normal case. */ - - { - unsigned gs, oldgs; - err |= __get_user(gs, &sc->gs); - gs |= 3; - asm("movl %%gs,%0" : "=r" (oldgs)); - if (gs != oldgs) - load_gs_index(gs); - } - RELOAD_SEG(fs,3); - RELOAD_SEG(ds,3); - RELOAD_SEG(es,3); +static int ia32_restore_sigcontext(struct pt_regs *regs, + struct sigcontext_ia32 __user *sc, + unsigned int *peax) +{ + unsigned int tmpflags, gs, oldgs, err = 0; + struct _fpstate_ia32 __user *buf; + u32 tmp; + + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + +#if DEBUG_SIG + printk(KERN_DEBUG "SIG restore_sigcontext: " + "sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n", + sc, sc->err, sc->eip, sc->cs, sc->eflags); +#endif + + /* + * Reload fs and gs if they have changed in the signal + * handler. This does not handle long fs/gs base changes in + * the handler, but does not clobber them at least in the + * normal case. + */ + err |= __get_user(gs, &sc->gs); + gs |= 3; + asm("movl %%gs,%0" : "=r" (oldgs)); + if (gs != oldgs) + load_gs_index(gs); + + RELOAD_SEG(fs, 3); + RELOAD_SEG(ds, 3); + RELOAD_SEG(es, 3); COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); COPY(dx); COPY(cx); COPY(ip); - /* Don't touch extended registers */ - - err |= __get_user(regs->cs, &sc->cs); - regs->cs |= 3; - err |= __get_user(regs->ss, &sc->ss); - regs->ss |= 3; + /* Don't touch extended registers */ - { - unsigned int tmpflags; - err |= __get_user(tmpflags, &sc->eflags); - regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); - regs->orig_rax = -1; /* disable syscall checks */ - } + err |= __get_user(regs->cs, &sc->cs); + regs->cs |= 3; + err |= __get_user(regs->ss, &sc->ss); + regs->ss |= 3; - { - u32 tmp; - struct _fpstate_ia32 __user * buf; - err |= __get_user(tmp, &sc->fpstate); - buf = compat_ptr(tmp); - if (buf) { - if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) - goto badframe; - err |= restore_i387_ia32(current, buf, 0); - } else { - struct task_struct *me = current; - if (used_math()) { - clear_fpu(me); - clear_used_math(); - } + err |= __get_user(tmpflags, &sc->eflags); + regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); + /* disable syscall checks */ + regs->orig_rax = -1; + + err |= __get_user(tmp, &sc->fpstate); + buf = compat_ptr(tmp); + if (buf) { + if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) + goto badframe; + err |= restore_i387_ia32(current, buf, 0); + } else { + struct task_struct *me = current; + + if (used_math()) { + clear_fpu(me); + clear_used_math(); } } - { - u32 tmp; - err |= __get_user(tmp, &sc->eax); - *peax = tmp; - } + err |= __get_user(tmp, &sc->eax); + *peax = tmp; + return err; badframe: @@ -283,7 +287,8 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs) goto badframe; if (__get_user(set.sig[0], &frame->sc.oldmask) || (_COMPAT_NSIG_WORDS > 1 - && __copy_from_user((((char *) &set.sig) + 4), &frame->extramask, + && __copy_from_user((((char *) &set.sig) + 4), + &frame->extramask, sizeof(frame->extramask)))) goto badframe; @@ -292,7 +297,7 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs) current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - + if (ia32_restore_sigcontext(regs, &frame->sc, &eax)) goto badframe; return eax; @@ -300,7 +305,7 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs) badframe: signal_fault(regs, frame, "32bit sigreturn"); return 0; -} +} asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) { @@ -321,7 +326,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - + if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax)) goto badframe; @@ -332,17 +337,17 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) return eax; badframe: - signal_fault(regs,frame,"32bit rt sigreturn"); + signal_fault(regs, frame, "32bit rt sigreturn"); return 0; -} +} /* * Set up a signal frame. */ -static int -ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __user *fpstate, - struct pt_regs *regs, unsigned int mask) +static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, + struct _fpstate_ia32 __user *fpstate, + struct pt_regs *regs, unsigned int mask) { int tmp, err = 0; @@ -375,7 +380,7 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __ tmp = save_i387_ia32(current, fpstate, regs, 0); if (tmp < 0) err = -EFAULT; - else { + else { clear_used_math(); stts(); err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL), @@ -392,8 +397,8 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __ /* * Determine which stack to use.. */ -static void __user * -get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) +static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, + size_t frame_size) { unsigned long rsp; @@ -409,9 +414,8 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) /* This is the legacy signal stack switching. */ else if ((regs->ss & 0xffff) != __USER_DS && !(ka->sa.sa_flags & SA_RESTORER) && - ka->sa.sa_restorer) { + ka->sa.sa_restorer) rsp = (unsigned long) ka->sa.sa_restorer; - } rsp -= frame_size; /* Align the stack pointer according to the i386 ABI, @@ -421,11 +425,25 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) } int ia32_setup_frame(int sig, struct k_sigaction *ka, - compat_sigset_t *set, struct pt_regs * regs) + compat_sigset_t *set, struct pt_regs *regs) { struct sigframe __user *frame; + void __user *restorer; int err = 0; + /* copy_to_user optimizes that into a single 8 byte store */ + static const struct { + u16 poplmovl; + u32 val; + u16 int80; + u16 pad; + } __attribute__((packed)) code = { + 0xb858, /* popl %eax ; movl $...,%eax */ + __NR_ia32_sigreturn, + 0x80cd, /* int $0x80 */ + 0, + }; + frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) @@ -443,38 +461,24 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, if (_COMPAT_NSIG_WORDS > 1) { err |= __copy_to_user(frame->extramask, &set->sig[1], sizeof(frame->extramask)); + if (err) + goto give_sigsegv; } - if (err) - goto give_sigsegv; /* Return stub is in 32bit vsyscall page */ - { - void __user *restorer; - if (current->binfmt->hasvdso) - restorer = VSYSCALL32_SIGRETURN; - else - restorer = (void *)&frame->retcode; - if (ka->sa.sa_flags & SA_RESTORER) - restorer = ka->sa.sa_restorer; - err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); - } - /* These are actually not used anymore, but left because some - gdb versions depend on them as a marker. */ - { - /* copy_to_user optimizes that into a single 8 byte store */ - static const struct { - u16 poplmovl; - u32 val; - u16 int80; - u16 pad; - } __attribute__((packed)) code = { - 0xb858, /* popl %eax ; movl $...,%eax */ - __NR_ia32_sigreturn, - 0x80cd, /* int $0x80 */ - 0, - }; - err |= __copy_to_user(frame->retcode, &code, 8); - } + if (current->binfmt->hasvdso) + restorer = VSYSCALL32_SIGRETURN; + else + restorer = (void *)&frame->retcode; + if (ka->sa.sa_flags & SA_RESTORER) + restorer = ka->sa.sa_restorer; + err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); + + /* + * These are actually not used anymore, but left because some + * gdb versions depend on them as a marker. + */ + err |= __copy_to_user(frame->retcode, &code, 8); if (err) goto give_sigsegv; @@ -487,11 +491,11 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, regs->rdx = 0; regs->rcx = 0; - asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); - asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); + asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); + asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); - regs->cs = __USER32_CS; - regs->ss = __USER32_DS; + regs->cs = __USER32_CS; + regs->ss = __USER32_DS; set_fs(USER_DS); regs->eflags &= ~TF_MASK; @@ -499,8 +503,8 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, ptrace_notify(SIGTRAP); #if DEBUG_SIG - printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n", - current->comm, current->pid, frame, regs->rip, frame->pretcode); + printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n", + current->comm, current->pid, frame, regs->rip, frame->pretcode); #endif return 0; @@ -511,25 +515,34 @@ give_sigsegv: } int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - compat_sigset_t *set, struct pt_regs * regs) + compat_sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; + struct exec_domain *ed = current_thread_info()->exec_domain; + void __user *restorer = VSYSCALL32_RTSIGRETURN; int err = 0; + /* __copy_to_user optimizes that into a single 8 byte store */ + static const struct { + u8 movl; + u32 val; + u16 int80; + u16 pad; + u8 pad2; + } __attribute__((packed)) code = { + 0xb8, + __NR_ia32_rt_sigreturn, + 0x80cd, + 0, + }; + frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - { - struct exec_domain *ed = current_thread_info()->exec_domain; - err |= __put_user((ed - && ed->signal_invmap - && sig < 32 - ? ed->signal_invmap[sig] - : sig), - &frame->sig); - } + err |= __put_user((ed && ed->signal_invmap && sig < 32 + ? ed->signal_invmap[sig] : sig), &frame->sig); err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo); err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc); err |= copy_siginfo_to_user32(&frame->info, info); @@ -544,38 +557,20 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, - regs, set->sig[0]); + regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; - - { - void __user *restorer = VSYSCALL32_RTSIGRETURN; - if (ka->sa.sa_flags & SA_RESTORER) - restorer = ka->sa.sa_restorer; - err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); - } + if (ka->sa.sa_flags & SA_RESTORER) + restorer = ka->sa.sa_restorer; + err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); - /* This is movl $,%eax ; int $0x80 */ - /* Not actually used anymore, but left because some gdb versions - need it. */ - { - /* __copy_to_user optimizes that into a single 8 byte store */ - static const struct { - u8 movl; - u32 val; - u16 int80; - u16 pad; - u8 pad2; - } __attribute__((packed)) code = { - 0xb8, - __NR_ia32_rt_sigreturn, - 0x80cd, - 0, - }; - err |= __copy_to_user(frame->retcode, &code, 8); - } + /* + * Not actually used anymore, but left because some gdb + * versions need it. + */ + err |= __copy_to_user(frame->retcode, &code, 8); if (err) goto give_sigsegv; @@ -593,11 +588,11 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->rdx = (unsigned long) &frame->info; regs->rcx = (unsigned long) &frame->uc; - asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); - asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); - - regs->cs = __USER32_CS; - regs->ss = __USER32_DS; + asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); + asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); + + regs->cs = __USER32_CS; + regs->ss = __USER32_DS; set_fs(USER_DS); regs->eflags &= ~TF_MASK; @@ -605,8 +600,8 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ptrace_notify(SIGTRAP); #if DEBUG_SIG - printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n", - current->comm, current->pid, frame, regs->rip, frame->pretcode); + printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n", + current->comm, current->pid, frame, regs->rip, frame->pretcode); #endif return 0; From 2da06b4e5da96fff4f07cc35af1db407e1e21aa7 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:08 +0100 Subject: [PATCH 035/890] x86: clean up arch/x86/ia32/ipc32.c White space and coding style cleanup. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/ia32/ipc32.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/arch/x86/ia32/ipc32.c b/arch/x86/ia32/ipc32.c index 7b3342e5aab5..d21991ce606c 100644 --- a/arch/x86/ia32/ipc32.c +++ b/arch/x86/ia32/ipc32.c @@ -9,9 +9,8 @@ #include #include -asmlinkage long -sys32_ipc(u32 call, int first, int second, int third, - compat_uptr_t ptr, u32 fifth) +asmlinkage long sys32_ipc(u32 call, int first, int second, int third, + compat_uptr_t ptr, u32 fifth) { int version; @@ -19,36 +18,35 @@ sys32_ipc(u32 call, int first, int second, int third, call &= 0xffff; switch (call) { - case SEMOP: + case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ return sys_semtimedop(first, compat_ptr(ptr), second, NULL); - case SEMTIMEDOP: + case SEMTIMEDOP: return compat_sys_semtimedop(first, compat_ptr(ptr), second, compat_ptr(fifth)); - case SEMGET: + case SEMGET: return sys_semget(first, second, third); - case SEMCTL: + case SEMCTL: return compat_sys_semctl(first, second, third, compat_ptr(ptr)); - case MSGSND: + case MSGSND: return compat_sys_msgsnd(first, second, third, compat_ptr(ptr)); - case MSGRCV: + case MSGRCV: return compat_sys_msgrcv(first, second, fifth, third, version, compat_ptr(ptr)); - case MSGGET: + case MSGGET: return sys_msgget((key_t) first, second); - case MSGCTL: + case MSGCTL: return compat_sys_msgctl(first, second, compat_ptr(ptr)); - case SHMAT: + case SHMAT: return compat_sys_shmat(first, second, third, version, compat_ptr(ptr)); - break; - case SHMDT: + case SHMDT: return sys_shmdt(compat_ptr(ptr)); - case SHMGET: + case SHMGET: return sys_shmget(first, (unsigned)second, third); - case SHMCTL: + case SHMCTL: return compat_sys_shmctl(first, second, compat_ptr(ptr)); } return -ENOSYS; From 5de15d42e4326b11ff9f3e733343fe7d4ece700b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:08 +0100 Subject: [PATCH 036/890] x86: clean up arch/x86/ia32/ptrace32.c White space and coding style clenaup. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/ia32/ptrace32.c | 190 ++++++++++++++++++++++----------------- 1 file changed, 107 insertions(+), 83 deletions(-) diff --git a/arch/x86/ia32/ptrace32.c b/arch/x86/ia32/ptrace32.c index 4a233ad6269c..9d754b640205 100644 --- a/arch/x86/ia32/ptrace32.c +++ b/arch/x86/ia32/ptrace32.c @@ -1,13 +1,13 @@ -/* +/* * 32bit ptrace for x86-64. * * Copyright 2001,2002 Andi Kleen, SuSE Labs. - * Some parts copied from arch/i386/kernel/ptrace.c. See that file for earlier + * Some parts copied from arch/i386/kernel/ptrace.c. See that file for earlier * copyright. - * - * This allows to access 64bit processes too; but there is no way to see the extended - * register contents. - */ + * + * This allows to access 64bit processes too; but there is no way to + * see the extended register contents. + */ #include #include @@ -35,8 +35,9 @@ */ #define FLAG_MASK 0x54dd5UL -#define R32(l,q) \ - case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; break +#define R32(l,q) \ + case offsetof(struct user32, regs.l): \ + stack[offsetof(struct pt_regs, q) / 8] = val; break static int putreg32(struct task_struct *child, unsigned regno, u32 val) { @@ -45,30 +46,35 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) switch (regno) { case offsetof(struct user32, regs.fs): - if (val && (val & 3) != 3) return -EIO; + if (val && (val & 3) != 3) + return -EIO; child->thread.fsindex = val & 0xffff; break; case offsetof(struct user32, regs.gs): - if (val && (val & 3) != 3) return -EIO; + if (val && (val & 3) != 3) + return -EIO; child->thread.gsindex = val & 0xffff; break; case offsetof(struct user32, regs.ds): - if (val && (val & 3) != 3) return -EIO; + if (val && (val & 3) != 3) + return -EIO; child->thread.ds = val & 0xffff; break; case offsetof(struct user32, regs.es): child->thread.es = val & 0xffff; break; - case offsetof(struct user32, regs.ss): - if ((val & 3) != 3) return -EIO; - stack[offsetof(struct pt_regs, ss)/8] = val & 0xffff; + case offsetof(struct user32, regs.ss): + if ((val & 3) != 3) + return -EIO; + stack[offsetof(struct pt_regs, ss)/8] = val & 0xffff; break; - case offsetof(struct user32, regs.cs): - if ((val & 3) != 3) return -EIO; + case offsetof(struct user32, regs.cs): + if ((val & 3) != 3) + return -EIO; stack[offsetof(struct pt_regs, cs)/8] = val & 0xffff; break; - R32(ebx, rbx); + R32(ebx, rbx); R32(ecx, rcx); R32(edx, rdx); R32(edi, rdi); @@ -81,12 +87,13 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) case offsetof(struct user32, regs.eflags): { __u64 *flags = &stack[offsetof(struct pt_regs, eflags)/8]; + val &= FLAG_MASK; *flags = val | (*flags & ~FLAG_MASK); break; } - case offsetof(struct user32, u_debugreg[4]): + case offsetof(struct user32, u_debugreg[4]): case offsetof(struct user32, u_debugreg[5]): return -EIO; @@ -108,36 +115,40 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) case offsetof(struct user32, u_debugreg[6]): child->thread.debugreg6 = val; - break; + break; case offsetof(struct user32, u_debugreg[7]): val &= ~DR_CONTROL_RESERVED; /* See arch/i386/kernel/ptrace.c for an explanation of * this awkward check.*/ - for(i=0; i<4; i++) + for (i = 0; i < 4; i++) if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1) return -EIO; - child->thread.debugreg7 = val; + child->thread.debugreg7 = val; if (val) set_tsk_thread_flag(child, TIF_DEBUG); else clear_tsk_thread_flag(child, TIF_DEBUG); - break; - + break; + default: if (regno > sizeof(struct user32) || (regno & 3)) return -EIO; - - /* Other dummy fields in the virtual user structure are ignored */ - break; + + /* + * Other dummy fields in the virtual user structure + * are ignored + */ + break; } return 0; } #undef R32 -#define R32(l,q) \ - case offsetof(struct user32, regs.l): *val = stack[offsetof(struct pt_regs, q)/8]; break +#define R32(l,q) \ + case offsetof(struct user32, regs.l): \ + *val = stack[offsetof(struct pt_regs, q)/8]; break static int getreg32(struct task_struct *child, unsigned regno, u32 *val) { @@ -145,7 +156,7 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) switch (regno) { case offsetof(struct user32, regs.fs): - *val = child->thread.fsindex; + *val = child->thread.fsindex; break; case offsetof(struct user32, regs.gs): *val = child->thread.gsindex; @@ -159,7 +170,7 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) R32(cs, cs); R32(ss, ss); - R32(ebx, rbx); + R32(ebx, rbx); R32(ecx, rcx); R32(edx, rdx); R32(edi, rdi); @@ -171,32 +182,35 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) R32(eflags, eflags); R32(esp, rsp); - case offsetof(struct user32, u_debugreg[0]): - *val = child->thread.debugreg0; - break; - case offsetof(struct user32, u_debugreg[1]): - *val = child->thread.debugreg1; - break; - case offsetof(struct user32, u_debugreg[2]): - *val = child->thread.debugreg2; - break; - case offsetof(struct user32, u_debugreg[3]): - *val = child->thread.debugreg3; - break; - case offsetof(struct user32, u_debugreg[6]): - *val = child->thread.debugreg6; - break; - case offsetof(struct user32, u_debugreg[7]): - *val = child->thread.debugreg7; - break; - + case offsetof(struct user32, u_debugreg[0]): + *val = child->thread.debugreg0; + break; + case offsetof(struct user32, u_debugreg[1]): + *val = child->thread.debugreg1; + break; + case offsetof(struct user32, u_debugreg[2]): + *val = child->thread.debugreg2; + break; + case offsetof(struct user32, u_debugreg[3]): + *val = child->thread.debugreg3; + break; + case offsetof(struct user32, u_debugreg[6]): + *val = child->thread.debugreg6; + break; + case offsetof(struct user32, u_debugreg[7]): + *val = child->thread.debugreg7; + break; + default: if (regno > sizeof(struct user32) || (regno & 3)) return -EIO; - /* Other dummy fields in the virtual user structure are ignored */ + /* + * Other dummy fields in the virtual user structure + * are ignored + */ *val = 0; - break; + break; } return 0; } @@ -205,10 +219,11 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data) { - int ret; - compat_siginfo_t __user *si32 = compat_ptr(data); - siginfo_t ssi; siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t)); + compat_siginfo_t __user *si32 = compat_ptr(data); + siginfo_t ssi; + int ret; + if (request == PTRACE_SETSIGINFO) { memset(&ssi, 0, sizeof(siginfo_t)); ret = copy_siginfo_from_user32(&ssi, si32); @@ -231,12 +246,12 @@ static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data) asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) { struct task_struct *child; - struct pt_regs *childregs; + struct pt_regs *childregs; void __user *datap = compat_ptr(data); int ret; __u32 val; - switch (request) { + switch (request) { case PTRACE_TRACEME: case PTRACE_ATTACH: case PTRACE_KILL: @@ -248,7 +263,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_SETOPTIONS: case PTRACE_SET_THREAD_AREA: case PTRACE_GET_THREAD_AREA: - return sys_ptrace(request, pid, addr, data); + return sys_ptrace(request, pid, addr, data); default: return -EINVAL; @@ -257,7 +272,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_PEEKDATA: case PTRACE_POKEDATA: case PTRACE_POKETEXT: - case PTRACE_POKEUSR: + case PTRACE_POKEUSR: case PTRACE_PEEKUSR: case PTRACE_GETREGS: case PTRACE_SETREGS: @@ -287,17 +302,19 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_PEEKDATA: case PTRACE_PEEKTEXT: ret = 0; - if (access_process_vm(child, addr, &val, sizeof(u32), 0)!=sizeof(u32)) + if (access_process_vm(child, addr, &val, sizeof(u32), 0) != + sizeof(u32)) ret = -EIO; else - ret = put_user(val, (unsigned int __user *)datap); - break; + ret = put_user(val, (unsigned int __user *)datap); + break; case PTRACE_POKEDATA: case PTRACE_POKETEXT: ret = 0; - if (access_process_vm(child, addr, &data, sizeof(u32), 1)!=sizeof(u32)) - ret = -EIO; + if (access_process_vm(child, addr, &data, sizeof(u32), 1) != + sizeof(u32)) + ret = -EIO; break; case PTRACE_PEEKUSR: @@ -312,14 +329,15 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_GETREGS: { /* Get all gp regs from the child. */ int i; - if (!access_ok(VERIFY_WRITE, datap, 16*4)) { + + if (!access_ok(VERIFY_WRITE, datap, 16*4)) { ret = -EIO; break; } ret = 0; - for ( i = 0; i <= 16*4 ; i += sizeof(__u32) ) { + for (i = 0; i <= 16*4; i += sizeof(__u32)) { getreg32(child, i, &val); - ret |= __put_user(val,(u32 __user *)datap); + ret |= __put_user(val, (u32 __user *)datap); datap += sizeof(u32); } break; @@ -328,12 +346,13 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_SETREGS: { /* Set all gp regs in the child. */ unsigned long tmp; int i; - if (!access_ok(VERIFY_READ, datap, 16*4)) { + + if (!access_ok(VERIFY_READ, datap, 16*4)) { ret = -EIO; break; } - ret = 0; - for ( i = 0; i <= 16*4; i += sizeof(u32) ) { + ret = 0; + for (i = 0; i <= 16*4; i += sizeof(u32)) { ret |= __get_user(tmp, (u32 __user *)datap); putreg32(child, i, tmp); datap += sizeof(u32); @@ -342,17 +361,17 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) } case PTRACE_GETFPREGS: - ret = -EIO; - if (!access_ok(VERIFY_READ, compat_ptr(data), + ret = -EIO; + if (!access_ok(VERIFY_READ, compat_ptr(data), sizeof(struct user_i387_struct))) break; save_i387_ia32(child, datap, childregs, 1); - ret = 0; + ret = 0; break; case PTRACE_SETFPREGS: ret = -EIO; - if (!access_ok(VERIFY_WRITE, datap, + if (!access_ok(VERIFY_WRITE, datap, sizeof(struct user_i387_struct))) break; ret = 0; @@ -360,9 +379,10 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) restore_i387_ia32(child, datap, 1); break; - case PTRACE_GETFPXREGS: { + case PTRACE_GETFPXREGS: { struct user32_fxsr_struct __user *u = datap; - init_fpu(child); + + init_fpu(child); ret = -EIO; if (!access_ok(VERIFY_WRITE, u, sizeof(*u))) break; @@ -370,27 +390,31 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) if (__copy_to_user(u, &child->thread.i387.fxsave, sizeof(*u))) break; ret = __put_user(childregs->cs, &u->fcs); - ret |= __put_user(child->thread.ds, &u->fos); - break; - } - case PTRACE_SETFPXREGS: { + ret |= __put_user(child->thread.ds, &u->fos); + break; + } + case PTRACE_SETFPXREGS: { struct user32_fxsr_struct __user *u = datap; + unlazy_fpu(child); ret = -EIO; if (!access_ok(VERIFY_READ, u, sizeof(*u))) break; - /* no checking to be bug-to-bug compatible with i386. */ - /* but silence warning */ + /* + * no checking to be bug-to-bug compatible with i386. + * but silence warning + */ if (__copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u))) ; set_stopped_child_used_math(child); child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask; - ret = 0; + ret = 0; break; } case PTRACE_GETEVENTMSG: - ret = put_user(child->ptrace_message,(unsigned int __user *)compat_ptr(data)); + ret = put_user(child->ptrace_message, + (unsigned int __user *)compat_ptr(data)); break; default: From c202f298de59c17c0a9799dc0e1b9e0629347935 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:08 +0100 Subject: [PATCH 037/890] x86: clean up arch/x86/ia32/sys_ia32.c White space and coding style clenaup. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/ia32/sys_ia32.c | 496 ++++++++++++++++++++------------------- include/linux/compat.h | 4 + 2 files changed, 256 insertions(+), 244 deletions(-) diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index bee96d614432..58991abc5b59 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c @@ -1,29 +1,29 @@ /* * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on - * sys_sparc32 + * sys_sparc32 * * Copyright (C) 2000 VA Linux Co * Copyright (C) 2000 Don Dugger - * Copyright (C) 1999 Arun Sharma - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1999 Arun Sharma + * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 2000 Hewlett-Packard Co. * Copyright (C) 2000 David Mosberger-Tang - * Copyright (C) 2000,2001,2002 Andi Kleen, SuSE Labs (x86-64 port) + * Copyright (C) 2000,2001,2002 Andi Kleen, SuSE Labs (x86-64 port) * * These routines maintain argument size conversion between 32bit and 64bit - * environment. In 2.5 most of this should be moved to a generic directory. + * environment. In 2.5 most of this should be moved to a generic directory. * * This file assumes that there is a hole at the end of user address space. - * - * Some of the functions are LE specific currently. These are hopefully all marked. - * This should be fixed. + * + * Some of the functions are LE specific currently. These are + * hopefully all marked. This should be fixed. */ #include #include -#include -#include +#include +#include #include #include #include @@ -90,43 +90,44 @@ int cp_compat_stat(struct kstat *kbuf, struct compat_stat __user *ubuf) if (sizeof(ino) < sizeof(kbuf->ino) && ino != kbuf->ino) return -EOVERFLOW; if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct compat_stat)) || - __put_user (old_encode_dev(kbuf->dev), &ubuf->st_dev) || - __put_user (ino, &ubuf->st_ino) || - __put_user (kbuf->mode, &ubuf->st_mode) || - __put_user (kbuf->nlink, &ubuf->st_nlink) || - __put_user (uid, &ubuf->st_uid) || - __put_user (gid, &ubuf->st_gid) || - __put_user (old_encode_dev(kbuf->rdev), &ubuf->st_rdev) || - __put_user (kbuf->size, &ubuf->st_size) || - __put_user (kbuf->atime.tv_sec, &ubuf->st_atime) || - __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime_nsec) || - __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime) || - __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec) || - __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime) || - __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec) || - __put_user (kbuf->blksize, &ubuf->st_blksize) || - __put_user (kbuf->blocks, &ubuf->st_blocks)) + __put_user(old_encode_dev(kbuf->dev), &ubuf->st_dev) || + __put_user(ino, &ubuf->st_ino) || + __put_user(kbuf->mode, &ubuf->st_mode) || + __put_user(kbuf->nlink, &ubuf->st_nlink) || + __put_user(uid, &ubuf->st_uid) || + __put_user(gid, &ubuf->st_gid) || + __put_user(old_encode_dev(kbuf->rdev), &ubuf->st_rdev) || + __put_user(kbuf->size, &ubuf->st_size) || + __put_user(kbuf->atime.tv_sec, &ubuf->st_atime) || + __put_user(kbuf->atime.tv_nsec, &ubuf->st_atime_nsec) || + __put_user(kbuf->mtime.tv_sec, &ubuf->st_mtime) || + __put_user(kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec) || + __put_user(kbuf->ctime.tv_sec, &ubuf->st_ctime) || + __put_user(kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec) || + __put_user(kbuf->blksize, &ubuf->st_blksize) || + __put_user(kbuf->blocks, &ubuf->st_blocks)) return -EFAULT; return 0; } -asmlinkage long -sys32_truncate64(char __user * filename, unsigned long offset_low, unsigned long offset_high) +asmlinkage long sys32_truncate64(char __user *filename, + unsigned long offset_low, + unsigned long offset_high) { return sys_truncate(filename, ((loff_t) offset_high << 32) | offset_low); } -asmlinkage long -sys32_ftruncate64(unsigned int fd, unsigned long offset_low, unsigned long offset_high) +asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long offset_low, + unsigned long offset_high) { return sys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low); } -/* Another set for IA32/LFS -- x86_64 struct stat is different due to - support for 64bit inode numbers. */ - -static int -cp_stat64(struct stat64 __user *ubuf, struct kstat *stat) +/* + * Another set for IA32/LFS -- x86_64 struct stat is different due to + * support for 64bit inode numbers. + */ +static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat) { typeof(ubuf->st_uid) uid = 0; typeof(ubuf->st_gid) gid = 0; @@ -134,38 +135,39 @@ cp_stat64(struct stat64 __user *ubuf, struct kstat *stat) SET_GID(gid, stat->gid); if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64)) || __put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) || - __put_user (stat->ino, &ubuf->__st_ino) || - __put_user (stat->ino, &ubuf->st_ino) || - __put_user (stat->mode, &ubuf->st_mode) || - __put_user (stat->nlink, &ubuf->st_nlink) || - __put_user (uid, &ubuf->st_uid) || - __put_user (gid, &ubuf->st_gid) || - __put_user (huge_encode_dev(stat->rdev), &ubuf->st_rdev) || - __put_user (stat->size, &ubuf->st_size) || - __put_user (stat->atime.tv_sec, &ubuf->st_atime) || - __put_user (stat->atime.tv_nsec, &ubuf->st_atime_nsec) || - __put_user (stat->mtime.tv_sec, &ubuf->st_mtime) || - __put_user (stat->mtime.tv_nsec, &ubuf->st_mtime_nsec) || - __put_user (stat->ctime.tv_sec, &ubuf->st_ctime) || - __put_user (stat->ctime.tv_nsec, &ubuf->st_ctime_nsec) || - __put_user (stat->blksize, &ubuf->st_blksize) || - __put_user (stat->blocks, &ubuf->st_blocks)) + __put_user(stat->ino, &ubuf->__st_ino) || + __put_user(stat->ino, &ubuf->st_ino) || + __put_user(stat->mode, &ubuf->st_mode) || + __put_user(stat->nlink, &ubuf->st_nlink) || + __put_user(uid, &ubuf->st_uid) || + __put_user(gid, &ubuf->st_gid) || + __put_user(huge_encode_dev(stat->rdev), &ubuf->st_rdev) || + __put_user(stat->size, &ubuf->st_size) || + __put_user(stat->atime.tv_sec, &ubuf->st_atime) || + __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec) || + __put_user(stat->mtime.tv_sec, &ubuf->st_mtime) || + __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec) || + __put_user(stat->ctime.tv_sec, &ubuf->st_ctime) || + __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec) || + __put_user(stat->blksize, &ubuf->st_blksize) || + __put_user(stat->blocks, &ubuf->st_blocks)) return -EFAULT; return 0; } -asmlinkage long -sys32_stat64(char __user * filename, struct stat64 __user *statbuf) +asmlinkage long sys32_stat64(char __user *filename, + struct stat64 __user *statbuf) { struct kstat stat; int ret = vfs_stat(filename, &stat); + if (!ret) ret = cp_stat64(statbuf, &stat); return ret; } -asmlinkage long -sys32_lstat64(char __user * filename, struct stat64 __user *statbuf) +asmlinkage long sys32_lstat64(char __user *filename, + struct stat64 __user *statbuf) { struct kstat stat; int ret = vfs_lstat(filename, &stat); @@ -174,8 +176,7 @@ sys32_lstat64(char __user * filename, struct stat64 __user *statbuf) return ret; } -asmlinkage long -sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf) +asmlinkage long sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf) { struct kstat stat; int ret = vfs_fstat(fd, &stat); @@ -184,9 +185,8 @@ sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf) return ret; } -asmlinkage long -sys32_fstatat(unsigned int dfd, char __user *filename, - struct stat64 __user* statbuf, int flag) +asmlinkage long sys32_fstatat(unsigned int dfd, char __user *filename, + struct stat64 __user *statbuf, int flag) { struct kstat stat; int error = -EINVAL; @@ -221,8 +221,7 @@ struct mmap_arg_struct { unsigned int offset; }; -asmlinkage long -sys32_mmap(struct mmap_arg_struct __user *arg) +asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg) { struct mmap_arg_struct a; struct file *file = NULL; @@ -233,33 +232,33 @@ sys32_mmap(struct mmap_arg_struct __user *arg) return -EFAULT; if (a.offset & ~PAGE_MASK) - return -EINVAL; + return -EINVAL; if (!(a.flags & MAP_ANONYMOUS)) { file = fget(a.fd); if (!file) return -EBADF; } - - mm = current->mm; - down_write(&mm->mmap_sem); - retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset>>PAGE_SHIFT); + + mm = current->mm; + down_write(&mm->mmap_sem); + retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, + a.offset>>PAGE_SHIFT); if (file) fput(file); - up_write(&mm->mmap_sem); + up_write(&mm->mmap_sem); return retval; } -asmlinkage long -sys32_mprotect(unsigned long start, size_t len, unsigned long prot) +asmlinkage long sys32_mprotect(unsigned long start, size_t len, + unsigned long prot) { - return sys_mprotect(start,len,prot); + return sys_mprotect(start, len, prot); } -asmlinkage long -sys32_pipe(int __user *fd) +asmlinkage long sys32_pipe(int __user *fd) { int retval; int fds[2]; @@ -269,13 +268,13 @@ sys32_pipe(int __user *fd) goto out; if (copy_to_user(fd, fds, sizeof(fds))) retval = -EFAULT; - out: +out: return retval; } -asmlinkage long -sys32_rt_sigaction(int sig, struct sigaction32 __user *act, - struct sigaction32 __user *oact, unsigned int sigsetsize) +asmlinkage long sys32_rt_sigaction(int sig, struct sigaction32 __user *act, + struct sigaction32 __user *oact, + unsigned int sigsetsize) { struct k_sigaction new_ka, old_ka; int ret; @@ -291,12 +290,17 @@ sys32_rt_sigaction(int sig, struct sigaction32 __user *act, if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(handler, &act->sa_handler) || __get_user(new_ka.sa.sa_flags, &act->sa_flags) || - __get_user(restorer, &act->sa_restorer)|| - __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t))) + __get_user(restorer, &act->sa_restorer) || + __copy_from_user(&set32, &act->sa_mask, + sizeof(compat_sigset_t))) return -EFAULT; new_ka.sa.sa_handler = compat_ptr(handler); new_ka.sa.sa_restorer = compat_ptr(restorer); - /* FIXME: here we rely on _COMPAT_NSIG_WORS to be >= than _NSIG_WORDS << 1 */ + + /* + * FIXME: here we rely on _COMPAT_NSIG_WORS to be >= + * than _NSIG_WORDS << 1 + */ switch (_NSIG_WORDS) { case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32); @@ -312,7 +316,10 @@ sys32_rt_sigaction(int sig, struct sigaction32 __user *act, ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - /* FIXME: here we rely on _COMPAT_NSIG_WORS to be >= than _NSIG_WORDS << 1 */ + /* + * FIXME: here we rely on _COMPAT_NSIG_WORS to be >= + * than _NSIG_WORDS << 1 + */ switch (_NSIG_WORDS) { case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); @@ -328,23 +335,26 @@ sys32_rt_sigaction(int sig, struct sigaction32 __user *act, set32.sig[0] = old_ka.sa.sa_mask.sig[0]; } if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) || - __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer) || + __put_user(ptr_to_compat(old_ka.sa.sa_handler), + &oact->sa_handler) || + __put_user(ptr_to_compat(old_ka.sa.sa_restorer), + &oact->sa_restorer) || __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || - __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t))) + __copy_to_user(&oact->sa_mask, &set32, + sizeof(compat_sigset_t))) return -EFAULT; } return ret; } -asmlinkage long -sys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact) +asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 __user *act, + struct old_sigaction32 __user *oact) { - struct k_sigaction new_ka, old_ka; - int ret; + struct k_sigaction new_ka, old_ka; + int ret; - if (act) { + if (act) { compat_old_sigset_t mask; compat_uptr_t handler, restorer; @@ -359,33 +369,35 @@ sys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigacti new_ka.sa.sa_restorer = compat_ptr(restorer); siginitset(&new_ka.sa.sa_mask, mask); - } + } - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) || - __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer) || + __put_user(ptr_to_compat(old_ka.sa.sa_handler), + &oact->sa_handler) || + __put_user(ptr_to_compat(old_ka.sa.sa_restorer), + &oact->sa_restorer) || __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) return -EFAULT; - } + } return ret; } -asmlinkage long -sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, - compat_sigset_t __user *oset, unsigned int sigsetsize) +asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, + compat_sigset_t __user *oset, + unsigned int sigsetsize) { sigset_t s; compat_sigset_t s32; int ret; mm_segment_t old_fs = get_fs(); - + if (set) { - if (copy_from_user (&s32, set, sizeof(compat_sigset_t))) + if (copy_from_user(&s32, set, sizeof(compat_sigset_t))) return -EFAULT; switch (_NSIG_WORDS) { case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); @@ -394,13 +406,14 @@ sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); } } - set_fs (KERNEL_DS); + set_fs(KERNEL_DS); ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&s : NULL, oset ? (sigset_t __user *)&s : NULL, - sigsetsize); - set_fs (old_fs); - if (ret) return ret; + sigsetsize); + set_fs(old_fs); + if (ret) + return ret; if (oset) { switch (_NSIG_WORDS) { case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; @@ -408,52 +421,49 @@ sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; } - if (copy_to_user (oset, &s32, sizeof(compat_sigset_t))) + if (copy_to_user(oset, &s32, sizeof(compat_sigset_t))) return -EFAULT; } return 0; } -static inline long -get_tv32(struct timeval *o, struct compat_timeval __user *i) +static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i) { - int err = -EFAULT; - if (access_ok(VERIFY_READ, i, sizeof(*i))) { + int err = -EFAULT; + + if (access_ok(VERIFY_READ, i, sizeof(*i))) { err = __get_user(o->tv_sec, &i->tv_sec); err |= __get_user(o->tv_usec, &i->tv_usec); } - return err; + return err; } -static inline long -put_tv32(struct compat_timeval __user *o, struct timeval *i) +static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i) { int err = -EFAULT; - if (access_ok(VERIFY_WRITE, o, sizeof(*o))) { + + if (access_ok(VERIFY_WRITE, o, sizeof(*o))) { err = __put_user(i->tv_sec, &o->tv_sec); err |= __put_user(i->tv_usec, &o->tv_usec); - } - return err; + } + return err; } -extern unsigned int alarm_setitimer(unsigned int seconds); - -asmlinkage long -sys32_alarm(unsigned int seconds) +asmlinkage long sys32_alarm(unsigned int seconds) { return alarm_setitimer(seconds); } -/* Translations due to time_t size differences. Which affects all - sorts of things, like timeval and itimerval. */ - -extern struct timezone sys_tz; - -asmlinkage long -sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) +/* + * Translations due to time_t size differences. Which affects all + * sorts of things, like timeval and itimerval. + */ +asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, + struct timezone __user *tz) { if (tv) { struct timeval ktv; + do_gettimeofday(&ktv); if (put_tv32(tv, &ktv)) return -EFAULT; @@ -465,14 +475,14 @@ sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) return 0; } -asmlinkage long -sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) +asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, + struct timezone __user *tz) { struct timeval ktv; struct timespec kts; struct timezone ktz; - if (tv) { + if (tv) { if (get_tv32(&ktv, tv)) return -EFAULT; kts.tv_sec = ktv.tv_sec; @@ -494,8 +504,7 @@ struct sel_arg_struct { unsigned int tvp; }; -asmlinkage long -sys32_old_select(struct sel_arg_struct __user *arg) +asmlinkage long sys32_old_select(struct sel_arg_struct __user *arg) { struct sel_arg_struct a; @@ -505,50 +514,45 @@ sys32_old_select(struct sel_arg_struct __user *arg) compat_ptr(a.exp), compat_ptr(a.tvp)); } -extern asmlinkage long -compat_sys_wait4(compat_pid_t pid, compat_uint_t * stat_addr, int options, - struct compat_rusage *ru); - -asmlinkage long -sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options) +asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, + int options) { return compat_sys_wait4(pid, stat_addr, options, NULL); } /* 32-bit timeval and related flotsam. */ -asmlinkage long -sys32_sysfs(int option, u32 arg1, u32 arg2) +asmlinkage long sys32_sysfs(int option, u32 arg1, u32 arg2) { return sys_sysfs(option, arg1, arg2); } -asmlinkage long -sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval) +asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, + struct compat_timespec __user *interval) { struct timespec t; int ret; - mm_segment_t old_fs = get_fs (); - - set_fs (KERNEL_DS); + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); - set_fs (old_fs); + set_fs(old_fs); if (put_compat_timespec(&t, interval)) return -EFAULT; return ret; } -asmlinkage long -sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize) +asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set, + compat_size_t sigsetsize) { sigset_t s; compat_sigset_t s32; int ret; mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); + + set_fs(KERNEL_DS); ret = sys_rt_sigpending((sigset_t __user *)&s, sigsetsize); - set_fs (old_fs); + set_fs(old_fs); if (!ret) { switch (_NSIG_WORDS) { case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; @@ -556,30 +560,29 @@ sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize) case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; } - if (copy_to_user (set, &s32, sizeof(compat_sigset_t))) + if (copy_to_user(set, &s32, sizeof(compat_sigset_t))) return -EFAULT; } return ret; } -asmlinkage long -sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) +asmlinkage long sys32_rt_sigqueueinfo(int pid, int sig, + compat_siginfo_t __user *uinfo) { siginfo_t info; int ret; mm_segment_t old_fs = get_fs(); - + if (copy_siginfo_from_user32(&info, uinfo)) return -EFAULT; - set_fs (KERNEL_DS); + set_fs(KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info); - set_fs (old_fs); + set_fs(old_fs); return ret; } /* These are here just in case some old ia32 binary calls it. */ -asmlinkage long -sys32_pause(void) +asmlinkage long sys32_pause(void) { current->state = TASK_INTERRUPTIBLE; schedule(); @@ -599,25 +602,25 @@ struct sysctl_ia32 { }; -asmlinkage long -sys32_sysctl(struct sysctl_ia32 __user *args32) +asmlinkage long sys32_sysctl(struct sysctl_ia32 __user *args32) { struct sysctl_ia32 a32; - mm_segment_t old_fs = get_fs (); + mm_segment_t old_fs = get_fs(); void __user *oldvalp, *newvalp; size_t oldlen; int __user *namep; long ret; - if (copy_from_user(&a32, args32, sizeof (a32))) + if (copy_from_user(&a32, args32, sizeof(a32))) return -EFAULT; /* - * We need to pre-validate these because we have to disable address checking - * before calling do_sysctl() because of OLDLEN but we can't run the risk of the - * user specifying bad addresses here. Well, since we're dealing with 32 bit - * addresses, we KNOW that access_ok() will always succeed, so this is an - * expensive NOP, but so what... + * We need to pre-validate these because we have to disable + * address checking before calling do_sysctl() because of + * OLDLEN but we can't run the risk of the user specifying bad + * addresses here. Well, since we're dealing with 32 bit + * addresses, we KNOW that access_ok() will always succeed, so + * this is an expensive NOP, but so what... */ namep = compat_ptr(a32.name); oldvalp = compat_ptr(a32.oldval); @@ -636,34 +639,34 @@ sys32_sysctl(struct sysctl_ia32 __user *args32) unlock_kernel(); set_fs(old_fs); - if (oldvalp && put_user (oldlen, (int __user *)compat_ptr(a32.oldlenp))) + if (oldvalp && put_user(oldlen, (int __user *)compat_ptr(a32.oldlenp))) return -EFAULT; return ret; } #endif -/* warning: next two assume little endian */ -asmlinkage long -sys32_pread(unsigned int fd, char __user *ubuf, u32 count, u32 poslo, u32 poshi) +/* warning: next two assume little endian */ +asmlinkage long sys32_pread(unsigned int fd, char __user *ubuf, u32 count, + u32 poslo, u32 poshi) { return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } -asmlinkage long -sys32_pwrite(unsigned int fd, char __user *ubuf, u32 count, u32 poslo, u32 poshi) +asmlinkage long sys32_pwrite(unsigned int fd, char __user *ubuf, u32 count, + u32 poslo, u32 poshi) { return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } -asmlinkage long -sys32_personality(unsigned long personality) +asmlinkage long sys32_personality(unsigned long personality) { int ret; - if (personality(current->personality) == PER_LINUX32 && + + if (personality(current->personality) == PER_LINUX32 && personality == PER_LINUX) personality = PER_LINUX32; ret = sys_personality(personality); @@ -672,34 +675,33 @@ sys32_personality(unsigned long personality) return ret; } -asmlinkage long -sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count) +asmlinkage long sys32_sendfile(int out_fd, int in_fd, + compat_off_t __user *offset, s32 count) { mm_segment_t old_fs = get_fs(); int ret; off_t of; - + if (offset && get_user(of, offset)) return -EFAULT; - + set_fs(KERNEL_DS); ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count); set_fs(old_fs); - + if (offset && put_user(of, offset)) return -EFAULT; - return ret; } asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) { struct mm_struct *mm = current->mm; unsigned long error; - struct file * file = NULL; + struct file *file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { @@ -717,36 +719,35 @@ asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len, return error; } -asmlinkage long sys32_olduname(struct oldold_utsname __user * name) +asmlinkage long sys32_olduname(struct oldold_utsname __user *name) { + char *arch = "x86_64"; int err; if (!name) return -EFAULT; if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname))) return -EFAULT; - - down_read(&uts_sem); - err = __copy_to_user(&name->sysname,&utsname()->sysname, - __OLD_UTS_LEN); - err |= __put_user(0,name->sysname+__OLD_UTS_LEN); - err |= __copy_to_user(&name->nodename,&utsname()->nodename, - __OLD_UTS_LEN); - err |= __put_user(0,name->nodename+__OLD_UTS_LEN); - err |= __copy_to_user(&name->release,&utsname()->release, - __OLD_UTS_LEN); - err |= __put_user(0,name->release+__OLD_UTS_LEN); - err |= __copy_to_user(&name->version,&utsname()->version, - __OLD_UTS_LEN); - err |= __put_user(0,name->version+__OLD_UTS_LEN); - { - char *arch = "x86_64"; - if (personality(current->personality) == PER_LINUX32) - arch = "i686"; - - err |= __copy_to_user(&name->machine, arch, strlen(arch)+1); - } + down_read(&uts_sem); + + err = __copy_to_user(&name->sysname, &utsname()->sysname, + __OLD_UTS_LEN); + err |= __put_user(0, name->sysname+__OLD_UTS_LEN); + err |= __copy_to_user(&name->nodename, &utsname()->nodename, + __OLD_UTS_LEN); + err |= __put_user(0, name->nodename+__OLD_UTS_LEN); + err |= __copy_to_user(&name->release, &utsname()->release, + __OLD_UTS_LEN); + err |= __put_user(0, name->release+__OLD_UTS_LEN); + err |= __copy_to_user(&name->version, &utsname()->version, + __OLD_UTS_LEN); + err |= __put_user(0, name->version+__OLD_UTS_LEN); + + if (personality(current->personality) == PER_LINUX32) + arch = "i686"; + + err |= __copy_to_user(&name->machine, arch, strlen(arch) + 1); up_read(&uts_sem); @@ -755,17 +756,19 @@ asmlinkage long sys32_olduname(struct oldold_utsname __user * name) return err; } -long sys32_uname(struct old_utsname __user * name) +long sys32_uname(struct old_utsname __user *name) { int err; + if (!name) return -EFAULT; down_read(&uts_sem); - err = copy_to_user(name, utsname(), sizeof (*name)); + err = copy_to_user(name, utsname(), sizeof(*name)); up_read(&uts_sem); - if (personality(current->personality) == PER_LINUX32) + if (personality(current->personality) == PER_LINUX32) err |= copy_to_user(&name->machine, "i686", 5); - return err?-EFAULT:0; + + return err ? -EFAULT : 0; } long sys32_ustat(unsigned dev, struct ustat32 __user *u32p) @@ -773,27 +776,28 @@ long sys32_ustat(unsigned dev, struct ustat32 __user *u32p) struct ustat u; mm_segment_t seg; int ret; - - seg = get_fs(); - set_fs(KERNEL_DS); + + seg = get_fs(); + set_fs(KERNEL_DS); ret = sys_ustat(dev, (struct ustat __user *)&u); set_fs(seg); - if (ret >= 0) { - if (!access_ok(VERIFY_WRITE,u32p,sizeof(struct ustat32)) || - __put_user((__u32) u.f_tfree, &u32p->f_tfree) || - __put_user((__u32) u.f_tinode, &u32p->f_tfree) || - __copy_to_user(&u32p->f_fname, u.f_fname, sizeof(u.f_fname)) || - __copy_to_user(&u32p->f_fpack, u.f_fpack, sizeof(u.f_fpack))) - ret = -EFAULT; - } + if (ret < 0) + return ret; + + if (!access_ok(VERIFY_WRITE, u32p, sizeof(struct ustat32)) || + __put_user((__u32) u.f_tfree, &u32p->f_tfree) || + __put_user((__u32) u.f_tinode, &u32p->f_tfree) || + __copy_to_user(&u32p->f_fname, u.f_fname, sizeof(u.f_fname)) || + __copy_to_user(&u32p->f_fpack, u.f_fpack, sizeof(u.f_fpack))) + ret = -EFAULT; return ret; -} +} asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp, struct pt_regs *regs) { long error; - char * filename; + char *filename; filename = getname(name); error = PTR_ERR(filename); @@ -814,16 +818,17 @@ asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, { void __user *parent_tid = (void __user *)regs->rdx; void __user *child_tid = (void __user *)regs->rdi; + if (!newsp) newsp = regs->rsp; - return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); + return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); } /* - * Some system calls that need sign extended arguments. This could be done by a generic wrapper. - */ - -long sys32_lseek (unsigned int fd, int offset, unsigned int whence) + * Some system calls that need sign extended arguments. This could be + * done by a generic wrapper. + */ +long sys32_lseek(unsigned int fd, int offset, unsigned int whence) { return sys_lseek(fd, offset, whence); } @@ -832,49 +837,52 @@ long sys32_kill(int pid, int sig) { return sys_kill(pid, sig); } - -long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, + +long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, __u32 len_low, __u32 len_high, int advice) -{ +{ return sys_fadvise64_64(fd, (((u64)offset_high)<<32) | offset_low, (((u64)len_high)<<32) | len_low, - advice); -} + advice); +} long sys32_vm86_warning(void) -{ +{ struct task_struct *me = current; static char lastcomm[sizeof(me->comm)]; + if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) { - compat_printk(KERN_INFO "%s: vm86 mode not supported on 64 bit kernel\n", - me->comm); + compat_printk(KERN_INFO + "%s: vm86 mode not supported on 64 bit kernel\n", + me->comm); strncpy(lastcomm, me->comm, sizeof(lastcomm)); - } + } return -ENOSYS; -} +} long sys32_lookup_dcookie(u32 addr_low, u32 addr_high, - char __user * buf, size_t len) + char __user *buf, size_t len) { return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len); } -asmlinkage ssize_t sys32_readahead(int fd, unsigned off_lo, unsigned off_hi, size_t count) +asmlinkage ssize_t sys32_readahead(int fd, unsigned off_lo, unsigned off_hi, + size_t count) { return sys_readahead(fd, ((u64)off_hi << 32) | off_lo, count); } asmlinkage long sys32_sync_file_range(int fd, unsigned off_low, unsigned off_hi, - unsigned n_low, unsigned n_hi, int flags) + unsigned n_low, unsigned n_hi, int flags) { return sys_sync_file_range(fd, ((u64)off_hi << 32) | off_low, ((u64)n_hi << 32) | n_low, flags); } -asmlinkage long sys32_fadvise64(int fd, unsigned offset_lo, unsigned offset_hi, size_t len, - int advice) +asmlinkage long sys32_fadvise64(int fd, unsigned offset_lo, unsigned offset_hi, + size_t len, int advice) { return sys_fadvise64_64(fd, ((u64)offset_hi << 32) | offset_lo, len, advice); diff --git a/include/linux/compat.h b/include/linux/compat.h index 0e69d2cf14aa..ba29d4c59643 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -191,6 +191,10 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, struct compat_timeval __user *tvp); +asmlinkage long compat_sys_wait4(compat_pid_t pid, + compat_uint_t *stat_addr, int options, + struct compat_rusage *ru); + #define BITS_PER_COMPAT_LONG (8*sizeof(compat_long_t)) #define BITS_TO_COMPAT_LONGS(bits) \ From 6ec875666d826dc6ea228afc9f6b644165081ab5 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:08 +0100 Subject: [PATCH 038/890] x86: clean up arch/x86/ia32/syscall32.c White space and coding style clenaup. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/ia32/syscall32.c | 45 +++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/arch/x86/ia32/syscall32.c b/arch/x86/ia32/syscall32.c index 15013bac181c..d751d96c2ef2 100644 --- a/arch/x86/ia32/syscall32.c +++ b/arch/x86/ia32/syscall32.c @@ -1,8 +1,9 @@ -/* Copyright 2002,2003 Andi Kleen, SuSE Labs */ - -/* vsyscall handling for 32bit processes. Map a stub page into it - on demand because 32bit cannot reach the kernel's fixmaps */ - +/* + * Copyright 2002,2003 Andi Kleen, SuSE Labs + * + * vsyscall handling for 32bit processes. Map a stub page into it on + * demand because 32bit cannot reach the kernel's fixmaps + */ #include #include #include @@ -50,31 +51,33 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack) } static int __init init_syscall32(void) -{ +{ char *syscall32_page = (void *)get_zeroed_page(GFP_KERNEL); - if (!syscall32_page) - panic("Cannot allocate syscall32 page"); + + if (!syscall32_page) + panic("Cannot allocate syscall32 page"); syscall32_pages[0] = virt_to_page(syscall32_page); - if (use_sysenter > 0) { - memcpy(syscall32_page, syscall32_sysenter, - syscall32_sysenter_end - syscall32_sysenter); - } else { - memcpy(syscall32_page, syscall32_syscall, - syscall32_syscall_end - syscall32_syscall); - } + if (use_sysenter > 0) { + memcpy(syscall32_page, syscall32_sysenter, + syscall32_sysenter_end - syscall32_sysenter); + } else { + memcpy(syscall32_page, syscall32_syscall, + syscall32_syscall_end - syscall32_syscall); + } return 0; -} - -__initcall(init_syscall32); +} +__initcall(init_syscall32); /* May not be __init: called during resume */ void syscall32_cpu_init(void) { if (use_sysenter < 0) - use_sysenter = (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL); + use_sysenter = (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL); - /* Load these always in case some future AMD CPU supports - SYSENTER from compat mode too. */ + /* + * Load these always in case some future AMD CPU supports + * SYSENTER from compat mode too. + */ checking_wrmsrl(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS); checking_wrmsrl(MSR_IA32_SYSENTER_ESP, 0ULL); checking_wrmsrl(MSR_IA32_SYSENTER_EIP, (u64)ia32_sysenter_target); From 5bafb671e20d2a3721589378681326197fc37a5f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:09 +0100 Subject: [PATCH 039/890] x86: clean up arch/x86/ia32/mmap32.c White space and coding style clenaup. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/ia32/mmap32.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/ia32/mmap32.c b/arch/x86/ia32/mmap32.c index e4b84b4a417a..7649370a3144 100644 --- a/arch/x86/ia32/mmap32.c +++ b/arch/x86/ia32/mmap32.c @@ -36,8 +36,8 @@ * * Leave an at least ~128 MB hole. */ -#define MIN_GAP (128*1024*1024) -#define MAX_GAP (TASK_SIZE/6*5) +#define MIN_GAP (128 * 1024 * 1024) +#define MAX_GAP (TASK_SIZE / 6 * 5) static inline unsigned long mmap_base(struct mm_struct *mm) { @@ -45,7 +45,7 @@ static inline unsigned long mmap_base(struct mm_struct *mm) unsigned long random_factor = 0; if (current->flags & PF_RANDOMIZE) - random_factor = get_random_int() % (1024*1024); + random_factor = get_random_int() % (1024 * 1024); if (gap < MIN_GAP) gap = MIN_GAP; @@ -66,8 +66,8 @@ void ia32_pick_mmap_layout(struct mm_struct *mm) * bit is set, or if the expected stack growth is unlimited: */ if (sysctl_legacy_va_layout || - (current->personality & ADDR_COMPAT_LAYOUT) || - current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { + (current->personality & ADDR_COMPAT_LAYOUT) || + current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { mm->mmap_base = TASK_UNMAPPED_BASE; mm->get_unmapped_area = arch_get_unmapped_area; mm->unmap_area = arch_unmap_area; From c140df973c07ac328aafd19d4f4c413f2f8902df Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:09 +0100 Subject: [PATCH 040/890] x86: clean up arch/x86/kernel/aperture_64.c whitespace cleanup. No code changed: text data bss dec hex filename 2080 76 4 2160 870 aperture_64.o.before 2080 76 4 2160 870 aperture_64.o.after errors lines of code errors/KLOC arch/x86/kernel/aperture_64.c 114 299 381.2 arch/x86/kernel/aperture_64.c 0 315 0 Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/aperture_64.c | 242 ++++++++++++++++++---------------- 1 file changed, 129 insertions(+), 113 deletions(-) diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 5b6992799c9d..250db0527f5d 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -1,12 +1,12 @@ -/* +/* * Firmware replacement code. - * + * * Work around broken BIOSes that don't set an aperture or only set the - * aperture in the AGP bridge. - * If all fails map the aperture over some low memory. This is cheaper than - * doing bounce buffering. The memory is lost. This is done at early boot - * because only the bootmem allocator can allocate 32+MB. - * + * aperture in the AGP bridge. + * If all fails map the aperture over some low memory. This is cheaper than + * doing bounce buffering. The memory is lost. This is done at early boot + * because only the bootmem allocator can allocate 32+MB. + * * Copyright 2002 Andi Kleen, SuSE Labs. */ #include @@ -30,7 +30,7 @@ int gart_iommu_aperture_disabled __initdata = 0; int gart_iommu_aperture_allowed __initdata = 0; int fallback_aper_order __initdata = 1; /* 64MB */ -int fallback_aper_force __initdata = 0; +int fallback_aper_force __initdata = 0; int fix_aperture __initdata = 1; @@ -49,20 +49,20 @@ static void __init insert_aperture_resource(u32 aper_base, u32 aper_size) /* This code runs before the PCI subsystem is initialized, so just access the northbridge directly. */ -static u32 __init allocate_aperture(void) +static u32 __init allocate_aperture(void) { u32 aper_size; - void *p; + void *p; - if (fallback_aper_order > 7) - fallback_aper_order = 7; - aper_size = (32 * 1024 * 1024) << fallback_aper_order; + if (fallback_aper_order > 7) + fallback_aper_order = 7; + aper_size = (32 * 1024 * 1024) << fallback_aper_order; - /* - * Aperture has to be naturally aligned. This means an 2GB aperture won't - * have much chance of finding a place in the lower 4GB of memory. - * Unfortunately we cannot move it up because that would make the - * IOMMU useless. + /* + * Aperture has to be naturally aligned. This means a 2GB aperture + * won't have much chance of finding a place in the lower 4GB of + * memory. Unfortunately we cannot move it up because that would + * make the IOMMU useless. */ p = __alloc_bootmem_nopanic(aper_size, aper_size, 0); if (!p || __pa(p)+aper_size > 0xffffffff) { @@ -73,54 +73,60 @@ static u32 __init allocate_aperture(void) return 0; } printk("Mapping aperture over %d KB of RAM @ %lx\n", - aper_size >> 10, __pa(p)); + aper_size >> 10, __pa(p)); insert_aperture_resource((u32)__pa(p), aper_size); - return (u32)__pa(p); + + return (u32)__pa(p); } static int __init aperture_valid(u64 aper_base, u32 aper_size) -{ - if (!aper_base) +{ + if (!aper_base) return 0; - if (aper_size < 64*1024*1024) { + if (aper_size < 64*1024*1024) { printk("Aperture too small (%d MB)\n", aper_size>>20); return 0; } if (aper_base + aper_size > 0x100000000UL) { printk("Aperture beyond 4GB. Ignoring.\n"); - return 0; + return 0; } if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) { printk("Aperture pointing to e820 RAM. Ignoring.\n"); - return 0; - } + return 0; + } return 1; -} +} /* Find a PCI capability */ -static __u32 __init find_cap(int num, int slot, int func, int cap) -{ - u8 pos; +static __u32 __init find_cap(int num, int slot, int func, int cap) +{ int bytes; - if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST)) + u8 pos; + + if (!(read_pci_config_16(num, slot, func, PCI_STATUS) & + PCI_STATUS_CAP_LIST)) return 0; - pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST); - for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { + + pos = read_pci_config_byte(num, slot, func, PCI_CAPABILITY_LIST); + for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { u8 id; - pos &= ~3; - id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID); + + pos &= ~3; + id = read_pci_config_byte(num, slot, func, pos+PCI_CAP_LIST_ID); if (id == 0xff) break; - if (id == cap) - return pos; - pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT); - } + if (id == cap) + return pos; + pos = read_pci_config_byte(num, slot, func, + pos+PCI_CAP_LIST_NEXT); + } return 0; -} +} /* Read a standard AGPv3 bridge header */ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) -{ +{ u32 apsize; u32 apsizereg; int nbits; @@ -128,7 +134,7 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) u64 aper; printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func); - apsizereg = read_pci_config_16(num,slot,func, cap + 0x14); + apsizereg = read_pci_config_16(num, slot, func, cap + 0x14); if (apsizereg == 0xffffffff) { printk("APSIZE in AGP bridge unreadable\n"); return 0; @@ -136,80 +142,84 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) apsize = apsizereg & 0xfff; /* Some BIOS use weird encodings not in the AGPv3 table. */ - if (apsize & 0xff) - apsize |= 0xf00; + if (apsize & 0xff) + apsize |= 0xf00; nbits = hweight16(apsize); *order = 7 - nbits; if ((int)*order < 0) /* < 32MB */ *order = 0; - - aper_low = read_pci_config(num,slot,func, 0x10); - aper_hi = read_pci_config(num,slot,func,0x14); + + aper_low = read_pci_config(num, slot, func, 0x10); + aper_hi = read_pci_config(num, slot, func, 0x14); aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); - printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", + printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", aper, 32 << *order, apsizereg); if (!aperture_valid(aper, (32*1024*1024) << *order)) - return 0; - return (u32)aper; -} + return 0; + return (u32)aper; +} -/* Look for an AGP bridge. Windows only expects the aperture in the - AGP bridge and some BIOS forget to initialize the Northbridge too. - Work around this here. - - Do an PCI bus scan by hand because we're running before the PCI - subsystem. - - All K8 AGP bridges are AGPv3 compliant, so we can do this scan - generically. It's probably overkill to always scan all slots because - the AGP bridges should be always an own bus on the HT hierarchy, - but do it here for future safety. */ +/* + * Look for an AGP bridge. Windows only expects the aperture in the + * AGP bridge and some BIOS forget to initialize the Northbridge too. + * Work around this here. + * + * Do an PCI bus scan by hand because we're running before the PCI + * subsystem. + * + * All K8 AGP bridges are AGPv3 compliant, so we can do this scan + * generically. It's probably overkill to always scan all slots because + * the AGP bridges should be always an own bus on the HT hierarchy, + * but do it here for future safety. + */ static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) { int num, slot, func; /* Poor man's PCI discovery */ - for (num = 0; num < 256; num++) { - for (slot = 0; slot < 32; slot++) { - for (func = 0; func < 8; func++) { + for (num = 0; num < 256; num++) { + for (slot = 0; slot < 32; slot++) { + for (func = 0; func < 8; func++) { u32 class, cap; u8 type; - class = read_pci_config(num,slot,func, + class = read_pci_config(num, slot, func, PCI_CLASS_REVISION); if (class == 0xffffffff) - break; - - switch (class >> 16) { + break; + + switch (class >> 16) { case PCI_CLASS_BRIDGE_HOST: case PCI_CLASS_BRIDGE_OTHER: /* needed? */ /* AGP bridge? */ - cap = find_cap(num,slot,func,PCI_CAP_ID_AGP); + cap = find_cap(num, slot, func, + PCI_CAP_ID_AGP); if (!cap) break; - *valid_agp = 1; - return read_agp(num,slot,func,cap,order); - } - + *valid_agp = 1; + return read_agp(num, slot, func, cap, + order); + } + /* No multi-function device? */ - type = read_pci_config_byte(num,slot,func, + type = read_pci_config_byte(num, slot, func, PCI_HEADER_TYPE); if (!(type & 0x80)) break; - } - } + } + } } - printk("No AGP bridge found\n"); + printk("No AGP bridge found\n"); + return 0; } void __init gart_iommu_hole_init(void) -{ - int fix, num; +{ u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0; u64 aper_base, last_aper_base = 0; - int valid_agp = 0; + int fix, num, valid_agp = 0; if (gart_iommu_aperture_disabled || !fix_aperture || !early_pci_allowed()) @@ -218,24 +228,24 @@ void __init gart_iommu_hole_init(void) printk(KERN_INFO "Checking aperture...\n"); fix = 0; - for (num = 24; num < 32; num++) { + for (num = 24; num < 32; num++) { if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) continue; iommu_detected = 1; gart_iommu_aperture = 1; - aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; - aper_size = (32 * 1024 * 1024) << aper_order; + aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; + aper_size = (32 * 1024 * 1024) << aper_order; aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff; - aper_base <<= 25; + aper_base <<= 25; - printk("CPU %d: aperture @ %Lx size %u MB\n", num-24, + printk("CPU %d: aperture @ %Lx size %u MB\n", num-24, aper_base, aper_size>>20); - + if (!aperture_valid(aper_base, aper_size)) { - fix = 1; - break; + fix = 1; + break; } if ((last_aper_order && aper_order != last_aper_order) || @@ -245,27 +255,28 @@ void __init gart_iommu_hole_init(void) } last_aper_order = aper_order; last_aper_base = aper_base; - } + } if (!fix && !fallback_aper_force) { if (last_aper_base) { unsigned long n = (32 * 1024 * 1024) << last_aper_order; + insert_aperture_resource((u32)last_aper_base, n); } - return; + return; } if (!fallback_aper_force) - aper_alloc = search_agp_bridge(&aper_order, &valid_agp); - - if (aper_alloc) { + aper_alloc = search_agp_bridge(&aper_order, &valid_agp); + + if (aper_alloc) { /* Got the aperture from the AGP bridge */ } else if (swiotlb && !valid_agp) { /* Do nothing */ } else if ((!no_iommu && end_pfn > MAX_DMA32_PFN) || force_iommu || valid_agp || - fallback_aper_force) { + fallback_aper_force) { printk("Your BIOS doesn't leave a aperture memory hole\n"); printk("Please enable the IOMMU option in the BIOS setup\n"); printk("This costs you %d MB of RAM\n", @@ -273,27 +284,32 @@ void __init gart_iommu_hole_init(void) aper_order = fallback_aper_order; aper_alloc = allocate_aperture(); - if (!aper_alloc) { - /* Could disable AGP and IOMMU here, but it's probably - not worth it. But the later users cannot deal with - bad apertures and turning on the aperture over memory - causes very strange problems, so it's better to - panic early. */ + if (!aper_alloc) { + /* + * Could disable AGP and IOMMU here, but it's + * probably not worth it. But the later users + * cannot deal with bad apertures and turning + * on the aperture over memory causes very + * strange problems, so it's better to panic + * early. + */ panic("Not enough memory for aperture"); } - } else { - return; - } + } else { + return; + } /* Fix up the north bridges */ - for (num = 24; num < 32; num++) { + for (num = 24; num < 32; num++) { if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) - continue; + continue; - /* Don't enable translation yet. That is done later. - Assume this BIOS didn't initialise the GART so - just overwrite all previous bits */ - write_pci_config(0, num, 3, 0x90, aper_order<<1); - write_pci_config(0, num, 3, 0x94, aper_alloc>>25); - } -} + /* + * Don't enable translation yet. That is done later. + * Assume this BIOS didn't initialise the GART so + * just overwrite all previous bits + */ + write_pci_config(0, num, 3, 0x90, aper_order<<1); + write_pci_config(0, num, 3, 0x94, aper_alloc>>25); + } +} From 31183ba8fd05b6ddc67ab4d726167cbc52e1b346 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:10 +0100 Subject: [PATCH 041/890] x86: clean up arch/x86/kernel/aperture_64.c printk()s clean up arch/x86/kernel/aperture_64.c printk()s. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/aperture_64.c | 42 ++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 250db0527f5d..52d2beac4556 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -66,14 +66,15 @@ static u32 __init allocate_aperture(void) */ p = __alloc_bootmem_nopanic(aper_size, aper_size, 0); if (!p || __pa(p)+aper_size > 0xffffffff) { - printk("Cannot allocate aperture memory hole (%p,%uK)\n", - p, aper_size>>10); + printk(KERN_ERR + "Cannot allocate aperture memory hole (%p,%uK)\n", + p, aper_size>>10); if (p) free_bootmem(__pa(p), aper_size); return 0; } - printk("Mapping aperture over %d KB of RAM @ %lx\n", - aper_size >> 10, __pa(p)); + printk(KERN_INFO "Mapping aperture over %d KB of RAM @ %lx\n", + aper_size >> 10, __pa(p)); insert_aperture_resource((u32)__pa(p), aper_size); return (u32)__pa(p); @@ -83,18 +84,20 @@ static int __init aperture_valid(u64 aper_base, u32 aper_size) { if (!aper_base) return 0; + if (aper_size < 64*1024*1024) { - printk("Aperture too small (%d MB)\n", aper_size>>20); + printk(KERN_ERR "Aperture too small (%d MB)\n", aper_size>>20); return 0; } if (aper_base + aper_size > 0x100000000UL) { - printk("Aperture beyond 4GB. Ignoring.\n"); + printk(KERN_ERR "Aperture beyond 4GB. Ignoring.\n"); return 0; } if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) { - printk("Aperture pointing to e820 RAM. Ignoring.\n"); + printk(KERN_ERR "Aperture pointing to e820 RAM. Ignoring.\n"); return 0; } + return 1; } @@ -133,10 +136,10 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) u32 aper_low, aper_hi; u64 aper; - printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func); + printk(KERN_INFO "AGP bridge at %02x:%02x:%02x\n", num, slot, func); apsizereg = read_pci_config_16(num, slot, func, cap + 0x14); if (apsizereg == 0xffffffff) { - printk("APSIZE in AGP bridge unreadable\n"); + printk(KERN_ERR "APSIZE in AGP bridge unreadable\n"); return 0; } @@ -153,8 +156,8 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) aper_hi = read_pci_config(num, slot, func, 0x14); aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); - printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", - aper, 32 << *order, apsizereg); + printk(KERN_INFO "Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", + aper, 32 << *order, apsizereg); if (!aperture_valid(aper, (32*1024*1024) << *order)) return 0; @@ -210,7 +213,7 @@ static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) } } } - printk("No AGP bridge found\n"); + printk(KERN_INFO "No AGP bridge found\n"); return 0; } @@ -240,8 +243,8 @@ void __init gart_iommu_hole_init(void) aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff; aper_base <<= 25; - printk("CPU %d: aperture @ %Lx size %u MB\n", num-24, - aper_base, aper_size>>20); + printk(KERN_INFO "CPU %d: aperture @ %Lx size %u MB\n", + num-24, aper_base, aper_size>>20); if (!aperture_valid(aper_base, aper_size)) { fix = 1; @@ -277,10 +280,13 @@ void __init gart_iommu_hole_init(void) force_iommu || valid_agp || fallback_aper_force) { - printk("Your BIOS doesn't leave a aperture memory hole\n"); - printk("Please enable the IOMMU option in the BIOS setup\n"); - printk("This costs you %d MB of RAM\n", - 32 << fallback_aper_order); + printk(KERN_ERR + "Your BIOS doesn't leave a aperture memory hole\n"); + printk(KERN_ERR + "Please enable the IOMMU option in the BIOS setup\n"); + printk(KERN_ERR + "This costs you %d MB of RAM\n", + 32 << fallback_aper_order); aper_order = fallback_aper_order; aper_alloc = allocate_aperture(); From a4ec1effce83796209a0258602b0cf50026d86f2 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:10 +0100 Subject: [PATCH 042/890] x86: mach-voyager, lindent lindent the mach-voyager files to get rid of more than 300 style errors: errors lines of code errors/KLOC arch/x86/mach-voyager/ [old] 409 3729 109.6 arch/x86/mach-voyager/ [new] 71 3678 19.3 Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/mach-voyager/setup.c | 32 +- arch/x86/mach-voyager/voyager_basic.c | 132 +++-- arch/x86/mach-voyager/voyager_cat.c | 601 +++++++++++----------- arch/x86/mach-voyager/voyager_smp.c | 672 +++++++++++-------------- arch/x86/mach-voyager/voyager_thread.c | 52 +- 5 files changed, 718 insertions(+), 771 deletions(-) diff --git a/arch/x86/mach-voyager/setup.c b/arch/x86/mach-voyager/setup.c index 3bef977cb29b..81257a861984 100644 --- a/arch/x86/mach-voyager/setup.c +++ b/arch/x86/mach-voyager/setup.c @@ -44,7 +44,7 @@ void __init trap_init_hook(void) { } -static struct irqaction irq0 = { +static struct irqaction irq0 = { .handler = timer_interrupt, .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL, .mask = CPU_MASK_NONE, @@ -59,44 +59,47 @@ void __init time_init_hook(void) /* Hook for machine specific memory setup. */ -char * __init machine_specific_memory_setup(void) +char *__init machine_specific_memory_setup(void) { char *who; who = "NOT VOYAGER"; - if(voyager_level == 5) { + if (voyager_level == 5) { __u32 addr, length; int i; who = "Voyager-SUS"; e820.nr_map = 0; - for(i=0; voyager_memory_detect(i, &addr, &length); i++) { + for (i = 0; voyager_memory_detect(i, &addr, &length); i++) { add_memory_region(addr, length, E820_RAM); } return who; - } else if(voyager_level == 4) { + } else if (voyager_level == 4) { __u32 tom; - __u16 catbase = inb(VOYAGER_SSPB_RELOCATION_PORT)<<8; + __u16 catbase = inb(VOYAGER_SSPB_RELOCATION_PORT) << 8; /* select the DINO config space */ outb(VOYAGER_DINO, VOYAGER_CAT_CONFIG_PORT); /* Read DINO top of memory register */ tom = ((inb(catbase + 0x4) & 0xf0) << 16) - + ((inb(catbase + 0x5) & 0x7f) << 24); + + ((inb(catbase + 0x5) & 0x7f) << 24); - if(inb(catbase) != VOYAGER_DINO) { - printk(KERN_ERR "Voyager: Failed to get DINO for L4, setting tom to EXT_MEM_K\n"); - tom = (boot_params.screen_info.ext_mem_k)<<10; + if (inb(catbase) != VOYAGER_DINO) { + printk(KERN_ERR + "Voyager: Failed to get DINO for L4, setting tom to EXT_MEM_K\n"); + tom = (boot_params.screen_info.ext_mem_k) << 10; } who = "Voyager-TOM"; add_memory_region(0, 0x9f000, E820_RAM); /* map from 1M to top of memory */ - add_memory_region(1*1024*1024, tom - 1*1024*1024, E820_RAM); + add_memory_region(1 * 1024 * 1024, tom - 1 * 1024 * 1024, + E820_RAM); /* FIXME: Should check the ASICs to see if I need to * take out the 8M window. Just do it at the moment * */ - add_memory_region(8*1024*1024, 8*1024*1024, E820_RESERVED); + add_memory_region(8 * 1024 * 1024, 8 * 1024 * 1024, + E820_RESERVED); return who; } @@ -114,8 +117,7 @@ char * __init machine_specific_memory_setup(void) unsigned long mem_size; /* compare results from other methods and take the greater */ - if (boot_params.alt_mem_k - < boot_params.screen_info.ext_mem_k) { + if (boot_params.alt_mem_k < boot_params.screen_info.ext_mem_k) { mem_size = boot_params.screen_info.ext_mem_k; who = "BIOS-88"; } else { @@ -126,6 +128,6 @@ char * __init machine_specific_memory_setup(void) e820.nr_map = 0; add_memory_region(0, LOWMEMSIZE(), E820_RAM); add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM); - } + } return who; } diff --git a/arch/x86/mach-voyager/voyager_basic.c b/arch/x86/mach-voyager/voyager_basic.c index 9b77b39b71a6..6a949e4edde8 100644 --- a/arch/x86/mach-voyager/voyager_basic.c +++ b/arch/x86/mach-voyager/voyager_basic.c @@ -35,7 +35,7 @@ /* * Power off function, if any */ -void (*pm_power_off)(void); +void (*pm_power_off) (void); EXPORT_SYMBOL(pm_power_off); int voyager_level = 0; @@ -43,39 +43,38 @@ int voyager_level = 0; struct voyager_SUS *voyager_SUS = NULL; #ifdef CONFIG_SMP -static void -voyager_dump(int dummy1, struct tty_struct *dummy3) +static void voyager_dump(int dummy1, struct tty_struct *dummy3) { /* get here via a sysrq */ voyager_smp_dump(); } static struct sysrq_key_op sysrq_voyager_dump_op = { - .handler = voyager_dump, - .help_msg = "Voyager", - .action_msg = "Dump Voyager Status", + .handler = voyager_dump, + .help_msg = "Voyager", + .action_msg = "Dump Voyager Status", }; #endif -void -voyager_detect(struct voyager_bios_info *bios) +void voyager_detect(struct voyager_bios_info *bios) { - if(bios->len != 0xff) { - int class = (bios->class_1 << 8) - | (bios->class_2 & 0xff); + if (bios->len != 0xff) { + int class = (bios->class_1 << 8) + | (bios->class_2 & 0xff); printk("Voyager System detected.\n" " Class %x, Revision %d.%d\n", class, bios->major, bios->minor); - if(class == VOYAGER_LEVEL4) + if (class == VOYAGER_LEVEL4) voyager_level = 4; - else if(class < VOYAGER_LEVEL5_AND_ABOVE) + else if (class < VOYAGER_LEVEL5_AND_ABOVE) voyager_level = 3; else voyager_level = 5; printk(" Architecture Level %d\n", voyager_level); - if(voyager_level < 4) - printk("\n**WARNING**: Voyager HAL only supports Levels 4 and 5 Architectures at the moment\n\n"); + if (voyager_level < 4) + printk + ("\n**WARNING**: Voyager HAL only supports Levels 4 and 5 Architectures at the moment\n\n"); /* install the power off handler */ pm_power_off = voyager_power_off; #ifdef CONFIG_SMP @@ -86,15 +85,13 @@ voyager_detect(struct voyager_bios_info *bios) } } -void -voyager_system_interrupt(int cpl, void *dev_id) +void voyager_system_interrupt(int cpl, void *dev_id) { printk("Voyager: detected system interrupt\n"); } /* Routine to read information from the extended CMOS area */ -__u8 -voyager_extended_cmos_read(__u16 addr) +__u8 voyager_extended_cmos_read(__u16 addr) { outb(addr & 0xff, 0x74); outb((addr >> 8) & 0xff, 0x75); @@ -108,12 +105,11 @@ voyager_extended_cmos_read(__u16 addr) typedef struct ClickMap { struct Entry { - __u32 Address; - __u32 Length; + __u32 Address; + __u32 Length; } Entry[CLICK_ENTRIES]; } ClickMap_t; - /* This routine is pretty much an awful hack to read the bios clickmap by * mapping it into page 0. There are usually three regions in the map: * Base Memory @@ -122,8 +118,7 @@ typedef struct ClickMap { * * Returns are 0 for failure and 1 for success on extracting region. */ -int __init -voyager_memory_detect(int region, __u32 *start, __u32 *length) +int __init voyager_memory_detect(int region, __u32 * start, __u32 * length) { int i; int retval = 0; @@ -132,13 +127,14 @@ voyager_memory_detect(int region, __u32 *start, __u32 *length) unsigned long map_addr; unsigned long old; - if(region >= CLICK_ENTRIES) { + if (region >= CLICK_ENTRIES) { printk("Voyager: Illegal ClickMap region %d\n", region); return 0; } - for(i = 0; i < sizeof(cmos); i++) - cmos[i] = voyager_extended_cmos_read(VOYAGER_MEMORY_CLICKMAP + i); + for (i = 0; i < sizeof(cmos); i++) + cmos[i] = + voyager_extended_cmos_read(VOYAGER_MEMORY_CLICKMAP + i); map_addr = *(unsigned long *)cmos; @@ -147,10 +143,10 @@ voyager_memory_detect(int region, __u32 *start, __u32 *length) pg0[0] = ((map_addr & PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT); local_flush_tlb(); /* now clear everything out but page 0 */ - map = (ClickMap_t *)(map_addr & (~PAGE_MASK)); + map = (ClickMap_t *) (map_addr & (~PAGE_MASK)); /* zero length is the end of the clickmap */ - if(map->Entry[region].Length != 0) { + if (map->Entry[region].Length != 0) { *length = map->Entry[region].Length * CLICK_SIZE; *start = map->Entry[region].Address; retval = 1; @@ -165,10 +161,9 @@ voyager_memory_detect(int region, __u32 *start, __u32 *length) /* voyager specific handling code for timer interrupts. Used to hand * off the timer tick to the SMP code, since the VIC doesn't have an * internal timer (The QIC does, but that's another story). */ -void -voyager_timer_interrupt(void) +void voyager_timer_interrupt(void) { - if((jiffies & 0x3ff) == 0) { + if ((jiffies & 0x3ff) == 0) { /* There seems to be something flaky in either * hardware or software that is resetting the timer 0 @@ -186,18 +181,20 @@ voyager_timer_interrupt(void) __u16 val; spin_lock(&i8253_lock); - + outb_p(0x00, 0x43); val = inb_p(0x40); val |= inb(0x40) << 8; spin_unlock(&i8253_lock); - if(val > LATCH) { - printk("\nVOYAGER: countdown timer value too high (%d), resetting\n\n", val); + if (val > LATCH) { + printk + ("\nVOYAGER: countdown timer value too high (%d), resetting\n\n", + val); spin_lock(&i8253_lock); - outb(0x34,0x43); - outb_p(LATCH & 0xff , 0x40); /* LSB */ - outb(LATCH >> 8 , 0x40); /* MSB */ + outb(0x34, 0x43); + outb_p(LATCH & 0xff, 0x40); /* LSB */ + outb(LATCH >> 8, 0x40); /* MSB */ spin_unlock(&i8253_lock); } } @@ -206,14 +203,13 @@ voyager_timer_interrupt(void) #endif } -void -voyager_power_off(void) +void voyager_power_off(void) { printk("VOYAGER Power Off\n"); - if(voyager_level == 5) { + if (voyager_level == 5) { voyager_cat_power_off(); - } else if(voyager_level == 4) { + } else if (voyager_level == 4) { /* This doesn't apparently work on most L4 machines, * but the specs say to do this to get automatic power * off. Unfortunately, if it doesn't power off the @@ -222,10 +218,8 @@ voyager_power_off(void) #if 0 int port; - /* enable the voyager Configuration Space */ - outb((inb(VOYAGER_MC_SETUP) & 0xf0) | 0x8, - VOYAGER_MC_SETUP); + outb((inb(VOYAGER_MC_SETUP) & 0xf0) | 0x8, VOYAGER_MC_SETUP); /* the port for the power off flag is an offset from the floating base */ port = (inb(VOYAGER_SSPB_RELOCATION_PORT) << 8) + 0x21; @@ -235,62 +229,57 @@ voyager_power_off(void) } /* and wait for it to happen */ local_irq_disable(); - for(;;) + for (;;) halt(); } /* copied from process.c */ -static inline void -kb_wait(void) +static inline void kb_wait(void) { int i; - for (i=0; i<0x10000; i++) + for (i = 0; i < 0x10000; i++) if ((inb_p(0x64) & 0x02) == 0) break; } -void -machine_shutdown(void) +void machine_shutdown(void) { /* Architecture specific shutdown needed before a kexec */ } -void -machine_restart(char *cmd) +void machine_restart(char *cmd) { printk("Voyager Warm Restart\n"); kb_wait(); - if(voyager_level == 5) { + if (voyager_level == 5) { /* write magic values to the RTC to inform system that * shutdown is beginning */ outb(0x8f, 0x70); - outb(0x5 , 0x71); - + outb(0x5, 0x71); + udelay(50); - outb(0xfe,0x64); /* pull reset low */ - } else if(voyager_level == 4) { - __u16 catbase = inb(VOYAGER_SSPB_RELOCATION_PORT)<<8; + outb(0xfe, 0x64); /* pull reset low */ + } else if (voyager_level == 4) { + __u16 catbase = inb(VOYAGER_SSPB_RELOCATION_PORT) << 8; __u8 basebd = inb(VOYAGER_MC_SETUP); - + outb(basebd | 0x08, VOYAGER_MC_SETUP); outb(0x02, catbase + 0x21); } local_irq_disable(); - for(;;) + for (;;) halt(); } -void -machine_emergency_restart(void) +void machine_emergency_restart(void) { /*for now, just hook this to a warm restart */ machine_restart(NULL); } -void -mca_nmi_hook(void) +void mca_nmi_hook(void) { __u8 dumpval __maybe_unused = inb(0xf823); __u8 swnmi __maybe_unused = inb(0xf813); @@ -301,8 +290,8 @@ mca_nmi_hook(void) /* clear swnmi */ outb(0xff, 0xf813); /* tell SUS to ignore dump */ - if(voyager_level == 5 && voyager_SUS != NULL) { - if(voyager_SUS->SUS_mbox == VOYAGER_DUMP_BUTTON_NMI) { + if (voyager_level == 5 && voyager_SUS != NULL) { + if (voyager_SUS->SUS_mbox == VOYAGER_DUMP_BUTTON_NMI) { voyager_SUS->kernel_mbox = VOYAGER_NO_COMMAND; voyager_SUS->kernel_flags |= VOYAGER_OS_IN_PROGRESS; udelay(1000); @@ -310,15 +299,14 @@ mca_nmi_hook(void) voyager_SUS->kernel_flags &= ~VOYAGER_OS_IN_PROGRESS; } } - printk(KERN_ERR "VOYAGER: Dump switch pressed, printing CPU%d tracebacks\n", smp_processor_id()); + printk(KERN_ERR + "VOYAGER: Dump switch pressed, printing CPU%d tracebacks\n", + smp_processor_id()); show_stack(NULL, NULL); show_state(); } - - -void -machine_halt(void) +void machine_halt(void) { /* treat a halt like a power off */ machine_power_off(); diff --git a/arch/x86/mach-voyager/voyager_cat.c b/arch/x86/mach-voyager/voyager_cat.c index 2132ca652df1..17a7904f75b1 100644 --- a/arch/x86/mach-voyager/voyager_cat.c +++ b/arch/x86/mach-voyager/voyager_cat.c @@ -39,34 +39,32 @@ #define CAT_DATA (sspb + 0xd) /* the internal cat functions */ -static void cat_pack(__u8 *msg, __u16 start_bit, __u8 *data, - __u16 num_bits); -static void cat_unpack(__u8 *msg, __u16 start_bit, __u8 *data, +static void cat_pack(__u8 * msg, __u16 start_bit, __u8 * data, __u16 num_bits); +static void cat_unpack(__u8 * msg, __u16 start_bit, __u8 * data, __u16 num_bits); -static void cat_build_header(__u8 *header, const __u16 len, +static void cat_build_header(__u8 * header, const __u16 len, const __u16 smallest_reg_bits, const __u16 longest_reg_bits); -static int cat_sendinst(voyager_module_t *modp, voyager_asic_t *asicp, +static int cat_sendinst(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg, __u8 op); -static int cat_getdata(voyager_module_t *modp, voyager_asic_t *asicp, - __u8 reg, __u8 *value); -static int cat_shiftout(__u8 *data, __u16 data_bytes, __u16 header_bytes, +static int cat_getdata(voyager_module_t * modp, voyager_asic_t * asicp, + __u8 reg, __u8 * value); +static int cat_shiftout(__u8 * data, __u16 data_bytes, __u16 header_bytes, __u8 pad_bits); -static int cat_write(voyager_module_t *modp, voyager_asic_t *asicp, __u8 reg, +static int cat_write(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg, __u8 value); -static int cat_read(voyager_module_t *modp, voyager_asic_t *asicp, __u8 reg, - __u8 *value); -static int cat_subread(voyager_module_t *modp, voyager_asic_t *asicp, +static int cat_read(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg, + __u8 * value); +static int cat_subread(voyager_module_t * modp, voyager_asic_t * asicp, __u16 offset, __u16 len, void *buf); -static int cat_senddata(voyager_module_t *modp, voyager_asic_t *asicp, +static int cat_senddata(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg, __u8 value); -static int cat_disconnect(voyager_module_t *modp, voyager_asic_t *asicp); -static int cat_connect(voyager_module_t *modp, voyager_asic_t *asicp); +static int cat_disconnect(voyager_module_t * modp, voyager_asic_t * asicp); +static int cat_connect(voyager_module_t * modp, voyager_asic_t * asicp); -static inline const char * -cat_module_name(int module_id) +static inline const char *cat_module_name(int module_id) { - switch(module_id) { + switch (module_id) { case 0x10: return "Processor Slot 0"; case 0x11: @@ -105,14 +103,14 @@ voyager_module_t *voyager_cat_list; /* the I/O port assignments for the VIC and QIC */ static struct resource vic_res = { - .name = "Voyager Interrupt Controller", - .start = 0xFC00, - .end = 0xFC6F + .name = "Voyager Interrupt Controller", + .start = 0xFC00, + .end = 0xFC6F }; static struct resource qic_res = { - .name = "Quad Interrupt Controller", - .start = 0xFC70, - .end = 0xFCFF + .name = "Quad Interrupt Controller", + .start = 0xFC70, + .end = 0xFCFF }; /* This function is used to pack a data bit stream inside a message. @@ -120,7 +118,7 @@ static struct resource qic_res = { * Note: This function assumes that any unused bit in the data stream * is set to zero so that the ors will work correctly */ static void -cat_pack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits) +cat_pack(__u8 * msg, const __u16 start_bit, __u8 * data, const __u16 num_bits) { /* compute initial shift needed */ const __u16 offset = start_bit % BITS_PER_BYTE; @@ -130,7 +128,7 @@ cat_pack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits) int i; /* adjust if we have more than a byte of residue */ - if(residue >= BITS_PER_BYTE) { + if (residue >= BITS_PER_BYTE) { residue -= BITS_PER_BYTE; len++; } @@ -138,24 +136,25 @@ cat_pack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits) /* clear out the bits. We assume here that if len==0 then * residue >= offset. This is always true for the catbus * operations */ - msg[byte] &= 0xff << (BITS_PER_BYTE - offset); + msg[byte] &= 0xff << (BITS_PER_BYTE - offset); msg[byte++] |= data[0] >> offset; - if(len == 0) + if (len == 0) return; - for(i = 1; i < len; i++) - msg[byte++] = (data[i-1] << (BITS_PER_BYTE - offset)) - | (data[i] >> offset); - if(residue != 0) { + for (i = 1; i < len; i++) + msg[byte++] = (data[i - 1] << (BITS_PER_BYTE - offset)) + | (data[i] >> offset); + if (residue != 0) { __u8 mask = 0xff >> residue; - __u8 last_byte = data[i-1] << (BITS_PER_BYTE - offset) - | (data[i] >> offset); - + __u8 last_byte = data[i - 1] << (BITS_PER_BYTE - offset) + | (data[i] >> offset); + last_byte &= ~mask; msg[byte] &= mask; msg[byte] |= last_byte; } return; } + /* unpack the data again (same arguments as cat_pack()). data buffer * must be zero populated. * @@ -163,7 +162,7 @@ cat_pack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits) * data (starting at bit 0 in data). */ static void -cat_unpack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits) +cat_unpack(__u8 * msg, const __u16 start_bit, __u8 * data, const __u16 num_bits) { /* compute initial shift needed */ const __u16 offset = start_bit % BITS_PER_BYTE; @@ -172,97 +171,97 @@ cat_unpack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits) __u16 byte = start_bit / BITS_PER_BYTE; int i; - if(last_bits != 0) + if (last_bits != 0) len++; /* special case: want < 8 bits from msg and we can get it from * a single byte of the msg */ - if(len == 0 && BITS_PER_BYTE - offset >= num_bits) { + if (len == 0 && BITS_PER_BYTE - offset >= num_bits) { data[0] = msg[byte] << offset; data[0] &= 0xff >> (BITS_PER_BYTE - num_bits); return; } - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { /* this annoying if has to be done just in case a read of * msg one beyond the array causes a panic */ - if(offset != 0) { + if (offset != 0) { data[i] = msg[byte++] << offset; data[i] |= msg[byte] >> (BITS_PER_BYTE - offset); - } - else { + } else { data[i] = msg[byte++]; } } /* do we need to truncate the final byte */ - if(last_bits != 0) { - data[i-1] &= 0xff << (BITS_PER_BYTE - last_bits); + if (last_bits != 0) { + data[i - 1] &= 0xff << (BITS_PER_BYTE - last_bits); } return; } static void -cat_build_header(__u8 *header, const __u16 len, const __u16 smallest_reg_bits, +cat_build_header(__u8 * header, const __u16 len, const __u16 smallest_reg_bits, const __u16 longest_reg_bits) { int i; __u16 start_bit = (smallest_reg_bits - 1) % BITS_PER_BYTE; __u8 *last_byte = &header[len - 1]; - if(start_bit == 0) + if (start_bit == 0) start_bit = 1; /* must have at least one bit in the hdr */ - - for(i=0; i < len; i++) + + for (i = 0; i < len; i++) header[i] = 0; - for(i = start_bit; i > 0; i--) + for (i = start_bit; i > 0; i--) *last_byte = ((*last_byte) << 1) + 1; } static int -cat_sendinst(voyager_module_t *modp, voyager_asic_t *asicp, __u8 reg, __u8 op) +cat_sendinst(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg, __u8 op) { __u8 parity, inst, inst_buf[4] = { 0 }; __u8 iseq[VOYAGER_MAX_SCAN_PATH], hseq[VOYAGER_MAX_REG_SIZE]; __u16 ibytes, hbytes, padbits; int i; - + /* * Parity is the parity of the register number + 1 (READ_REGISTER * and WRITE_REGISTER always add '1' to the number of bits == 1) */ - parity = (__u8)(1 + (reg & 0x01) + - ((__u8)(reg & 0x02) >> 1) + - ((__u8)(reg & 0x04) >> 2) + - ((__u8)(reg & 0x08) >> 3)) % 2; + parity = (__u8) (1 + (reg & 0x01) + + ((__u8) (reg & 0x02) >> 1) + + ((__u8) (reg & 0x04) >> 2) + + ((__u8) (reg & 0x08) >> 3)) % 2; inst = ((parity << 7) | (reg << 2) | op); outb(VOYAGER_CAT_IRCYC, CAT_CMD); - if(!modp->scan_path_connected) { - if(asicp->asic_id != VOYAGER_CAT_ID) { - printk("**WARNING***: cat_sendinst has disconnected scan path not to CAT asic\n"); + if (!modp->scan_path_connected) { + if (asicp->asic_id != VOYAGER_CAT_ID) { + printk + ("**WARNING***: cat_sendinst has disconnected scan path not to CAT asic\n"); return 1; } outb(VOYAGER_CAT_HEADER, CAT_DATA); outb(inst, CAT_DATA); - if(inb(CAT_DATA) != VOYAGER_CAT_HEADER) { + if (inb(CAT_DATA) != VOYAGER_CAT_HEADER) { CDEBUG(("VOYAGER CAT: cat_sendinst failed to get CAT_HEADER\n")); return 1; } return 0; } ibytes = modp->inst_bits / BITS_PER_BYTE; - if((padbits = modp->inst_bits % BITS_PER_BYTE) != 0) { + if ((padbits = modp->inst_bits % BITS_PER_BYTE) != 0) { padbits = BITS_PER_BYTE - padbits; ibytes++; } hbytes = modp->largest_reg / BITS_PER_BYTE; - if(modp->largest_reg % BITS_PER_BYTE) + if (modp->largest_reg % BITS_PER_BYTE) hbytes++; CDEBUG(("cat_sendinst: ibytes=%d, hbytes=%d\n", ibytes, hbytes)); /* initialise the instruction sequence to 0xff */ - for(i=0; i < ibytes + hbytes; i++) + for (i = 0; i < ibytes + hbytes; i++) iseq[i] = 0xff; cat_build_header(hseq, hbytes, modp->smallest_reg, modp->largest_reg); cat_pack(iseq, modp->inst_bits, hseq, hbytes * BITS_PER_BYTE); @@ -271,11 +270,11 @@ cat_sendinst(voyager_module_t *modp, voyager_asic_t *asicp, __u8 reg, __u8 op) cat_pack(iseq, asicp->bit_location, inst_buf, asicp->ireg_length); #ifdef VOYAGER_CAT_DEBUG printk("ins = 0x%x, iseq: ", inst); - for(i=0; i< ibytes + hbytes; i++) + for (i = 0; i < ibytes + hbytes; i++) printk("0x%x ", iseq[i]); printk("\n"); #endif - if(cat_shiftout(iseq, ibytes, hbytes, padbits)) { + if (cat_shiftout(iseq, ibytes, hbytes, padbits)) { CDEBUG(("VOYAGER CAT: cat_sendinst: cat_shiftout failed\n")); return 1; } @@ -284,72 +283,74 @@ cat_sendinst(voyager_module_t *modp, voyager_asic_t *asicp, __u8 reg, __u8 op) } static int -cat_getdata(voyager_module_t *modp, voyager_asic_t *asicp, __u8 reg, - __u8 *value) +cat_getdata(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg, + __u8 * value) { - if(!modp->scan_path_connected) { - if(asicp->asic_id != VOYAGER_CAT_ID) { + if (!modp->scan_path_connected) { + if (asicp->asic_id != VOYAGER_CAT_ID) { CDEBUG(("VOYAGER CAT: ERROR: cat_getdata to CAT asic with scan path connected\n")); return 1; } - if(reg > VOYAGER_SUBADDRHI) + if (reg > VOYAGER_SUBADDRHI) outb(VOYAGER_CAT_RUN, CAT_CMD); outb(VOYAGER_CAT_DRCYC, CAT_CMD); outb(VOYAGER_CAT_HEADER, CAT_DATA); *value = inb(CAT_DATA); outb(0xAA, CAT_DATA); - if(inb(CAT_DATA) != VOYAGER_CAT_HEADER) { + if (inb(CAT_DATA) != VOYAGER_CAT_HEADER) { CDEBUG(("cat_getdata: failed to get VOYAGER_CAT_HEADER\n")); return 1; } return 0; - } - else { - __u16 sbits = modp->num_asics -1 + asicp->ireg_length; + } else { + __u16 sbits = modp->num_asics - 1 + asicp->ireg_length; __u16 sbytes = sbits / BITS_PER_BYTE; __u16 tbytes; - __u8 string[VOYAGER_MAX_SCAN_PATH], trailer[VOYAGER_MAX_REG_SIZE]; + __u8 string[VOYAGER_MAX_SCAN_PATH], + trailer[VOYAGER_MAX_REG_SIZE]; __u8 padbits; int i; - + outb(VOYAGER_CAT_DRCYC, CAT_CMD); - if((padbits = sbits % BITS_PER_BYTE) != 0) { + if ((padbits = sbits % BITS_PER_BYTE) != 0) { padbits = BITS_PER_BYTE - padbits; sbytes++; } tbytes = asicp->ireg_length / BITS_PER_BYTE; - if(asicp->ireg_length % BITS_PER_BYTE) + if (asicp->ireg_length % BITS_PER_BYTE) tbytes++; CDEBUG(("cat_getdata: tbytes = %d, sbytes = %d, padbits = %d\n", - tbytes, sbytes, padbits)); + tbytes, sbytes, padbits)); cat_build_header(trailer, tbytes, 1, asicp->ireg_length); - - for(i = tbytes - 1; i >= 0; i--) { + for (i = tbytes - 1; i >= 0; i--) { outb(trailer[i], CAT_DATA); string[sbytes + i] = inb(CAT_DATA); } - for(i = sbytes - 1; i >= 0; i--) { + for (i = sbytes - 1; i >= 0; i--) { outb(0xaa, CAT_DATA); string[i] = inb(CAT_DATA); } *value = 0; - cat_unpack(string, padbits + (tbytes * BITS_PER_BYTE) + asicp->asic_location, value, asicp->ireg_length); + cat_unpack(string, + padbits + (tbytes * BITS_PER_BYTE) + + asicp->asic_location, value, asicp->ireg_length); #ifdef VOYAGER_CAT_DEBUG printk("value=0x%x, string: ", *value); - for(i=0; i< tbytes+sbytes; i++) + for (i = 0; i < tbytes + sbytes; i++) printk("0x%x ", string[i]); printk("\n"); #endif - + /* sanity check the rest of the return */ - for(i=0; i < tbytes; i++) { + for (i = 0; i < tbytes; i++) { __u8 input = 0; - cat_unpack(string, padbits + (i * BITS_PER_BYTE), &input, BITS_PER_BYTE); - if(trailer[i] != input) { + cat_unpack(string, padbits + (i * BITS_PER_BYTE), + &input, BITS_PER_BYTE); + if (trailer[i] != input) { CDEBUG(("cat_getdata: failed to sanity check rest of ret(%d) 0x%x != 0x%x\n", i, input, trailer[i])); return 1; } @@ -360,14 +361,14 @@ cat_getdata(voyager_module_t *modp, voyager_asic_t *asicp, __u8 reg, } static int -cat_shiftout(__u8 *data, __u16 data_bytes, __u16 header_bytes, __u8 pad_bits) +cat_shiftout(__u8 * data, __u16 data_bytes, __u16 header_bytes, __u8 pad_bits) { int i; - - for(i = data_bytes + header_bytes - 1; i >= header_bytes; i--) + + for (i = data_bytes + header_bytes - 1; i >= header_bytes; i--) outb(data[i], CAT_DATA); - for(i = header_bytes - 1; i >= 0; i--) { + for (i = header_bytes - 1; i >= 0; i--) { __u8 header = 0; __u8 input; @@ -376,7 +377,7 @@ cat_shiftout(__u8 *data, __u16 data_bytes, __u16 header_bytes, __u8 pad_bits) CDEBUG(("cat_shiftout: returned 0x%x\n", input)); cat_unpack(data, ((data_bytes + i) * BITS_PER_BYTE) - pad_bits, &header, BITS_PER_BYTE); - if(input != header) { + if (input != header) { CDEBUG(("VOYAGER CAT: cat_shiftout failed to return header 0x%x != 0x%x\n", input, header)); return 1; } @@ -385,57 +386,57 @@ cat_shiftout(__u8 *data, __u16 data_bytes, __u16 header_bytes, __u8 pad_bits) } static int -cat_senddata(voyager_module_t *modp, voyager_asic_t *asicp, +cat_senddata(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg, __u8 value) { outb(VOYAGER_CAT_DRCYC, CAT_CMD); - if(!modp->scan_path_connected) { - if(asicp->asic_id != VOYAGER_CAT_ID) { + if (!modp->scan_path_connected) { + if (asicp->asic_id != VOYAGER_CAT_ID) { CDEBUG(("VOYAGER CAT: ERROR: scan path disconnected when asic != CAT\n")); return 1; } outb(VOYAGER_CAT_HEADER, CAT_DATA); outb(value, CAT_DATA); - if(inb(CAT_DATA) != VOYAGER_CAT_HEADER) { + if (inb(CAT_DATA) != VOYAGER_CAT_HEADER) { CDEBUG(("cat_senddata: failed to get correct header response to sent data\n")); return 1; } - if(reg > VOYAGER_SUBADDRHI) { + if (reg > VOYAGER_SUBADDRHI) { outb(VOYAGER_CAT_RUN, CAT_CMD); outb(VOYAGER_CAT_END, CAT_CMD); outb(VOYAGER_CAT_RUN, CAT_CMD); } - + return 0; - } - else { + } else { __u16 hbytes = asicp->ireg_length / BITS_PER_BYTE; - __u16 dbytes = (modp->num_asics - 1 + asicp->ireg_length)/BITS_PER_BYTE; - __u8 padbits, dseq[VOYAGER_MAX_SCAN_PATH], - hseq[VOYAGER_MAX_REG_SIZE]; + __u16 dbytes = + (modp->num_asics - 1 + asicp->ireg_length) / BITS_PER_BYTE; + __u8 padbits, dseq[VOYAGER_MAX_SCAN_PATH], + hseq[VOYAGER_MAX_REG_SIZE]; int i; - if((padbits = (modp->num_asics - 1 - + asicp->ireg_length) % BITS_PER_BYTE) != 0) { + if ((padbits = (modp->num_asics - 1 + + asicp->ireg_length) % BITS_PER_BYTE) != 0) { padbits = BITS_PER_BYTE - padbits; dbytes++; } - if(asicp->ireg_length % BITS_PER_BYTE) + if (asicp->ireg_length % BITS_PER_BYTE) hbytes++; - + cat_build_header(hseq, hbytes, 1, asicp->ireg_length); - - for(i = 0; i < dbytes + hbytes; i++) + + for (i = 0; i < dbytes + hbytes; i++) dseq[i] = 0xff; CDEBUG(("cat_senddata: dbytes=%d, hbytes=%d, padbits=%d\n", dbytes, hbytes, padbits)); cat_pack(dseq, modp->num_asics - 1 + asicp->ireg_length, hseq, hbytes * BITS_PER_BYTE); - cat_pack(dseq, asicp->asic_location, &value, + cat_pack(dseq, asicp->asic_location, &value, asicp->ireg_length); #ifdef VOYAGER_CAT_DEBUG printk("dseq "); - for(i=0; i 1) { + if (len > 1) { /* set auto increment */ __u8 newval; - - if(cat_read(modp, asicp, VOYAGER_AUTO_INC_REG, &val)) { + + if (cat_read(modp, asicp, VOYAGER_AUTO_INC_REG, &val)) { CDEBUG(("cat_subaddrsetup: read of VOYAGER_AUTO_INC_REG failed\n")); return 1; } - CDEBUG(("cat_subaddrsetup: VOYAGER_AUTO_INC_REG = 0x%x\n", val)); + CDEBUG(("cat_subaddrsetup: VOYAGER_AUTO_INC_REG = 0x%x\n", + val)); newval = val | VOYAGER_AUTO_INC; - if(newval != val) { - if(cat_write(modp, asicp, VOYAGER_AUTO_INC_REG, val)) { + if (newval != val) { + if (cat_write(modp, asicp, VOYAGER_AUTO_INC_REG, val)) { CDEBUG(("cat_subaddrsetup: write to VOYAGER_AUTO_INC_REG failed\n")); return 1; } } } - if(cat_write(modp, asicp, VOYAGER_SUBADDRLO, (__u8)(offset &0xff))) { + if (cat_write(modp, asicp, VOYAGER_SUBADDRLO, (__u8) (offset & 0xff))) { CDEBUG(("cat_subaddrsetup: write to SUBADDRLO failed\n")); return 1; } - if(asicp->subaddr > VOYAGER_SUBADDR_LO) { - if(cat_write(modp, asicp, VOYAGER_SUBADDRHI, (__u8)(offset >> 8))) { + if (asicp->subaddr > VOYAGER_SUBADDR_LO) { + if (cat_write + (modp, asicp, VOYAGER_SUBADDRHI, (__u8) (offset >> 8))) { CDEBUG(("cat_subaddrsetup: write to SUBADDRHI failed\n")); return 1; } cat_read(modp, asicp, VOYAGER_SUBADDRHI, &val); - CDEBUG(("cat_subaddrsetup: offset = %d, hi = %d\n", offset, val)); + CDEBUG(("cat_subaddrsetup: offset = %d, hi = %d\n", offset, + val)); } cat_read(modp, asicp, VOYAGER_SUBADDRLO, &val); CDEBUG(("cat_subaddrsetup: offset = %d, lo = %d\n", offset, val)); return 0; } - + static int -cat_subwrite(voyager_module_t *modp, voyager_asic_t *asicp, __u16 offset, - __u16 len, void *buf) +cat_subwrite(voyager_module_t * modp, voyager_asic_t * asicp, __u16 offset, + __u16 len, void *buf) { int i, retval; /* FIXME: need special actions for VOYAGER_CAT_ID here */ - if(asicp->asic_id == VOYAGER_CAT_ID) { + if (asicp->asic_id == VOYAGER_CAT_ID) { CDEBUG(("cat_subwrite: ATTEMPT TO WRITE TO CAT ASIC\n")); /* FIXME -- This is supposed to be handled better * There is a problem writing to the cat asic in the * PSI. The 30us delay seems to work, though */ udelay(30); } - - if((retval = cat_subaddrsetup(modp, asicp, offset, len)) != 0) { + + if ((retval = cat_subaddrsetup(modp, asicp, offset, len)) != 0) { printk("cat_subwrite: cat_subaddrsetup FAILED\n"); return retval; } - - if(cat_sendinst(modp, asicp, VOYAGER_SUBADDRDATA, VOYAGER_WRITE_CONFIG)) { + + if (cat_sendinst + (modp, asicp, VOYAGER_SUBADDRDATA, VOYAGER_WRITE_CONFIG)) { printk("cat_subwrite: cat_sendinst FAILED\n"); return 1; } - for(i = 0; i < len; i++) { - if(cat_senddata(modp, asicp, 0xFF, ((__u8 *)buf)[i])) { - printk("cat_subwrite: cat_sendata element at %d FAILED\n", i); + for (i = 0; i < len; i++) { + if (cat_senddata(modp, asicp, 0xFF, ((__u8 *) buf)[i])) { + printk + ("cat_subwrite: cat_sendata element at %d FAILED\n", + i); return 1; } } return 0; } static int -cat_subread(voyager_module_t *modp, voyager_asic_t *asicp, __u16 offset, +cat_subread(voyager_module_t * modp, voyager_asic_t * asicp, __u16 offset, __u16 len, void *buf) { int i, retval; - if((retval = cat_subaddrsetup(modp, asicp, offset, len)) != 0) { + if ((retval = cat_subaddrsetup(modp, asicp, offset, len)) != 0) { CDEBUG(("cat_subread: cat_subaddrsetup FAILED\n")); return retval; } - if(cat_sendinst(modp, asicp, VOYAGER_SUBADDRDATA, VOYAGER_READ_CONFIG)) { + if (cat_sendinst(modp, asicp, VOYAGER_SUBADDRDATA, VOYAGER_READ_CONFIG)) { CDEBUG(("cat_subread: cat_sendinst failed\n")); return 1; } - for(i = 0; i < len; i++) { - if(cat_getdata(modp, asicp, 0xFF, - &((__u8 *)buf)[i])) { - CDEBUG(("cat_subread: cat_getdata element %d failed\n", i)); + for (i = 0; i < len; i++) { + if (cat_getdata(modp, asicp, 0xFF, &((__u8 *) buf)[i])) { + CDEBUG(("cat_subread: cat_getdata element %d failed\n", + i)); return 1; } } return 0; } - /* buffer for storing EPROM data read in during initialisation */ static __initdata __u8 eprom_buf[0xFFFF]; static voyager_module_t *voyager_initial_module; @@ -568,8 +573,7 @@ static voyager_module_t *voyager_initial_module; * boot cpu *after* all memory initialisation has been done (so we can * use kmalloc) but before smp initialisation, so we can probe the SMP * configuration and pick up necessary information. */ -void __init -voyager_cat_init(void) +void __init voyager_cat_init(void) { voyager_module_t **modpp = &voyager_initial_module; voyager_asic_t **asicpp; @@ -578,27 +582,29 @@ voyager_cat_init(void) unsigned long qic_addr = 0; __u8 qabc_data[0x20]; __u8 num_submodules, val; - voyager_eprom_hdr_t *eprom_hdr = (voyager_eprom_hdr_t *)&eprom_buf[0]; - + voyager_eprom_hdr_t *eprom_hdr = (voyager_eprom_hdr_t *) & eprom_buf[0]; + __u8 cmos[4]; unsigned long addr; - + /* initiallise the SUS mailbox */ - for(i=0; iSUS_version); voyager_SUS->kernel_version = VOYAGER_MAILBOX_VERSION; @@ -609,8 +615,6 @@ voyager_cat_init(void) voyager_extended_vic_processors = 0; voyager_quad_processors = 0; - - printk("VOYAGER: beginning CAT bus probe\n"); /* set up the SuperSet Port Block which tells us where the * CAT communication port is */ @@ -618,14 +622,14 @@ voyager_cat_init(void) VDEBUG(("VOYAGER DEBUG: sspb = 0x%x\n", sspb)); /* now find out if were 8 slot or normal */ - if((inb(VIC_PROC_WHO_AM_I) & EIGHT_SLOT_IDENTIFIER) - == EIGHT_SLOT_IDENTIFIER) { + if ((inb(VIC_PROC_WHO_AM_I) & EIGHT_SLOT_IDENTIFIER) + == EIGHT_SLOT_IDENTIFIER) { voyager_8slot = 1; - printk(KERN_NOTICE "Voyager: Eight slot 51xx configuration detected\n"); + printk(KERN_NOTICE + "Voyager: Eight slot 51xx configuration detected\n"); } - for(i = VOYAGER_MIN_MODULE; - i <= VOYAGER_MAX_MODULE; i++) { + for (i = VOYAGER_MIN_MODULE; i <= VOYAGER_MAX_MODULE; i++) { __u8 input; int asic; __u16 eprom_size; @@ -643,21 +647,21 @@ voyager_cat_init(void) outb(0xAA, CAT_DATA); input = inb(CAT_DATA); outb(VOYAGER_CAT_END, CAT_CMD); - if(input != VOYAGER_CAT_HEADER) { + if (input != VOYAGER_CAT_HEADER) { continue; } CDEBUG(("VOYAGER DEBUG: found module id 0x%x, %s\n", i, cat_module_name(i))); - *modpp = kmalloc(sizeof(voyager_module_t), GFP_KERNEL); /*&voyager_module_storage[cat_count++];*/ - if(*modpp == NULL) { + *modpp = kmalloc(sizeof(voyager_module_t), GFP_KERNEL); /*&voyager_module_storage[cat_count++]; */ + if (*modpp == NULL) { printk("**WARNING** kmalloc failure in cat_init\n"); continue; } memset(*modpp, 0, sizeof(voyager_module_t)); /* need temporary asic for cat_subread. It will be * filled in correctly later */ - (*modpp)->asic = kmalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count];*/ - if((*modpp)->asic == NULL) { + (*modpp)->asic = kmalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count]; */ + if ((*modpp)->asic == NULL) { printk("**WARNING** kmalloc failure in cat_init\n"); continue; } @@ -666,47 +670,52 @@ voyager_cat_init(void) (*modpp)->asic->subaddr = VOYAGER_SUBADDR_HI; (*modpp)->module_addr = i; (*modpp)->scan_path_connected = 0; - if(i == VOYAGER_PSI) { + if (i == VOYAGER_PSI) { /* Exception leg for modules with no EEPROM */ printk("Module \"%s\"\n", cat_module_name(i)); continue; } - + CDEBUG(("cat_init: Reading eeprom for module 0x%x at offset %d\n", i, VOYAGER_XSUM_END_OFFSET)); outb(VOYAGER_CAT_RUN, CAT_CMD); cat_disconnect(*modpp, (*modpp)->asic); - if(cat_subread(*modpp, (*modpp)->asic, - VOYAGER_XSUM_END_OFFSET, sizeof(eprom_size), - &eprom_size)) { - printk("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n", i); + if (cat_subread(*modpp, (*modpp)->asic, + VOYAGER_XSUM_END_OFFSET, sizeof(eprom_size), + &eprom_size)) { + printk + ("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n", + i); outb(VOYAGER_CAT_END, CAT_CMD); continue; } - if(eprom_size > sizeof(eprom_buf)) { - printk("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x. Need %d\n", i, eprom_size); + if (eprom_size > sizeof(eprom_buf)) { + printk + ("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x. Need %d\n", + i, eprom_size); outb(VOYAGER_CAT_END, CAT_CMD); continue; } outb(VOYAGER_CAT_END, CAT_CMD); outb(VOYAGER_CAT_RUN, CAT_CMD); - CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i, eprom_size)); - if(cat_subread(*modpp, (*modpp)->asic, 0, - eprom_size, eprom_buf)) { + CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i, + eprom_size)); + if (cat_subread + (*modpp, (*modpp)->asic, 0, eprom_size, eprom_buf)) { outb(VOYAGER_CAT_END, CAT_CMD); continue; } outb(VOYAGER_CAT_END, CAT_CMD); printk("Module \"%s\", version 0x%x, tracer 0x%x, asics %d\n", cat_module_name(i), eprom_hdr->version_id, - *((__u32 *)eprom_hdr->tracer), eprom_hdr->num_asics); + *((__u32 *) eprom_hdr->tracer), eprom_hdr->num_asics); (*modpp)->ee_size = eprom_hdr->ee_size; (*modpp)->num_asics = eprom_hdr->num_asics; asicpp = &((*modpp)->asic); sp_offset = eprom_hdr->scan_path_offset; /* All we really care about are the Quad cards. We - * identify them because they are in a processor slot - * and have only four asics */ - if((i < 0x10 || (i>=0x14 && i < 0x1c) || i>0x1f)) { + * identify them because they are in a processor slot + * and have only four asics */ + if ((i < 0x10 || (i >= 0x14 && i < 0x1c) || i > 0x1f)) { modpp = &((*modpp)->next); continue; } @@ -717,16 +726,17 @@ voyager_cat_init(void) &num_submodules); /* lowest two bits, active low */ num_submodules = ~(0xfc | num_submodules); - CDEBUG(("VOYAGER CAT: %d submodules present\n", num_submodules)); - if(num_submodules == 0) { + CDEBUG(("VOYAGER CAT: %d submodules present\n", + num_submodules)); + if (num_submodules == 0) { /* fill in the dyadic extended processors */ __u8 cpu = i & 0x07; printk("Module \"%s\": Dyadic Processor Card\n", cat_module_name(i)); - voyager_extended_vic_processors |= (1<asic, VOYAGER_SUBMODSELECT, val); outb(VOYAGER_CAT_END, CAT_CMD); - CDEBUG(("cat_init: Reading eeprom for module 0x%x at offset %d\n", i, VOYAGER_XSUM_END_OFFSET)); outb(VOYAGER_CAT_RUN, CAT_CMD); cat_disconnect(*modpp, (*modpp)->asic); - if(cat_subread(*modpp, (*modpp)->asic, - VOYAGER_XSUM_END_OFFSET, sizeof(eprom_size), - &eprom_size)) { - printk("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n", i); + if (cat_subread(*modpp, (*modpp)->asic, + VOYAGER_XSUM_END_OFFSET, sizeof(eprom_size), + &eprom_size)) { + printk + ("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n", + i); outb(VOYAGER_CAT_END, CAT_CMD); continue; } - if(eprom_size > sizeof(eprom_buf)) { - printk("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x. Need %d\n", i, eprom_size); + if (eprom_size > sizeof(eprom_buf)) { + printk + ("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x. Need %d\n", + i, eprom_size); outb(VOYAGER_CAT_END, CAT_CMD); continue; } outb(VOYAGER_CAT_END, CAT_CMD); outb(VOYAGER_CAT_RUN, CAT_CMD); - CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i, eprom_size)); - if(cat_subread(*modpp, (*modpp)->asic, 0, - eprom_size, eprom_buf)) { + CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i, + eprom_size)); + if (cat_subread + (*modpp, (*modpp)->asic, 0, eprom_size, eprom_buf)) { outb(VOYAGER_CAT_END, CAT_CMD); continue; } @@ -773,30 +787,35 @@ voyager_cat_init(void) sp_offset = eprom_hdr->scan_path_offset; /* get rid of the dummy CAT asic and read the real one */ kfree((*modpp)->asic); - for(asic=0; asic < (*modpp)->num_asics; asic++) { + for (asic = 0; asic < (*modpp)->num_asics; asic++) { int j; - voyager_asic_t *asicp = *asicpp - = kzalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count++];*/ + voyager_asic_t *asicp = *asicpp = kzalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count++]; */ voyager_sp_table_t *sp_table; voyager_at_t *asic_table; voyager_jtt_t *jtag_table; - if(asicp == NULL) { - printk("**WARNING** kmalloc failure in cat_init\n"); + if (asicp == NULL) { + printk + ("**WARNING** kmalloc failure in cat_init\n"); continue; } asicpp = &(asicp->next); asicp->asic_location = asic; - sp_table = (voyager_sp_table_t *)(eprom_buf + sp_offset); + sp_table = + (voyager_sp_table_t *) (eprom_buf + sp_offset); asicp->asic_id = sp_table->asic_id; - asic_table = (voyager_at_t *)(eprom_buf + sp_table->asic_data_offset); - for(j=0; j<4; j++) + asic_table = + (voyager_at_t *) (eprom_buf + + sp_table->asic_data_offset); + for (j = 0; j < 4; j++) asicp->jtag_id[j] = asic_table->jtag_id[j]; - jtag_table = (voyager_jtt_t *)(eprom_buf + asic_table->jtag_offset); + jtag_table = + (voyager_jtt_t *) (eprom_buf + + asic_table->jtag_offset); asicp->ireg_length = jtag_table->ireg_len; asicp->bit_location = (*modpp)->inst_bits; (*modpp)->inst_bits += asicp->ireg_length; - if(asicp->ireg_length > (*modpp)->largest_reg) + if (asicp->ireg_length > (*modpp)->largest_reg) (*modpp)->largest_reg = asicp->ireg_length; if (asicp->ireg_length < (*modpp)->smallest_reg || (*modpp)->smallest_reg == 0) @@ -804,15 +823,13 @@ voyager_cat_init(void) CDEBUG(("asic 0x%x, ireg_length=%d, bit_location=%d\n", asicp->asic_id, asicp->ireg_length, asicp->bit_location)); - if(asicp->asic_id == VOYAGER_QUAD_QABC) { + if (asicp->asic_id == VOYAGER_QUAD_QABC) { CDEBUG(("VOYAGER CAT: QABC ASIC found\n")); qabc_asic = asicp; } sp_offset += sizeof(voyager_sp_table_t); } - CDEBUG(("Module inst_bits = %d, largest_reg = %d, smallest_reg=%d\n", - (*modpp)->inst_bits, (*modpp)->largest_reg, - (*modpp)->smallest_reg)); + CDEBUG(("Module inst_bits = %d, largest_reg = %d, smallest_reg=%d\n", (*modpp)->inst_bits, (*modpp)->largest_reg, (*modpp)->smallest_reg)); /* OK, now we have the QUAD ASICs set up, use them. * we need to: * @@ -828,10 +845,11 @@ voyager_cat_init(void) qic_addr = qabc_data[5] << 8; qic_addr = (qic_addr | qabc_data[6]) << 8; qic_addr = (qic_addr | qabc_data[7]) << 8; - printk("Module \"%s\": Quad Processor Card; CPI 0x%lx, SET=0x%x\n", - cat_module_name(i), qic_addr, qabc_data[8]); + printk + ("Module \"%s\": Quad Processor Card; CPI 0x%lx, SET=0x%x\n", + cat_module_name(i), qic_addr, qabc_data[8]); #if 0 /* plumbing fails---FIXME */ - if((qabc_data[8] & 0xf0) == 0) { + if ((qabc_data[8] & 0xf0) == 0) { /* FIXME: 32 way 8 CPU slot monster cannot be * plumbed this way---need to check for it */ @@ -842,94 +860,97 @@ voyager_cat_init(void) #ifdef VOYAGER_CAT_DEBUG /* verify plumbing */ cat_subread(*modpp, qabc_asic, 8, 1, &qabc_data[8]); - if((qabc_data[8] & 0xf0) == 0) { - CDEBUG(("PLUMBING FAILED: 0x%x\n", qabc_data[8])); + if ((qabc_data[8] & 0xf0) == 0) { + CDEBUG(("PLUMBING FAILED: 0x%x\n", + qabc_data[8])); } #endif } #endif { - struct resource *res = kzalloc(sizeof(struct resource),GFP_KERNEL); + struct resource *res = + kzalloc(sizeof(struct resource), GFP_KERNEL); res->name = kmalloc(128, GFP_KERNEL); - sprintf((char *)res->name, "Voyager %s Quad CPI", cat_module_name(i)); + sprintf((char *)res->name, "Voyager %s Quad CPI", + cat_module_name(i)); res->start = qic_addr; res->end = qic_addr + 0x3ff; request_resource(&iomem_resource, res); } qic_addr = (unsigned long)ioremap(qic_addr, 0x400); - - for(j = 0; j < 4; j++) { + + for (j = 0; j < 4; j++) { __u8 cpu; - if(voyager_8slot) { + if (voyager_8slot) { /* 8 slot has a different mapping, * each slot has only one vic line, so * 1 cpu in each slot must be < 8 */ - cpu = (i & 0x07) + j*8; + cpu = (i & 0x07) + j * 8; } else { - cpu = (i & 0x03) + j*4; + cpu = (i & 0x03) + j * 4; } - if( (qabc_data[8] & (1<next); } *modpp = NULL; - printk("CAT Bus Initialisation finished: extended procs 0x%x, quad procs 0x%x, allowed vic boot = 0x%x\n", voyager_extended_vic_processors, voyager_quad_processors, voyager_allowed_boot_processors); + printk + ("CAT Bus Initialisation finished: extended procs 0x%x, quad procs 0x%x, allowed vic boot = 0x%x\n", + voyager_extended_vic_processors, voyager_quad_processors, + voyager_allowed_boot_processors); request_resource(&ioport_resource, &vic_res); - if(voyager_quad_processors) + if (voyager_quad_processors) request_resource(&ioport_resource, &qic_res); /* set up the front power switch */ } -int -voyager_cat_readb(__u8 module, __u8 asic, int reg) +int voyager_cat_readb(__u8 module, __u8 asic, int reg) { return 0; } -static int -cat_disconnect(voyager_module_t *modp, voyager_asic_t *asicp) +static int cat_disconnect(voyager_module_t * modp, voyager_asic_t * asicp) { __u8 val; int err = 0; - if(!modp->scan_path_connected) + if (!modp->scan_path_connected) return 0; - if(asicp->asic_id != VOYAGER_CAT_ID) { + if (asicp->asic_id != VOYAGER_CAT_ID) { CDEBUG(("cat_disconnect: ASIC is not CAT\n")); return 1; } err = cat_read(modp, asicp, VOYAGER_SCANPATH, &val); - if(err) { + if (err) { CDEBUG(("cat_disconnect: failed to read SCANPATH\n")); return err; } val &= VOYAGER_DISCONNECT_ASIC; err = cat_write(modp, asicp, VOYAGER_SCANPATH, val); - if(err) { + if (err) { CDEBUG(("cat_disconnect: failed to write SCANPATH\n")); return err; } @@ -940,27 +961,26 @@ cat_disconnect(voyager_module_t *modp, voyager_asic_t *asicp) return 0; } -static int -cat_connect(voyager_module_t *modp, voyager_asic_t *asicp) +static int cat_connect(voyager_module_t * modp, voyager_asic_t * asicp) { __u8 val; int err = 0; - if(modp->scan_path_connected) + if (modp->scan_path_connected) return 0; - if(asicp->asic_id != VOYAGER_CAT_ID) { + if (asicp->asic_id != VOYAGER_CAT_ID) { CDEBUG(("cat_connect: ASIC is not CAT\n")); return 1; } err = cat_read(modp, asicp, VOYAGER_SCANPATH, &val); - if(err) { + if (err) { CDEBUG(("cat_connect: failed to read SCANPATH\n")); return err; } val |= VOYAGER_CONNECT_ASIC; err = cat_write(modp, asicp, VOYAGER_SCANPATH, val); - if(err) { + if (err) { CDEBUG(("cat_connect: failed to write SCANPATH\n")); return err; } @@ -971,11 +991,10 @@ cat_connect(voyager_module_t *modp, voyager_asic_t *asicp) return 0; } -void -voyager_cat_power_off(void) +void voyager_cat_power_off(void) { /* Power the machine off by writing to the PSI over the CAT - * bus */ + * bus */ __u8 data; voyager_module_t psi = { 0 }; voyager_asic_t psi_asic = { 0 }; @@ -1009,8 +1028,7 @@ voyager_cat_power_off(void) struct voyager_status voyager_status = { 0 }; -void -voyager_cat_psi(__u8 cmd, __u16 reg, __u8 *data) +void voyager_cat_psi(__u8 cmd, __u16 reg, __u8 * data) { voyager_module_t psi = { 0 }; voyager_asic_t psi_asic = { 0 }; @@ -1027,7 +1045,7 @@ voyager_cat_psi(__u8 cmd, __u16 reg, __u8 *data) outb(VOYAGER_PSI, VOYAGER_CAT_CONFIG_PORT); outb(VOYAGER_CAT_RUN, CAT_CMD); cat_disconnect(&psi, &psi_asic); - switch(cmd) { + switch (cmd) { case VOYAGER_PSI_READ: cat_read(&psi, &psi_asic, reg, data); break; @@ -1047,8 +1065,7 @@ voyager_cat_psi(__u8 cmd, __u16 reg, __u8 *data) outb(VOYAGER_CAT_END, CAT_CMD); } -void -voyager_cat_do_common_interrupt(void) +void voyager_cat_do_common_interrupt(void) { /* This is caused either by a memory parity error or something * in the PSI */ @@ -1057,7 +1074,7 @@ voyager_cat_do_common_interrupt(void) voyager_asic_t psi_asic = { 0 }; struct voyager_psi psi_reg; int i; - re_read: + re_read: psi.asic = &psi_asic; psi.asic->asic_id = VOYAGER_CAT_ID; psi.asic->subaddr = VOYAGER_SUBADDR_HI; @@ -1072,43 +1089,45 @@ voyager_cat_do_common_interrupt(void) cat_disconnect(&psi, &psi_asic); /* Read the status. NOTE: Need to read *all* the PSI regs here * otherwise the cmn int will be reasserted */ - for(i = 0; i < sizeof(psi_reg.regs); i++) { - cat_read(&psi, &psi_asic, i, &((__u8 *)&psi_reg.regs)[i]); + for (i = 0; i < sizeof(psi_reg.regs); i++) { + cat_read(&psi, &psi_asic, i, &((__u8 *) & psi_reg.regs)[i]); } outb(VOYAGER_CAT_END, CAT_CMD); - if((psi_reg.regs.checkbit & 0x02) == 0) { + if ((psi_reg.regs.checkbit & 0x02) == 0) { psi_reg.regs.checkbit |= 0x02; cat_write(&psi, &psi_asic, 5, psi_reg.regs.checkbit); printk("VOYAGER RE-READ PSI\n"); goto re_read; } outb(VOYAGER_CAT_RUN, CAT_CMD); - for(i = 0; i < sizeof(psi_reg.subregs); i++) { + for (i = 0; i < sizeof(psi_reg.subregs); i++) { /* This looks strange, but the PSI doesn't do auto increment * correctly */ - cat_subread(&psi, &psi_asic, VOYAGER_PSI_SUPPLY_REG + i, - 1, &((__u8 *)&psi_reg.subregs)[i]); + cat_subread(&psi, &psi_asic, VOYAGER_PSI_SUPPLY_REG + i, + 1, &((__u8 *) & psi_reg.subregs)[i]); } outb(VOYAGER_CAT_END, CAT_CMD); #ifdef VOYAGER_CAT_DEBUG printk("VOYAGER PSI: "); - for(i=0; iqic_cpi[cpi].cpi = - (smp_processor_id() << 16) + cpi; + (smp_processor_id() << 16) + cpi; } -static inline void -send_QIC_CPI(__u32 cpuset, __u8 cpi) +static inline void send_QIC_CPI(__u32 cpuset, __u8 cpi) { int cpu; for_each_online_cpu(cpu) { - if(cpuset & (1<>3 &0x7 on the 32 way */ - if(((cpuid >> 2) & 0x03) == i) + if (((cpuid >> 2) & 0x03) == i) /* don't lower our own mask! */ continue; @@ -368,12 +356,10 @@ do_quad_bootstrap(void) } } - /* Set up all the basic stuff: read the SMP config and make all the * SMP information reflect only the boot cpu. All others will be * brought on-line later. */ -void __init -find_smp_config(void) +void __init find_smp_config(void) { int i; @@ -382,24 +368,31 @@ find_smp_config(void) printk("VOYAGER SMP: Boot cpu is %d\n", boot_cpu_id); /* initialize the CPU structures (moved from smp_boot_cpus) */ - for(i=0; iqic_cpi[VIC_CPU_BOOT_CPI].cpi; + dummy = + voyager_quad_cpi_addr[cpuid]->qic_cpi[VIC_CPU_BOOT_CPI].cpi; printk("read dummy %d\n", dummy); } @@ -516,7 +507,6 @@ start_secondary(void *unused) cpu_idle(); } - /* Routine to kick start the given CPU and wait for it to report ready * (or timeout in startup). When this routine returns, the requested * CPU is either fully running and configured or known to be dead. @@ -524,15 +514,14 @@ start_secondary(void *unused) * We call this routine sequentially 1 CPU at a time, so no need for * locking */ -static void __init -do_boot_cpu(__u8 cpu) +static void __init do_boot_cpu(__u8 cpu) { struct task_struct *idle; int timeout; unsigned long flags; - int quad_boot = (1<thread.eip = (unsigned long) start_secondary; + idle->thread.eip = (unsigned long)start_secondary; /* init_tasks (in sched.c) is indexed logically */ - stack_start.esp = (void *) idle->thread.esp; + stack_start.esp = (void *)idle->thread.esp; init_gdt(cpu); - per_cpu(current_task, cpu) = idle; + per_cpu(current_task, cpu) = idle; early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); irq_ctx_init(cpu); /* Note: Don't modify initial ss override */ - VDEBUG(("VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p\n", cpu, + VDEBUG(("VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p\n", cpu, (unsigned long)hijack_source.val, hijack_source.idt.Segment, hijack_source.idt.Offset, stack_start.esp)); @@ -586,16 +575,23 @@ do_boot_cpu(__u8 cpu) min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS)); flush_tlb_all(); - if(quad_boot) { + if (quad_boot) { printk("CPU %d: non extended Quad boot\n", cpu); - hijack_vector = (__u32 *)phys_to_virt((VIC_CPU_BOOT_CPI + QIC_DEFAULT_CPI_BASE)*4); + hijack_vector = + (__u32 *) + phys_to_virt((VIC_CPU_BOOT_CPI + QIC_DEFAULT_CPI_BASE) * 4); *hijack_vector = hijack_source.val; } else { printk("CPU%d: extended VIC boot\n", cpu); - hijack_vector = (__u32 *)phys_to_virt((VIC_CPU_BOOT_CPI + VIC_DEFAULT_CPI_BASE)*4); + hijack_vector = + (__u32 *) + phys_to_virt((VIC_CPU_BOOT_CPI + VIC_DEFAULT_CPI_BASE) * 4); *hijack_vector = hijack_source.val; /* VIC errata, may also receive interrupt at this address */ - hijack_vector = (__u32 *)phys_to_virt((VIC_CPU_BOOT_ERRATA_CPI + VIC_DEFAULT_CPI_BASE)*4); + hijack_vector = + (__u32 *) + phys_to_virt((VIC_CPU_BOOT_ERRATA_CPI + + VIC_DEFAULT_CPI_BASE) * 4); *hijack_vector = hijack_source.val; } /* All non-boot CPUs start with interrupts fully masked. Need @@ -603,73 +599,76 @@ do_boot_cpu(__u8 cpu) * this in the VIC by masquerading as the processor we're * about to boot and lowering its interrupt mask */ local_irq_save(flags); - if(quad_boot) { + if (quad_boot) { send_one_QIC_CPI(cpu, VIC_CPU_BOOT_CPI); } else { outb(VIC_CPU_MASQUERADE_ENABLE | cpu, VIC_PROCESSOR_ID); /* here we're altering registers belonging to `cpu' */ - + outb(VIC_BOOT_INTERRUPT_MASK, 0x21); /* now go back to our original identity */ outb(boot_cpu_id, VIC_PROCESSOR_ID); /* and boot the CPU */ - send_CPI((1<thread.esp),"r" (current->thread.eip)); + asm volatile ("movl %0,%%esp\n\t" + "jmp *%1"::"r" (current->thread.esp), + "r"(current->thread.eip)); } /* handle a Voyager SYS_INT -- If we don't, the base board will @@ -758,25 +756,23 @@ initialize_secondary(void) * System interrupts occur because some problem was detected on the * various busses. To find out what you have to probe all the * hardware via the CAT bus. FIXME: At the moment we do nothing. */ -fastcall void -smp_vic_sys_interrupt(struct pt_regs *regs) +fastcall void smp_vic_sys_interrupt(struct pt_regs *regs) { ack_CPI(VIC_SYS_INT); - printk("Voyager SYSTEM INTERRUPT\n"); + printk("Voyager SYSTEM INTERRUPT\n"); } /* Handle a voyager CMN_INT; These interrupts occur either because of * a system status change or because a single bit memory error * occurred. FIXME: At the moment, ignore all this. */ -fastcall void -smp_vic_cmn_interrupt(struct pt_regs *regs) +fastcall void smp_vic_cmn_interrupt(struct pt_regs *regs) { static __u8 in_cmn_int = 0; static DEFINE_SPINLOCK(cmn_int_lock); /* common ints are broadcast, so make sure we only do this once */ _raw_spin_lock(&cmn_int_lock); - if(in_cmn_int) + if (in_cmn_int) goto unlock_end; in_cmn_int++; @@ -784,12 +780,12 @@ smp_vic_cmn_interrupt(struct pt_regs *regs) VDEBUG(("Voyager COMMON INTERRUPT\n")); - if(voyager_level == 5) + if (voyager_level == 5) voyager_cat_do_common_interrupt(); _raw_spin_lock(&cmn_int_lock); in_cmn_int = 0; - unlock_end: + unlock_end: _raw_spin_unlock(&cmn_int_lock); ack_CPI(VIC_CMN_INT); } @@ -797,26 +793,24 @@ smp_vic_cmn_interrupt(struct pt_regs *regs) /* * Reschedule call back. Nothing to do, all the work is done * automatically when we return from the interrupt. */ -static void -smp_reschedule_interrupt(void) +static void smp_reschedule_interrupt(void) { /* do nothing */ } -static struct mm_struct * flush_mm; +static struct mm_struct *flush_mm; static unsigned long flush_va; static DEFINE_SPINLOCK(tlbstate_lock); #define FLUSH_ALL 0xffffffff /* - * We cannot call mmdrop() because we are in interrupt context, + * We cannot call mmdrop() because we are in interrupt context, * instead update mm->cpu_vm_mask. * * We need to reload %cr3 since the page tables may be going * away from under us.. */ -static inline void -leave_mm (unsigned long cpu) +static inline void leave_mm(unsigned long cpu) { if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) BUG(); @@ -824,12 +818,10 @@ leave_mm (unsigned long cpu) load_cr3(swapper_pg_dir); } - /* * Invalidate call-back */ -static void -smp_invalidate_interrupt(void) +static void smp_invalidate_interrupt(void) { __u8 cpu = smp_processor_id(); @@ -837,9 +829,9 @@ smp_invalidate_interrupt(void) return; /* This will flood messages. Don't uncomment unless you see * Problems with cross cpu invalidation - VDEBUG(("VOYAGER SMP: CPU%d received INVALIDATE_CPI\n", - smp_processor_id())); - */ + VDEBUG(("VOYAGER SMP: CPU%d received INVALIDATE_CPI\n", + smp_processor_id())); + */ if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) { if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) { @@ -857,11 +849,10 @@ smp_invalidate_interrupt(void) /* All the new flush operations for 2.4 */ - /* This routine is called with a physical cpu mask */ static void -voyager_flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, - unsigned long va) +voyager_flush_tlb_others(unsigned long cpumask, struct mm_struct *mm, + unsigned long va) { int stuck = 50000; @@ -875,7 +866,7 @@ voyager_flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, BUG(); spin_lock(&tlbstate_lock); - + flush_mm = mm; flush_va = va; atomic_set_mask(cpumask, &smp_invalidate_needed); @@ -887,23 +878,23 @@ voyager_flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, while (smp_invalidate_needed) { mb(); - if(--stuck == 0) { - printk("***WARNING*** Stuck doing invalidate CPI (CPU%d)\n", smp_processor_id()); + if (--stuck == 0) { + printk("***WARNING*** Stuck doing invalidate CPI " + "(CPU%d)\n", smp_processor_id()); break; } } /* Uncomment only to debug invalidation problems - VDEBUG(("VOYAGER SMP: Completed invalidate CPI (CPU%d)\n", cpu)); - */ + VDEBUG(("VOYAGER SMP: Completed invalidate CPI (CPU%d)\n", cpu)); + */ flush_mm = NULL; flush_va = 0; spin_unlock(&tlbstate_lock); } -void -flush_tlb_current_task(void) +void flush_tlb_current_task(void) { struct mm_struct *mm = current->mm; unsigned long cpu_mask; @@ -918,9 +909,7 @@ flush_tlb_current_task(void) preempt_enable(); } - -void -flush_tlb_mm (struct mm_struct * mm) +void flush_tlb_mm(struct mm_struct *mm) { unsigned long cpu_mask; @@ -940,7 +929,7 @@ flush_tlb_mm (struct mm_struct * mm) preempt_enable(); } -void flush_tlb_page(struct vm_area_struct * vma, unsigned long va) +void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) { struct mm_struct *mm = vma->vm_mm; unsigned long cpu_mask; @@ -949,10 +938,10 @@ void flush_tlb_page(struct vm_area_struct * vma, unsigned long va) cpu_mask = cpus_addr(mm->cpu_vm_mask)[0] & ~(1 << smp_processor_id()); if (current->active_mm == mm) { - if(current->mm) + if (current->mm) __flush_tlb_one(va); - else - leave_mm(smp_processor_id()); + else + leave_mm(smp_processor_id()); } if (cpu_mask) @@ -960,21 +949,21 @@ void flush_tlb_page(struct vm_area_struct * vma, unsigned long va) preempt_enable(); } + EXPORT_SYMBOL(flush_tlb_page); /* enable the requested IRQs */ -static void -smp_enable_irq_interrupt(void) +static void smp_enable_irq_interrupt(void) { __u8 irq; __u8 cpu = get_cpu(); VDEBUG(("VOYAGER SMP: CPU%d enabling irq mask 0x%x\n", cpu, - vic_irq_enable_mask[cpu])); + vic_irq_enable_mask[cpu])); spin_lock(&vic_irq_lock); - for(irq = 0; irq < 16; irq++) { - if(vic_irq_enable_mask[cpu] & (1<func; void *info = call_data->info; @@ -1027,16 +1014,17 @@ smp_call_function_interrupt(void) * about to execute the function */ mb(); - if(!test_and_clear_bit(cpu, &call_data->started)) { + if (!test_and_clear_bit(cpu, &call_data->started)) { /* If the bit wasn't set, this could be a replay */ - printk(KERN_WARNING "VOYAGER SMP: CPU %d received call funtion with no call pending\n", cpu); + printk(KERN_WARNING "VOYAGER SMP: CPU %d received call funtion" + " with no call pending\n", cpu); return; } /* * At this point the info structure may be out of scope unless wait==1 */ irq_enter(); - (*func)(info); + (*func) (info); __get_cpu_var(irq_stat).irq_call_count++; irq_exit(); if (wait) { @@ -1046,14 +1034,13 @@ smp_call_function_interrupt(void) } static int -voyager_smp_call_function_mask (cpumask_t cpumask, - void (*func) (void *info), void *info, - int wait) +voyager_smp_call_function_mask(cpumask_t cpumask, + void (*func) (void *info), void *info, int wait) { struct call_data_struct data; u32 mask = cpus_addr(cpumask)[0]; - mask &= ~(1<= 0x93000) + trampoline_base = (__u32) alloc_bootmem_low_pages(PAGE_SIZE); + if (__pa(trampoline_base) >= 0x93000) BUG(); } /* send a reschedule CPI to one CPU by physical CPU number*/ -static void -voyager_smp_send_reschedule(int cpu) +static void voyager_smp_send_reschedule(int cpu) { send_one_CPI(cpu, VIC_RESCHEDULE_CPI); } - -int -hard_smp_processor_id(void) +int hard_smp_processor_id(void) { __u8 i; __u8 cpumask = inb(VIC_PROC_WHO_AM_I); - if((cpumask & QUAD_IDENTIFIER) == QUAD_IDENTIFIER) + if ((cpumask & QUAD_IDENTIFIER) == QUAD_IDENTIFIER) return cpumask & 0x1F; - for(i = 0; i < 8; i++) { - if(cpumask & (1<> 4; weight += 4; - if(weight > 7) + if (weight > 7) weight = 7; - if(weight < 0) + if (weight < 0) weight = 0; - - outb((__u8)weight, VIC_PRIORITY_REGISTER); + + outb((__u8) weight, VIC_PRIORITY_REGISTER); #ifdef VOYAGER_DEBUG - if((vic_tick[cpu] & 0xFFF) == 0) { + if ((vic_tick[cpu] & 0xFFF) == 0) { /* print this message roughly every 25 secs */ printk("VOYAGER SMP: vic_tick[%d] = %lu, weight = %ld\n", cpu, vic_tick[cpu], weight); @@ -1345,15 +1314,14 @@ smp_local_timer_interrupt(void) } /* setup the profiling timer */ -int -setup_profiling_timer(unsigned int multiplier) +int setup_profiling_timer(unsigned int multiplier) { int i; - if ( (!multiplier)) + if ((!multiplier)) return -EINVAL; - /* + /* * Set the new multiplier for each CPU. CPUs don't start using the * new values until the next timer interrupt in which they do process * accounting. @@ -1367,15 +1335,13 @@ setup_profiling_timer(unsigned int multiplier) /* This is a bit of a mess, but forced on us by the genirq changes * there's no genirq handler that really does what voyager wants * so hack it up with the simple IRQ handler */ -static void fastcall -handle_vic_irq(unsigned int irq, struct irq_desc *desc) +static void fastcall handle_vic_irq(unsigned int irq, struct irq_desc *desc) { before_handle_vic_irq(irq); handle_simple_irq(irq, desc); after_handle_vic_irq(irq); } - /* The CPIs are handled in the per cpu 8259s, so they must be * enabled to be received: FIX: enabling the CPIs in the early * boot sequence interferes with bug checking; enable them later @@ -1385,13 +1351,12 @@ handle_vic_irq(unsigned int irq, struct irq_desc *desc) #define QIC_SET_GATE(cpi, vector) \ set_intr_gate((cpi) + QIC_DEFAULT_CPI_BASE, (vector)) -void __init -smp_intr_init(void) +void __init smp_intr_init(void) { int i; /* initialize the per cpu irq mask to all disabled */ - for(i = 0; i < NR_CPUS; i++) + for (i = 0; i < NR_CPUS; i++) vic_irq_mask[i] = 0xFFFF; VIC_SET_GATE(VIC_CPI_LEVEL0, vic_cpi_interrupt); @@ -1404,42 +1369,40 @@ smp_intr_init(void) QIC_SET_GATE(QIC_RESCHEDULE_CPI, qic_reschedule_interrupt); QIC_SET_GATE(QIC_ENABLE_IRQ_CPI, qic_enable_irq_interrupt); QIC_SET_GATE(QIC_CALL_FUNCTION_CPI, qic_call_function_interrupt); - - /* now put the VIC descriptor into the first 48 IRQs + /* now put the VIC descriptor into the first 48 IRQs * * This is for later: first 16 correspond to PC IRQs; next 16 * are Primary MC IRQs and final 16 are Secondary MC IRQs */ - for(i = 0; i < 48; i++) + for (i = 0; i < 48; i++) set_irq_chip_and_handler(i, &vic_chip, handle_vic_irq); } /* send a CPI at level cpi to a set of cpus in cpuset (set 1 bit per * processor to receive CPI */ -static void -send_CPI(__u32 cpuset, __u8 cpi) +static void send_CPI(__u32 cpuset, __u8 cpi) { int cpu; __u32 quad_cpuset = (cpuset & voyager_quad_processors); - if(cpi < VIC_START_FAKE_CPI) { - /* fake CPI are only used for booting, so send to the + if (cpi < VIC_START_FAKE_CPI) { + /* fake CPI are only used for booting, so send to the * extended quads as well---Quads must be VIC booted */ - outb((__u8)(cpuset), VIC_CPI_Registers[cpi]); + outb((__u8) (cpuset), VIC_CPI_Registers[cpi]); return; } - if(quad_cpuset) + if (quad_cpuset) send_QIC_CPI(quad_cpuset, cpi); cpuset &= ~quad_cpuset; cpuset &= 0xff; /* only first 8 CPUs vaild for VIC CPI */ - if(cpuset == 0) + if (cpuset == 0) return; for_each_online_cpu(cpu) { - if(cpuset & (1<qic_cpi[cpi].cpi; } -static void -ack_special_QIC_CPI(__u8 cpi) +static void ack_special_QIC_CPI(__u8 cpi) { - switch(cpi) { + switch (cpi) { case VIC_CMN_INT: outb(QIC_CMN_INT, QIC_INTERRUPT_CLEAR0); break; @@ -1474,8 +1436,7 @@ ack_special_QIC_CPI(__u8 cpi) } /* Acknowledge receipt of CPI in the VIC (essentially an EOI) */ -static void -ack_VIC_CPI(__u8 cpi) +static void ack_VIC_CPI(__u8 cpi) { #ifdef VOYAGER_DEBUG unsigned long flags; @@ -1484,17 +1445,17 @@ ack_VIC_CPI(__u8 cpi) local_irq_save(flags); isr = vic_read_isr(); - if((isr & (1<<(cpi &7))) == 0) { + if ((isr & (1 << (cpi & 7))) == 0) { printk("VOYAGER SMP: CPU%d lost CPI%d\n", cpu, cpi); } #endif /* send specific EOI; the two system interrupts have * bit 4 set for a separate vector but behave as the * corresponding 3 bit intr */ - outb_p(0x60|(cpi & 7),0x20); + outb_p(0x60 | (cpi & 7), 0x20); #ifdef VOYAGER_DEBUG - if((vic_read_isr() & (1<<(cpi &7))) != 0) { + if ((vic_read_isr() & (1 << (cpi & 7))) != 0) { printk("VOYAGER SMP: CPU%d still asserting CPI%d\n", cpu, cpi); } local_irq_restore(flags); @@ -1502,12 +1463,11 @@ ack_VIC_CPI(__u8 cpi) } /* cribbed with thanks from irq.c */ -#define __byte(x,y) (((unsigned char *)&(y))[x]) +#define __byte(x,y) (((unsigned char *)&(y))[x]) #define cached_21(cpu) (__byte(0,vic_irq_mask[cpu])) #define cached_A1(cpu) (__byte(1,vic_irq_mask[cpu])) -static unsigned int -startup_vic_irq(unsigned int irq) +static unsigned int startup_vic_irq(unsigned int irq) { unmask_vic_irq(irq); @@ -1535,13 +1495,12 @@ startup_vic_irq(unsigned int irq) * broadcast an Interrupt enable CPI which causes all other CPUs to * adjust their masks accordingly. */ -static void -unmask_vic_irq(unsigned int irq) +static void unmask_vic_irq(unsigned int irq) { /* linux doesn't to processor-irq affinity, so enable on * all CPUs we know about */ int cpu = smp_processor_id(), real_cpu; - __u16 mask = (1<status |= IRQ_REPLAY | IRQ_INPROGRESS; - } else if(desc->status & IRQ_DISABLED) { + } else if (desc->status & IRQ_DISABLED) { /* Damn, the interrupt actually arrived, do the lazy * disable thing. The interrupt routine in irq.c will * not handle a IRQ_DISABLED interrupt, so nothing more @@ -1667,8 +1619,7 @@ before_handle_vic_irq(unsigned int irq) } /* Finish the VIC interrupt: basically mask */ -static void -after_handle_vic_irq(unsigned int irq) +static void after_handle_vic_irq(unsigned int irq) { irq_desc_t *desc = irq_desc + irq; @@ -1685,11 +1636,11 @@ after_handle_vic_irq(unsigned int irq) #ifdef VOYAGER_DEBUG /* DEBUG: before we ack, check what's in progress */ isr = vic_read_isr(); - if((isr & (1<= 32) + if (irq >= 32) /* You can only have 32 interrupts in a voyager system * (and 32 only if you have a secondary microchannel * bus) */ @@ -1780,8 +1730,8 @@ set_vic_irq_affinity(unsigned int irq, cpumask_t mask) for_each_online_cpu(cpu) { unsigned long cpu_mask = 1 << cpu; - - if(cpu_mask & real_mask) { + + if (cpu_mask & real_mask) { /* enable the interrupt for this cpu */ cpu_irq_affinity[cpu] |= irq_mask; } else { @@ -1800,25 +1750,23 @@ set_vic_irq_affinity(unsigned int irq, cpumask_t mask) unmask_vic_irq(irq); } -static void -ack_vic_irq(unsigned int irq) +static void ack_vic_irq(unsigned int irq) { if (irq & 8) { - outb(0x62,0x20); /* Specific EOI to cascade */ - outb(0x60|(irq & 7),0xA0); + outb(0x62, 0x20); /* Specific EOI to cascade */ + outb(0x60 | (irq & 7), 0xA0); } else { - outb(0x60 | (irq & 7),0x20); + outb(0x60 | (irq & 7), 0x20); } } /* enable the CPIs. In the VIC, the CPIs are delivered by the 8259 * but are not vectored by it. This means that the 8259 mask must be * lowered to receive them */ -static __init void -vic_enable_cpi(void) +static __init void vic_enable_cpi(void) { __u8 cpu = smp_processor_id(); - + /* just take a copy of the current mask (nop for boot cpu) */ vic_irq_mask[cpu] = vic_irq_mask[boot_cpu_id]; @@ -1827,7 +1775,7 @@ vic_enable_cpi(void) /* for sys int and cmn int */ enable_local_vic_irq(7); - if(is_cpu_quad()) { + if (is_cpu_quad()) { outb(QIC_DEFAULT_MASK0, QIC_MASK_REGISTER0); outb(QIC_CPI_ENABLE, QIC_MASK_REGISTER1); VDEBUG(("VOYAGER SMP: QIC ENABLE CPI: CPU%d: MASK 0x%x\n", @@ -1838,8 +1786,7 @@ vic_enable_cpi(void) cpu, vic_irq_mask[cpu])); } -void -voyager_smp_dump() +void voyager_smp_dump() { int old_cpu = smp_processor_id(), cpu; @@ -1865,10 +1812,10 @@ voyager_smp_dump() cpu, vic_irq_mask[cpu], imr, irr, isr); #if 0 /* These lines are put in to try to unstick an un ack'd irq */ - if(isr != 0) { + if (isr != 0) { int irq; - for(irq=0; irq<16; irq++) { - if(isr & (1<cpu = hard_smp_processor_id(); x86_write_percpu(cpu_number, hard_smp_processor_id()); diff --git a/arch/x86/mach-voyager/voyager_thread.c b/arch/x86/mach-voyager/voyager_thread.c index 50f9366c411e..c69c931818ed 100644 --- a/arch/x86/mach-voyager/voyager_thread.c +++ b/arch/x86/mach-voyager/voyager_thread.c @@ -30,12 +30,10 @@ #include #include - struct task_struct *voyager_thread; static __u8 set_timeout; -static int -execute(const char *string) +static int execute(const char *string) { int ret; @@ -52,48 +50,48 @@ execute(const char *string) NULL, }; - if ((ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC)) != 0) { - printk(KERN_ERR "Voyager failed to run \"%s\": %i\n", - string, ret); + if ((ret = + call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC)) != 0) { + printk(KERN_ERR "Voyager failed to run \"%s\": %i\n", string, + ret); } return ret; } -static void -check_from_kernel(void) +static void check_from_kernel(void) { - if(voyager_status.switch_off) { - + if (voyager_status.switch_off) { + /* FIXME: This should be configurable via proc */ execute("umask 600; echo 0 > /etc/initrunlvl; kill -HUP 1"); - } else if(voyager_status.power_fail) { + } else if (voyager_status.power_fail) { VDEBUG(("Voyager daemon detected AC power failure\n")); - + /* FIXME: This should be configureable via proc */ execute("umask 600; echo F > /etc/powerstatus; kill -PWR 1"); set_timeout = 1; } } -static void -check_continuing_condition(void) +static void check_continuing_condition(void) { - if(voyager_status.power_fail) { + if (voyager_status.power_fail) { __u8 data; - voyager_cat_psi(VOYAGER_PSI_SUBREAD, + voyager_cat_psi(VOYAGER_PSI_SUBREAD, VOYAGER_PSI_AC_FAIL_REG, &data); - if((data & 0x1f) == 0) { + if ((data & 0x1f) == 0) { /* all power restored */ - printk(KERN_NOTICE "VOYAGER AC power restored, cancelling shutdown\n"); + printk(KERN_NOTICE + "VOYAGER AC power restored, cancelling shutdown\n"); /* FIXME: should be user configureable */ - execute("umask 600; echo O > /etc/powerstatus; kill -PWR 1"); + execute + ("umask 600; echo O > /etc/powerstatus; kill -PWR 1"); set_timeout = 0; } } } -static int -thread(void *unused) +static int thread(void *unused) { printk(KERN_NOTICE "Voyager starting monitor thread\n"); @@ -102,7 +100,7 @@ thread(void *unused) schedule_timeout(set_timeout ? HZ : MAX_SCHEDULE_TIMEOUT); VDEBUG(("Voyager Daemon awoken\n")); - if(voyager_status.request_from_kernel == 0) { + if (voyager_status.request_from_kernel == 0) { /* probably awoken from timeout */ check_continuing_condition(); } else { @@ -112,20 +110,18 @@ thread(void *unused) } } -static int __init -voyager_thread_start(void) +static int __init voyager_thread_start(void) { voyager_thread = kthread_run(thread, NULL, "kvoyagerd"); if (IS_ERR(voyager_thread)) { - printk(KERN_ERR "Voyager: Failed to create system monitor thread.\n"); + printk(KERN_ERR + "Voyager: Failed to create system monitor thread.\n"); return PTR_ERR(voyager_thread); } return 0; } - -static void __exit -voyager_thread_stop(void) +static void __exit voyager_thread_stop(void) { kthread_stop(voyager_thread); } From 3d0d14f983b55a570b976976284df4c434af3223 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:11 +0100 Subject: [PATCH 043/890] x86: lindent arch/i386/math-emu lindent these files: errors lines of code errors/KLOC arch/x86/math-emu/ 2236 9424 237.2 arch/x86/math-emu/ 128 8706 14.7 no other changes. No code changed: text data bss dec hex filename 5589802 612739 3833856 10036397 9924ad vmlinux.before 5589802 612739 3833856 10036397 9924ad vmlinux.after the intent of this patch is to ease the automated tracking of kernel code quality - it's just much easier for us to maintain it if every file in arch/x86 is supposed to be clean. NOTE: it is a known problem of lindent that it causes some style damage of its own, but it's a safe tool (well, except for the gcc array range initializers extension), so we did the bulk of the changes via lindent, and did the manual fixups in a followup patch. the resulting math-emu code has been tested by Thomas Gleixner on a real 386 DX CPU as well, and it works fine. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/math-emu/errors.c | 866 +++++---- arch/x86/math-emu/exception.h | 9 +- arch/x86/math-emu/fpu_arith.c | 150 +- arch/x86/math-emu/fpu_asm.h | 1 - arch/x86/math-emu/fpu_aux.c | 203 +-- arch/x86/math-emu/fpu_emu.h | 77 +- arch/x86/math-emu/fpu_entry.c | 1178 +++++++------ arch/x86/math-emu/fpu_etc.c | 193 +- arch/x86/math-emu/fpu_proto.h | 80 +- arch/x86/math-emu/fpu_tags.c | 92 +- arch/x86/math-emu/fpu_trig.c | 2814 ++++++++++++++---------------- arch/x86/math-emu/get_address.c | 626 ++++--- arch/x86/math-emu/load_store.c | 448 ++--- arch/x86/math-emu/poly.h | 79 +- arch/x86/math-emu/poly_2xm1.c | 195 +-- arch/x86/math-emu/poly_atan.c | 331 ++-- arch/x86/math-emu/poly_l2.c | 344 ++-- arch/x86/math-emu/poly_sin.c | 615 ++++--- arch/x86/math-emu/poly_tan.c | 320 ++-- arch/x86/math-emu/reg_add_sub.c | 545 +++--- arch/x86/math-emu/reg_compare.c | 547 +++--- arch/x86/math-emu/reg_constant.c | 71 +- arch/x86/math-emu/reg_convert.c | 51 +- arch/x86/math-emu/reg_divide.c | 299 ++-- arch/x86/math-emu/reg_ld_str.c | 2083 ++++++++++------------ arch/x86/math-emu/reg_mul.c | 163 +- arch/x86/math-emu/status_w.h | 8 +- 27 files changed, 5835 insertions(+), 6553 deletions(-) diff --git a/arch/x86/math-emu/errors.c b/arch/x86/math-emu/errors.c index a1b0d22f6978..7cb5bf3495b2 100644 --- a/arch/x86/math-emu/errors.c +++ b/arch/x86/math-emu/errors.c @@ -33,45 +33,41 @@ #undef PRINT_MESSAGES /* */ - #if 0 void Un_impl(void) { - u_char byte1, FPU_modrm; - unsigned long address = FPU_ORIG_EIP; + u_char byte1, FPU_modrm; + unsigned long address = FPU_ORIG_EIP; - RE_ENTRANT_CHECK_OFF; - /* No need to check access_ok(), we have previously fetched these bytes. */ - printk("Unimplemented FPU Opcode at eip=%p : ", (void __user *) address); - if ( FPU_CS == __USER_CS ) - { - while ( 1 ) - { - FPU_get_user(byte1, (u_char __user *) address); - if ( (byte1 & 0xf8) == 0xd8 ) break; - printk("[%02x]", byte1); - address++; + RE_ENTRANT_CHECK_OFF; + /* No need to check access_ok(), we have previously fetched these bytes. */ + printk("Unimplemented FPU Opcode at eip=%p : ", (void __user *)address); + if (FPU_CS == __USER_CS) { + while (1) { + FPU_get_user(byte1, (u_char __user *) address); + if ((byte1 & 0xf8) == 0xd8) + break; + printk("[%02x]", byte1); + address++; + } + printk("%02x ", byte1); + FPU_get_user(FPU_modrm, 1 + (u_char __user *) address); + + if (FPU_modrm >= 0300) + printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, + FPU_modrm & 7); + else + printk("/%d\n", (FPU_modrm >> 3) & 7); + } else { + printk("cs selector = %04x\n", FPU_CS); } - printk("%02x ", byte1); - FPU_get_user(FPU_modrm, 1 + (u_char __user *) address); - - if (FPU_modrm >= 0300) - printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); - else - printk("/%d\n", (FPU_modrm >> 3) & 7); - } - else - { - printk("cs selector = %04x\n", FPU_CS); - } - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_ON; - EXCEPTION(EX_Invalid); + EXCEPTION(EX_Invalid); } -#endif /* 0 */ - +#endif /* 0 */ /* Called for opcodes which are illegal and which are known to result in a @@ -79,139 +75,152 @@ void Un_impl(void) */ void FPU_illegal(void) { - math_abort(FPU_info,SIGILL); + math_abort(FPU_info, SIGILL); } - - void FPU_printall(void) { - int i; - static const char *tag_desc[] = { "Valid", "Zero", "ERROR", "Empty", - "DeNorm", "Inf", "NaN" }; - u_char byte1, FPU_modrm; - unsigned long address = FPU_ORIG_EIP; + int i; + static const char *tag_desc[] = { "Valid", "Zero", "ERROR", "Empty", + "DeNorm", "Inf", "NaN" + }; + u_char byte1, FPU_modrm; + unsigned long address = FPU_ORIG_EIP; - RE_ENTRANT_CHECK_OFF; - /* No need to check access_ok(), we have previously fetched these bytes. */ - printk("At %p:", (void *) address); - if ( FPU_CS == __USER_CS ) - { + RE_ENTRANT_CHECK_OFF; + /* No need to check access_ok(), we have previously fetched these bytes. */ + printk("At %p:", (void *)address); + if (FPU_CS == __USER_CS) { #define MAX_PRINTED_BYTES 20 - for ( i = 0; i < MAX_PRINTED_BYTES; i++ ) - { - FPU_get_user(byte1, (u_char __user *) address); - if ( (byte1 & 0xf8) == 0xd8 ) - { - printk(" %02x", byte1); - break; - } - printk(" [%02x]", byte1); - address++; - } - if ( i == MAX_PRINTED_BYTES ) - printk(" [more..]\n"); - else - { - FPU_get_user(FPU_modrm, 1 + (u_char __user *) address); - - if (FPU_modrm >= 0300) - printk(" %02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); - else - printk(" /%d, mod=%d rm=%d\n", - (FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7); - } - } - else - { - printk("%04x\n", FPU_CS); - } + for (i = 0; i < MAX_PRINTED_BYTES; i++) { + FPU_get_user(byte1, (u_char __user *) address); + if ((byte1 & 0xf8) == 0xd8) { + printk(" %02x", byte1); + break; + } + printk(" [%02x]", byte1); + address++; + } + if (i == MAX_PRINTED_BYTES) + printk(" [more..]\n"); + else { + FPU_get_user(FPU_modrm, 1 + (u_char __user *) address); - partial_status = status_word(); + if (FPU_modrm >= 0300) + printk(" %02x (%02x+%d)\n", FPU_modrm, + FPU_modrm & 0xf8, FPU_modrm & 7); + else + printk(" /%d, mod=%d rm=%d\n", + (FPU_modrm >> 3) & 7, + (FPU_modrm >> 6) & 3, FPU_modrm & 7); + } + } else { + printk("%04x\n", FPU_CS); + } + + partial_status = status_word(); #ifdef DEBUGGING -if ( partial_status & SW_Backward ) printk("SW: backward compatibility\n"); -if ( partial_status & SW_C3 ) printk("SW: condition bit 3\n"); -if ( partial_status & SW_C2 ) printk("SW: condition bit 2\n"); -if ( partial_status & SW_C1 ) printk("SW: condition bit 1\n"); -if ( partial_status & SW_C0 ) printk("SW: condition bit 0\n"); -if ( partial_status & SW_Summary ) printk("SW: exception summary\n"); -if ( partial_status & SW_Stack_Fault ) printk("SW: stack fault\n"); -if ( partial_status & SW_Precision ) printk("SW: loss of precision\n"); -if ( partial_status & SW_Underflow ) printk("SW: underflow\n"); -if ( partial_status & SW_Overflow ) printk("SW: overflow\n"); -if ( partial_status & SW_Zero_Div ) printk("SW: divide by zero\n"); -if ( partial_status & SW_Denorm_Op ) printk("SW: denormalized operand\n"); -if ( partial_status & SW_Invalid ) printk("SW: invalid operation\n"); + if (partial_status & SW_Backward) + printk("SW: backward compatibility\n"); + if (partial_status & SW_C3) + printk("SW: condition bit 3\n"); + if (partial_status & SW_C2) + printk("SW: condition bit 2\n"); + if (partial_status & SW_C1) + printk("SW: condition bit 1\n"); + if (partial_status & SW_C0) + printk("SW: condition bit 0\n"); + if (partial_status & SW_Summary) + printk("SW: exception summary\n"); + if (partial_status & SW_Stack_Fault) + printk("SW: stack fault\n"); + if (partial_status & SW_Precision) + printk("SW: loss of precision\n"); + if (partial_status & SW_Underflow) + printk("SW: underflow\n"); + if (partial_status & SW_Overflow) + printk("SW: overflow\n"); + if (partial_status & SW_Zero_Div) + printk("SW: divide by zero\n"); + if (partial_status & SW_Denorm_Op) + printk("SW: denormalized operand\n"); + if (partial_status & SW_Invalid) + printk("SW: invalid operation\n"); #endif /* DEBUGGING */ - printk(" SW: b=%d st=%ld es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n", - partial_status & 0x8000 ? 1 : 0, /* busy */ - (partial_status & 0x3800) >> 11, /* stack top pointer */ - partial_status & 0x80 ? 1 : 0, /* Error summary status */ - partial_status & 0x40 ? 1 : 0, /* Stack flag */ - partial_status & SW_C3?1:0, partial_status & SW_C2?1:0, /* cc */ - partial_status & SW_C1?1:0, partial_status & SW_C0?1:0, /* cc */ - partial_status & SW_Precision?1:0, partial_status & SW_Underflow?1:0, - partial_status & SW_Overflow?1:0, partial_status & SW_Zero_Div?1:0, - partial_status & SW_Denorm_Op?1:0, partial_status & SW_Invalid?1:0); - -printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d ef=%d%d%d%d%d%d\n", - control_word & 0x1000 ? 1 : 0, - (control_word & 0x800) >> 11, (control_word & 0x400) >> 10, - (control_word & 0x200) >> 9, (control_word & 0x100) >> 8, - control_word & 0x80 ? 1 : 0, - control_word & SW_Precision?1:0, control_word & SW_Underflow?1:0, - control_word & SW_Overflow?1:0, control_word & SW_Zero_Div?1:0, - control_word & SW_Denorm_Op?1:0, control_word & SW_Invalid?1:0); + printk(" SW: b=%d st=%ld es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n", partial_status & 0x8000 ? 1 : 0, /* busy */ + (partial_status & 0x3800) >> 11, /* stack top pointer */ + partial_status & 0x80 ? 1 : 0, /* Error summary status */ + partial_status & 0x40 ? 1 : 0, /* Stack flag */ + partial_status & SW_C3 ? 1 : 0, partial_status & SW_C2 ? 1 : 0, /* cc */ + partial_status & SW_C1 ? 1 : 0, partial_status & SW_C0 ? 1 : 0, /* cc */ + partial_status & SW_Precision ? 1 : 0, + partial_status & SW_Underflow ? 1 : 0, + partial_status & SW_Overflow ? 1 : 0, + partial_status & SW_Zero_Div ? 1 : 0, + partial_status & SW_Denorm_Op ? 1 : 0, + partial_status & SW_Invalid ? 1 : 0); - for ( i = 0; i < 8; i++ ) - { - FPU_REG *r = &st(i); - u_char tagi = FPU_gettagi(i); - switch (tagi) - { - case TAG_Empty: - continue; - break; - case TAG_Zero: - case TAG_Special: - tagi = FPU_Special(r); - case TAG_Valid: - printk("st(%d) %c .%04lx %04lx %04lx %04lx e%+-6d ", i, - getsign(r) ? '-' : '+', - (long)(r->sigh >> 16), - (long)(r->sigh & 0xFFFF), - (long)(r->sigl >> 16), - (long)(r->sigl & 0xFFFF), - exponent(r) - EXP_BIAS + 1); - break; - default: - printk("Whoops! Error in errors.c: tag%d is %d ", i, tagi); - continue; - break; + printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d ef=%d%d%d%d%d%d\n", + control_word & 0x1000 ? 1 : 0, + (control_word & 0x800) >> 11, (control_word & 0x400) >> 10, + (control_word & 0x200) >> 9, (control_word & 0x100) >> 8, + control_word & 0x80 ? 1 : 0, + control_word & SW_Precision ? 1 : 0, + control_word & SW_Underflow ? 1 : 0, + control_word & SW_Overflow ? 1 : 0, + control_word & SW_Zero_Div ? 1 : 0, + control_word & SW_Denorm_Op ? 1 : 0, + control_word & SW_Invalid ? 1 : 0); + + for (i = 0; i < 8; i++) { + FPU_REG *r = &st(i); + u_char tagi = FPU_gettagi(i); + switch (tagi) { + case TAG_Empty: + continue; + break; + case TAG_Zero: + case TAG_Special: + tagi = FPU_Special(r); + case TAG_Valid: + printk("st(%d) %c .%04lx %04lx %04lx %04lx e%+-6d ", i, + getsign(r) ? '-' : '+', + (long)(r->sigh >> 16), + (long)(r->sigh & 0xFFFF), + (long)(r->sigl >> 16), + (long)(r->sigl & 0xFFFF), + exponent(r) - EXP_BIAS + 1); + break; + default: + printk("Whoops! Error in errors.c: tag%d is %d ", i, + tagi); + continue; + break; + } + printk("%s\n", tag_desc[(int)(unsigned)tagi]); } - printk("%s\n", tag_desc[(int) (unsigned) tagi]); - } - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_ON; } static struct { - int type; - const char *name; + int type; + const char *name; } exception_names[] = { - { EX_StackOver, "stack overflow" }, - { EX_StackUnder, "stack underflow" }, - { EX_Precision, "loss of precision" }, - { EX_Underflow, "underflow" }, - { EX_Overflow, "overflow" }, - { EX_ZeroDiv, "divide by zero" }, - { EX_Denormal, "denormalized operand" }, - { EX_Invalid, "invalid operation" }, - { EX_INTERNAL, "INTERNAL BUG in "FPU_VERSION }, - { 0, NULL } + { + EX_StackOver, "stack overflow"}, { + EX_StackUnder, "stack underflow"}, { + EX_Precision, "loss of precision"}, { + EX_Underflow, "underflow"}, { + EX_Overflow, "overflow"}, { + EX_ZeroDiv, "divide by zero"}, { + EX_Denormal, "denormalized operand"}, { + EX_Invalid, "invalid operation"}, { + EX_INTERNAL, "INTERNAL BUG in " FPU_VERSION}, { + 0, NULL} }; /* @@ -295,445 +304,386 @@ static struct { asmlinkage void FPU_exception(int n) { - int i, int_type; + int i, int_type; - int_type = 0; /* Needed only to stop compiler warnings */ - if ( n & EX_INTERNAL ) - { - int_type = n - EX_INTERNAL; - n = EX_INTERNAL; - /* Set lots of exception bits! */ - partial_status |= (SW_Exc_Mask | SW_Summary | SW_Backward); - } - else - { - /* Extract only the bits which we use to set the status word */ - n &= (SW_Exc_Mask); - /* Set the corresponding exception bit */ - partial_status |= n; - /* Set summary bits iff exception isn't masked */ - if ( partial_status & ~control_word & CW_Exceptions ) - partial_status |= (SW_Summary | SW_Backward); - if ( n & (SW_Stack_Fault | EX_Precision) ) - { - if ( !(n & SW_C1) ) - /* This bit distinguishes over- from underflow for a stack fault, - and roundup from round-down for precision loss. */ - partial_status &= ~SW_C1; + int_type = 0; /* Needed only to stop compiler warnings */ + if (n & EX_INTERNAL) { + int_type = n - EX_INTERNAL; + n = EX_INTERNAL; + /* Set lots of exception bits! */ + partial_status |= (SW_Exc_Mask | SW_Summary | SW_Backward); + } else { + /* Extract only the bits which we use to set the status word */ + n &= (SW_Exc_Mask); + /* Set the corresponding exception bit */ + partial_status |= n; + /* Set summary bits iff exception isn't masked */ + if (partial_status & ~control_word & CW_Exceptions) + partial_status |= (SW_Summary | SW_Backward); + if (n & (SW_Stack_Fault | EX_Precision)) { + if (!(n & SW_C1)) + /* This bit distinguishes over- from underflow for a stack fault, + and roundup from round-down for precision loss. */ + partial_status &= ~SW_C1; + } } - } - RE_ENTRANT_CHECK_OFF; - if ( (~control_word & n & CW_Exceptions) || (n == EX_INTERNAL) ) - { + RE_ENTRANT_CHECK_OFF; + if ((~control_word & n & CW_Exceptions) || (n == EX_INTERNAL)) { #ifdef PRINT_MESSAGES - /* My message from the sponsor */ - printk(FPU_VERSION" "__DATE__" (C) W. Metzenthen.\n"); -#endif /* PRINT_MESSAGES */ - - /* Get a name string for error reporting */ - for (i=0; exception_names[i].type; i++) - if ( (exception_names[i].type & n) == exception_names[i].type ) - break; - - if (exception_names[i].type) - { -#ifdef PRINT_MESSAGES - printk("FP Exception: %s!\n", exception_names[i].name); -#endif /* PRINT_MESSAGES */ - } - else - printk("FPU emulator: Unknown Exception: 0x%04x!\n", n); - - if ( n == EX_INTERNAL ) - { - printk("FPU emulator: Internal error type 0x%04x\n", int_type); - FPU_printall(); - } -#ifdef PRINT_MESSAGES - else - FPU_printall(); + /* My message from the sponsor */ + printk(FPU_VERSION " " __DATE__ " (C) W. Metzenthen.\n"); #endif /* PRINT_MESSAGES */ - /* - * The 80486 generates an interrupt on the next non-control FPU - * instruction. So we need some means of flagging it. - * We use the ES (Error Summary) bit for this. - */ - } - RE_ENTRANT_CHECK_ON; + /* Get a name string for error reporting */ + for (i = 0; exception_names[i].type; i++) + if ((exception_names[i].type & n) == + exception_names[i].type) + break; + + if (exception_names[i].type) { +#ifdef PRINT_MESSAGES + printk("FP Exception: %s!\n", exception_names[i].name); +#endif /* PRINT_MESSAGES */ + } else + printk("FPU emulator: Unknown Exception: 0x%04x!\n", n); + + if (n == EX_INTERNAL) { + printk("FPU emulator: Internal error type 0x%04x\n", + int_type); + FPU_printall(); + } +#ifdef PRINT_MESSAGES + else + FPU_printall(); +#endif /* PRINT_MESSAGES */ + + /* + * The 80486 generates an interrupt on the next non-control FPU + * instruction. So we need some means of flagging it. + * We use the ES (Error Summary) bit for this. + */ + } + RE_ENTRANT_CHECK_ON; #ifdef __DEBUG__ - math_abort(FPU_info,SIGFPE); + math_abort(FPU_info, SIGFPE); #endif /* __DEBUG__ */ } - /* Real operation attempted on a NaN. */ /* Returns < 0 if the exception is unmasked */ -int real_1op_NaN(FPU_REG *a) +int real_1op_NaN(FPU_REG * a) { - int signalling, isNaN; + int signalling, isNaN; - isNaN = (exponent(a) == EXP_OVER) && (a->sigh & 0x80000000); + isNaN = (exponent(a) == EXP_OVER) && (a->sigh & 0x80000000); - /* The default result for the case of two "equal" NaNs (signs may - differ) is chosen to reproduce 80486 behaviour */ - signalling = isNaN && !(a->sigh & 0x40000000); + /* The default result for the case of two "equal" NaNs (signs may + differ) is chosen to reproduce 80486 behaviour */ + signalling = isNaN && !(a->sigh & 0x40000000); - if ( !signalling ) - { - if ( !isNaN ) /* pseudo-NaN, or other unsupported? */ - { - if ( control_word & CW_Invalid ) - { - /* Masked response */ - reg_copy(&CONST_QNaN, a); - } - EXCEPTION(EX_Invalid); - return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special; + if (!signalling) { + if (!isNaN) { /* pseudo-NaN, or other unsupported? */ + if (control_word & CW_Invalid) { + /* Masked response */ + reg_copy(&CONST_QNaN, a); + } + EXCEPTION(EX_Invalid); + return (!(control_word & CW_Invalid) ? FPU_Exception : + 0) | TAG_Special; + } + return TAG_Special; } - return TAG_Special; - } - if ( control_word & CW_Invalid ) - { - /* The masked response */ - if ( !(a->sigh & 0x80000000) ) /* pseudo-NaN ? */ - { - reg_copy(&CONST_QNaN, a); + if (control_word & CW_Invalid) { + /* The masked response */ + if (!(a->sigh & 0x80000000)) { /* pseudo-NaN ? */ + reg_copy(&CONST_QNaN, a); + } + /* ensure a Quiet NaN */ + a->sigh |= 0x40000000; } - /* ensure a Quiet NaN */ - a->sigh |= 0x40000000; - } - EXCEPTION(EX_Invalid); + EXCEPTION(EX_Invalid); - return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special; + return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special; } - /* Real operation attempted on two operands, one a NaN. */ /* Returns < 0 if the exception is unmasked */ int real_2op_NaN(FPU_REG const *b, u_char tagb, - int deststnr, - FPU_REG const *defaultNaN) + int deststnr, FPU_REG const *defaultNaN) { - FPU_REG *dest = &st(deststnr); - FPU_REG const *a = dest; - u_char taga = FPU_gettagi(deststnr); - FPU_REG const *x; - int signalling, unsupported; + FPU_REG *dest = &st(deststnr); + FPU_REG const *a = dest; + u_char taga = FPU_gettagi(deststnr); + FPU_REG const *x; + int signalling, unsupported; - if ( taga == TAG_Special ) - taga = FPU_Special(a); - if ( tagb == TAG_Special ) - tagb = FPU_Special(b); + if (taga == TAG_Special) + taga = FPU_Special(a); + if (tagb == TAG_Special) + tagb = FPU_Special(b); - /* TW_NaN is also used for unsupported data types. */ - unsupported = ((taga == TW_NaN) - && !((exponent(a) == EXP_OVER) && (a->sigh & 0x80000000))) - || ((tagb == TW_NaN) - && !((exponent(b) == EXP_OVER) && (b->sigh & 0x80000000))); - if ( unsupported ) - { - if ( control_word & CW_Invalid ) - { - /* Masked response */ - FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr); + /* TW_NaN is also used for unsupported data types. */ + unsupported = ((taga == TW_NaN) + && !((exponent(a) == EXP_OVER) + && (a->sigh & 0x80000000))) + || ((tagb == TW_NaN) + && !((exponent(b) == EXP_OVER) && (b->sigh & 0x80000000))); + if (unsupported) { + if (control_word & CW_Invalid) { + /* Masked response */ + FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr); + } + EXCEPTION(EX_Invalid); + return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | + TAG_Special; } - EXCEPTION(EX_Invalid); - return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special; - } - if (taga == TW_NaN) - { - x = a; - if (tagb == TW_NaN) - { - signalling = !(a->sigh & b->sigh & 0x40000000); - if ( significand(b) > significand(a) ) - x = b; - else if ( significand(b) == significand(a) ) - { - /* The default result for the case of two "equal" NaNs (signs may - differ) is chosen to reproduce 80486 behaviour */ - x = defaultNaN; - } - } - else - { - /* return the quiet version of the NaN in a */ - signalling = !(a->sigh & 0x40000000); - } - } - else + if (taga == TW_NaN) { + x = a; + if (tagb == TW_NaN) { + signalling = !(a->sigh & b->sigh & 0x40000000); + if (significand(b) > significand(a)) + x = b; + else if (significand(b) == significand(a)) { + /* The default result for the case of two "equal" NaNs (signs may + differ) is chosen to reproduce 80486 behaviour */ + x = defaultNaN; + } + } else { + /* return the quiet version of the NaN in a */ + signalling = !(a->sigh & 0x40000000); + } + } else #ifdef PARANOID - if (tagb == TW_NaN) + if (tagb == TW_NaN) #endif /* PARANOID */ - { - signalling = !(b->sigh & 0x40000000); - x = b; - } + { + signalling = !(b->sigh & 0x40000000); + x = b; + } #ifdef PARANOID - else - { - signalling = 0; - EXCEPTION(EX_INTERNAL|0x113); - x = &CONST_QNaN; - } + else { + signalling = 0; + EXCEPTION(EX_INTERNAL | 0x113); + x = &CONST_QNaN; + } #endif /* PARANOID */ - if ( (!signalling) || (control_word & CW_Invalid) ) - { - if ( ! x ) - x = b; + if ((!signalling) || (control_word & CW_Invalid)) { + if (!x) + x = b; - if ( !(x->sigh & 0x80000000) ) /* pseudo-NaN ? */ - x = &CONST_QNaN; + if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */ + x = &CONST_QNaN; - FPU_copy_to_regi(x, TAG_Special, deststnr); + FPU_copy_to_regi(x, TAG_Special, deststnr); - if ( !signalling ) - return TAG_Special; + if (!signalling) + return TAG_Special; - /* ensure a Quiet NaN */ - dest->sigh |= 0x40000000; - } + /* ensure a Quiet NaN */ + dest->sigh |= 0x40000000; + } - EXCEPTION(EX_Invalid); + EXCEPTION(EX_Invalid); - return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special; + return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special; } - /* Invalid arith operation on Valid registers */ /* Returns < 0 if the exception is unmasked */ asmlinkage int arith_invalid(int deststnr) { - EXCEPTION(EX_Invalid); - - if ( control_word & CW_Invalid ) - { - /* The masked response */ - FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr); - } - - return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Valid; + EXCEPTION(EX_Invalid); + + if (control_word & CW_Invalid) { + /* The masked response */ + FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr); + } + + return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Valid; } - /* Divide a finite number by zero */ asmlinkage int FPU_divide_by_zero(int deststnr, u_char sign) { - FPU_REG *dest = &st(deststnr); - int tag = TAG_Valid; + FPU_REG *dest = &st(deststnr); + int tag = TAG_Valid; - if ( control_word & CW_ZeroDiv ) - { - /* The masked response */ - FPU_copy_to_regi(&CONST_INF, TAG_Special, deststnr); - setsign(dest, sign); - tag = TAG_Special; - } - - EXCEPTION(EX_ZeroDiv); + if (control_word & CW_ZeroDiv) { + /* The masked response */ + FPU_copy_to_regi(&CONST_INF, TAG_Special, deststnr); + setsign(dest, sign); + tag = TAG_Special; + } - return (!(control_word & CW_ZeroDiv) ? FPU_Exception : 0) | tag; + EXCEPTION(EX_ZeroDiv); + + return (!(control_word & CW_ZeroDiv) ? FPU_Exception : 0) | tag; } - /* This may be called often, so keep it lean */ int set_precision_flag(int flags) { - if ( control_word & CW_Precision ) - { - partial_status &= ~(SW_C1 & flags); - partial_status |= flags; /* The masked response */ - return 0; - } - else - { - EXCEPTION(flags); - return 1; - } + if (control_word & CW_Precision) { + partial_status &= ~(SW_C1 & flags); + partial_status |= flags; /* The masked response */ + return 0; + } else { + EXCEPTION(flags); + return 1; + } } - /* This may be called often, so keep it lean */ asmlinkage void set_precision_flag_up(void) { - if ( control_word & CW_Precision ) - partial_status |= (SW_Precision | SW_C1); /* The masked response */ - else - EXCEPTION(EX_Precision | SW_C1); + if (control_word & CW_Precision) + partial_status |= (SW_Precision | SW_C1); /* The masked response */ + else + EXCEPTION(EX_Precision | SW_C1); } - /* This may be called often, so keep it lean */ asmlinkage void set_precision_flag_down(void) { - if ( control_word & CW_Precision ) - { /* The masked response */ - partial_status &= ~SW_C1; - partial_status |= SW_Precision; - } - else - EXCEPTION(EX_Precision); + if (control_word & CW_Precision) { /* The masked response */ + partial_status &= ~SW_C1; + partial_status |= SW_Precision; + } else + EXCEPTION(EX_Precision); } - asmlinkage int denormal_operand(void) { - if ( control_word & CW_Denormal ) - { /* The masked response */ - partial_status |= SW_Denorm_Op; - return TAG_Special; - } - else - { - EXCEPTION(EX_Denormal); - return TAG_Special | FPU_Exception; - } + if (control_word & CW_Denormal) { /* The masked response */ + partial_status |= SW_Denorm_Op; + return TAG_Special; + } else { + EXCEPTION(EX_Denormal); + return TAG_Special | FPU_Exception; + } } - -asmlinkage int arith_overflow(FPU_REG *dest) +asmlinkage int arith_overflow(FPU_REG * dest) { - int tag = TAG_Valid; + int tag = TAG_Valid; - if ( control_word & CW_Overflow ) - { - /* The masked response */ + if (control_word & CW_Overflow) { + /* The masked response */ /* ###### The response here depends upon the rounding mode */ - reg_copy(&CONST_INF, dest); - tag = TAG_Special; - } - else - { - /* Subtract the magic number from the exponent */ - addexponent(dest, (-3 * (1 << 13))); - } + reg_copy(&CONST_INF, dest); + tag = TAG_Special; + } else { + /* Subtract the magic number from the exponent */ + addexponent(dest, (-3 * (1 << 13))); + } - EXCEPTION(EX_Overflow); - if ( control_word & CW_Overflow ) - { - /* The overflow exception is masked. */ - /* By definition, precision is lost. - The roundup bit (C1) is also set because we have - "rounded" upwards to Infinity. */ - EXCEPTION(EX_Precision | SW_C1); - return tag; - } + EXCEPTION(EX_Overflow); + if (control_word & CW_Overflow) { + /* The overflow exception is masked. */ + /* By definition, precision is lost. + The roundup bit (C1) is also set because we have + "rounded" upwards to Infinity. */ + EXCEPTION(EX_Precision | SW_C1); + return tag; + } - return tag; + return tag; } - -asmlinkage int arith_underflow(FPU_REG *dest) +asmlinkage int arith_underflow(FPU_REG * dest) { - int tag = TAG_Valid; + int tag = TAG_Valid; - if ( control_word & CW_Underflow ) - { - /* The masked response */ - if ( exponent16(dest) <= EXP_UNDER - 63 ) - { - reg_copy(&CONST_Z, dest); - partial_status &= ~SW_C1; /* Round down. */ - tag = TAG_Zero; + if (control_word & CW_Underflow) { + /* The masked response */ + if (exponent16(dest) <= EXP_UNDER - 63) { + reg_copy(&CONST_Z, dest); + partial_status &= ~SW_C1; /* Round down. */ + tag = TAG_Zero; + } else { + stdexp(dest); + } + } else { + /* Add the magic number to the exponent. */ + addexponent(dest, (3 * (1 << 13)) + EXTENDED_Ebias); } - else - { - stdexp(dest); + + EXCEPTION(EX_Underflow); + if (control_word & CW_Underflow) { + /* The underflow exception is masked. */ + EXCEPTION(EX_Precision); + return tag; } - } - else - { - /* Add the magic number to the exponent. */ - addexponent(dest, (3 * (1 << 13)) + EXTENDED_Ebias); - } - EXCEPTION(EX_Underflow); - if ( control_word & CW_Underflow ) - { - /* The underflow exception is masked. */ - EXCEPTION(EX_Precision); - return tag; - } - - return tag; + return tag; } - void FPU_stack_overflow(void) { - if ( control_word & CW_Invalid ) - { - /* The masked response */ - top--; - FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); - } + if (control_word & CW_Invalid) { + /* The masked response */ + top--; + FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); + } - EXCEPTION(EX_StackOver); + EXCEPTION(EX_StackOver); - return; + return; } - void FPU_stack_underflow(void) { - if ( control_word & CW_Invalid ) - { - /* The masked response */ - FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); - } + if (control_word & CW_Invalid) { + /* The masked response */ + FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); + } - EXCEPTION(EX_StackUnder); + EXCEPTION(EX_StackUnder); - return; + return; } - void FPU_stack_underflow_i(int i) { - if ( control_word & CW_Invalid ) - { - /* The masked response */ - FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i); - } + if (control_word & CW_Invalid) { + /* The masked response */ + FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i); + } - EXCEPTION(EX_StackUnder); + EXCEPTION(EX_StackUnder); - return; + return; } - void FPU_stack_underflow_pop(int i) { - if ( control_word & CW_Invalid ) - { - /* The masked response */ - FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i); - FPU_pop(); - } + if (control_word & CW_Invalid) { + /* The masked response */ + FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i); + FPU_pop(); + } - EXCEPTION(EX_StackUnder); + EXCEPTION(EX_StackUnder); - return; + return; } - diff --git a/arch/x86/math-emu/exception.h b/arch/x86/math-emu/exception.h index b463f21a811e..67f43a4683d5 100644 --- a/arch/x86/math-emu/exception.h +++ b/arch/x86/math-emu/exception.h @@ -9,7 +9,6 @@ #ifndef _EXCEPTION_H_ #define _EXCEPTION_H_ - #ifdef __ASSEMBLY__ #define Const_(x) $##x #else @@ -20,8 +19,8 @@ #include "fpu_emu.h" #endif /* SW_C1 */ -#define FPU_BUSY Const_(0x8000) /* FPU busy bit (8087 compatibility) */ -#define EX_ErrorSummary Const_(0x0080) /* Error summary status */ +#define FPU_BUSY Const_(0x8000) /* FPU busy bit (8087 compatibility) */ +#define EX_ErrorSummary Const_(0x0080) /* Error summary status */ /* Special exceptions: */ #define EX_INTERNAL Const_(0x8000) /* Internal error in wm-FPU-emu */ #define EX_StackOver Const_(0x0041|SW_C1) /* stack overflow */ @@ -34,11 +33,9 @@ #define EX_Denormal Const_(0x0002) /* denormalized operand */ #define EX_Invalid Const_(0x0001) /* invalid operation */ - #define PRECISION_LOST_UP Const_((EX_Precision | SW_C1)) #define PRECISION_LOST_DOWN Const_(EX_Precision) - #ifndef __ASSEMBLY__ #ifdef DEBUG @@ -48,6 +45,6 @@ #define EXCEPTION(x) FPU_exception(x) #endif -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLY__ */ #endif /* _EXCEPTION_H_ */ diff --git a/arch/x86/math-emu/fpu_arith.c b/arch/x86/math-emu/fpu_arith.c index 6972dec01af6..aeab24e083c4 100644 --- a/arch/x86/math-emu/fpu_arith.c +++ b/arch/x86/math-emu/fpu_arith.c @@ -15,160 +15,138 @@ #include "control_w.h" #include "status_w.h" - void fadd__(void) { - /* fadd st,st(i) */ - int i = FPU_rm; - clear_C1(); - FPU_add(&st(i), FPU_gettagi(i), 0, control_word); + /* fadd st,st(i) */ + int i = FPU_rm; + clear_C1(); + FPU_add(&st(i), FPU_gettagi(i), 0, control_word); } - void fmul__(void) { - /* fmul st,st(i) */ - int i = FPU_rm; - clear_C1(); - FPU_mul(&st(i), FPU_gettagi(i), 0, control_word); + /* fmul st,st(i) */ + int i = FPU_rm; + clear_C1(); + FPU_mul(&st(i), FPU_gettagi(i), 0, control_word); } - - void fsub__(void) { - /* fsub st,st(i) */ - clear_C1(); - FPU_sub(0, FPU_rm, control_word); + /* fsub st,st(i) */ + clear_C1(); + FPU_sub(0, FPU_rm, control_word); } - void fsubr_(void) { - /* fsubr st,st(i) */ - clear_C1(); - FPU_sub(REV, FPU_rm, control_word); + /* fsubr st,st(i) */ + clear_C1(); + FPU_sub(REV, FPU_rm, control_word); } - void fdiv__(void) { - /* fdiv st,st(i) */ - clear_C1(); - FPU_div(0, FPU_rm, control_word); + /* fdiv st,st(i) */ + clear_C1(); + FPU_div(0, FPU_rm, control_word); } - void fdivr_(void) { - /* fdivr st,st(i) */ - clear_C1(); - FPU_div(REV, FPU_rm, control_word); + /* fdivr st,st(i) */ + clear_C1(); + FPU_div(REV, FPU_rm, control_word); } - - void fadd_i(void) { - /* fadd st(i),st */ - int i = FPU_rm; - clear_C1(); - FPU_add(&st(i), FPU_gettagi(i), i, control_word); + /* fadd st(i),st */ + int i = FPU_rm; + clear_C1(); + FPU_add(&st(i), FPU_gettagi(i), i, control_word); } - void fmul_i(void) { - /* fmul st(i),st */ - clear_C1(); - FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word); + /* fmul st(i),st */ + clear_C1(); + FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word); } - void fsubri(void) { - /* fsubr st(i),st */ - clear_C1(); - FPU_sub(DEST_RM, FPU_rm, control_word); + /* fsubr st(i),st */ + clear_C1(); + FPU_sub(DEST_RM, FPU_rm, control_word); } - void fsub_i(void) { - /* fsub st(i),st */ - clear_C1(); - FPU_sub(REV|DEST_RM, FPU_rm, control_word); + /* fsub st(i),st */ + clear_C1(); + FPU_sub(REV | DEST_RM, FPU_rm, control_word); } - void fdivri(void) { - /* fdivr st(i),st */ - clear_C1(); - FPU_div(DEST_RM, FPU_rm, control_word); + /* fdivr st(i),st */ + clear_C1(); + FPU_div(DEST_RM, FPU_rm, control_word); } - void fdiv_i(void) { - /* fdiv st(i),st */ - clear_C1(); - FPU_div(REV|DEST_RM, FPU_rm, control_word); + /* fdiv st(i),st */ + clear_C1(); + FPU_div(REV | DEST_RM, FPU_rm, control_word); } - - void faddp_(void) { - /* faddp st(i),st */ - int i = FPU_rm; - clear_C1(); - if ( FPU_add(&st(i), FPU_gettagi(i), i, control_word) >= 0 ) - FPU_pop(); + /* faddp st(i),st */ + int i = FPU_rm; + clear_C1(); + if (FPU_add(&st(i), FPU_gettagi(i), i, control_word) >= 0) + FPU_pop(); } - void fmulp_(void) { - /* fmulp st(i),st */ - clear_C1(); - if ( FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word) >= 0 ) - FPU_pop(); + /* fmulp st(i),st */ + clear_C1(); + if (FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word) >= 0) + FPU_pop(); } - - void fsubrp(void) { - /* fsubrp st(i),st */ - clear_C1(); - if ( FPU_sub(DEST_RM, FPU_rm, control_word) >= 0 ) - FPU_pop(); + /* fsubrp st(i),st */ + clear_C1(); + if (FPU_sub(DEST_RM, FPU_rm, control_word) >= 0) + FPU_pop(); } - void fsubp_(void) { - /* fsubp st(i),st */ - clear_C1(); - if ( FPU_sub(REV|DEST_RM, FPU_rm, control_word) >= 0 ) - FPU_pop(); + /* fsubp st(i),st */ + clear_C1(); + if (FPU_sub(REV | DEST_RM, FPU_rm, control_word) >= 0) + FPU_pop(); } - void fdivrp(void) { - /* fdivrp st(i),st */ - clear_C1(); - if ( FPU_div(DEST_RM, FPU_rm, control_word) >= 0 ) - FPU_pop(); + /* fdivrp st(i),st */ + clear_C1(); + if (FPU_div(DEST_RM, FPU_rm, control_word) >= 0) + FPU_pop(); } - void fdivp_(void) { - /* fdivp st(i),st */ - clear_C1(); - if ( FPU_div(REV|DEST_RM, FPU_rm, control_word) >= 0 ) - FPU_pop(); + /* fdivp st(i),st */ + clear_C1(); + if (FPU_div(REV | DEST_RM, FPU_rm, control_word) >= 0) + FPU_pop(); } diff --git a/arch/x86/math-emu/fpu_asm.h b/arch/x86/math-emu/fpu_asm.h index 9ba12416df12..955b932735a4 100644 --- a/arch/x86/math-emu/fpu_asm.h +++ b/arch/x86/math-emu/fpu_asm.h @@ -14,7 +14,6 @@ #define EXCEPTION FPU_exception - #define PARAM1 8(%ebp) #define PARAM2 12(%ebp) #define PARAM3 16(%ebp) diff --git a/arch/x86/math-emu/fpu_aux.c b/arch/x86/math-emu/fpu_aux.c index 20886cfb9f76..491e737ce547 100644 --- a/arch/x86/math-emu/fpu_aux.c +++ b/arch/x86/math-emu/fpu_aux.c @@ -16,34 +16,34 @@ #include "status_w.h" #include "control_w.h" - static void fnop(void) { } static void fclex(void) { - partial_status &= ~(SW_Backward|SW_Summary|SW_Stack_Fault|SW_Precision| - SW_Underflow|SW_Overflow|SW_Zero_Div|SW_Denorm_Op| - SW_Invalid); - no_ip_update = 1; + partial_status &= + ~(SW_Backward | SW_Summary | SW_Stack_Fault | SW_Precision | + SW_Underflow | SW_Overflow | SW_Zero_Div | SW_Denorm_Op | + SW_Invalid); + no_ip_update = 1; } /* Needs to be externally visible */ void finit(void) { - control_word = 0x037f; - partial_status = 0; - top = 0; /* We don't keep top in the status word internally. */ - fpu_tag_word = 0xffff; - /* The behaviour is different from that detailed in - Section 15.1.6 of the Intel manual */ - operand_address.offset = 0; - operand_address.selector = 0; - instruction_address.offset = 0; - instruction_address.selector = 0; - instruction_address.opcode = 0; - no_ip_update = 1; + control_word = 0x037f; + partial_status = 0; + top = 0; /* We don't keep top in the status word internally. */ + fpu_tag_word = 0xffff; + /* The behaviour is different from that detailed in + Section 15.1.6 of the Intel manual */ + operand_address.offset = 0; + operand_address.selector = 0; + instruction_address.offset = 0; + instruction_address.selector = 0; + instruction_address.opcode = 0; + no_ip_update = 1; } /* @@ -54,151 +54,134 @@ void finit(void) #define fsetpm fnop static FUNC const finit_table[] = { - feni, fdisi, fclex, finit, - fsetpm, FPU_illegal, FPU_illegal, FPU_illegal + feni, fdisi, fclex, finit, + fsetpm, FPU_illegal, FPU_illegal, FPU_illegal }; void finit_(void) { - (finit_table[FPU_rm])(); + (finit_table[FPU_rm]) (); } - static void fstsw_ax(void) { - *(short *) &FPU_EAX = status_word(); - no_ip_update = 1; + *(short *)&FPU_EAX = status_word(); + no_ip_update = 1; } static FUNC const fstsw_table[] = { - fstsw_ax, FPU_illegal, FPU_illegal, FPU_illegal, - FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal + fstsw_ax, FPU_illegal, FPU_illegal, FPU_illegal, + FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal }; void fstsw_(void) { - (fstsw_table[FPU_rm])(); + (fstsw_table[FPU_rm]) (); } - static FUNC const fp_nop_table[] = { - fnop, FPU_illegal, FPU_illegal, FPU_illegal, - FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal + fnop, FPU_illegal, FPU_illegal, FPU_illegal, + FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal }; void fp_nop(void) { - (fp_nop_table[FPU_rm])(); + (fp_nop_table[FPU_rm]) (); } - void fld_i_(void) { - FPU_REG *st_new_ptr; - int i; - u_char tag; + FPU_REG *st_new_ptr; + int i; + u_char tag; - if ( STACK_OVERFLOW ) - { FPU_stack_overflow(); return; } - - /* fld st(i) */ - i = FPU_rm; - if ( NOT_EMPTY(i) ) - { - reg_copy(&st(i), st_new_ptr); - tag = FPU_gettagi(i); - push(); - FPU_settag0(tag); - } - else - { - if ( control_word & CW_Invalid ) - { - /* The masked response */ - FPU_stack_underflow(); + if (STACK_OVERFLOW) { + FPU_stack_overflow(); + return; + } + + /* fld st(i) */ + i = FPU_rm; + if (NOT_EMPTY(i)) { + reg_copy(&st(i), st_new_ptr); + tag = FPU_gettagi(i); + push(); + FPU_settag0(tag); + } else { + if (control_word & CW_Invalid) { + /* The masked response */ + FPU_stack_underflow(); + } else + EXCEPTION(EX_StackUnder); } - else - EXCEPTION(EX_StackUnder); - } } - void fxch_i(void) { - /* fxch st(i) */ - FPU_REG t; - int i = FPU_rm; - FPU_REG *st0_ptr = &st(0), *sti_ptr = &st(i); - long tag_word = fpu_tag_word; - int regnr = top & 7, regnri = ((regnr + i) & 7); - u_char st0_tag = (tag_word >> (regnr*2)) & 3; - u_char sti_tag = (tag_word >> (regnri*2)) & 3; + /* fxch st(i) */ + FPU_REG t; + int i = FPU_rm; + FPU_REG *st0_ptr = &st(0), *sti_ptr = &st(i); + long tag_word = fpu_tag_word; + int regnr = top & 7, regnri = ((regnr + i) & 7); + u_char st0_tag = (tag_word >> (regnr * 2)) & 3; + u_char sti_tag = (tag_word >> (regnri * 2)) & 3; - if ( st0_tag == TAG_Empty ) - { - if ( sti_tag == TAG_Empty ) - { - FPU_stack_underflow(); - FPU_stack_underflow_i(i); - return; + if (st0_tag == TAG_Empty) { + if (sti_tag == TAG_Empty) { + FPU_stack_underflow(); + FPU_stack_underflow_i(i); + return; + } + if (control_word & CW_Invalid) { + /* Masked response */ + FPU_copy_to_reg0(sti_ptr, sti_tag); + } + FPU_stack_underflow_i(i); + return; } - if ( control_word & CW_Invalid ) - { - /* Masked response */ - FPU_copy_to_reg0(sti_ptr, sti_tag); + if (sti_tag == TAG_Empty) { + if (control_word & CW_Invalid) { + /* Masked response */ + FPU_copy_to_regi(st0_ptr, st0_tag, i); + } + FPU_stack_underflow(); + return; } - FPU_stack_underflow_i(i); - return; - } - if ( sti_tag == TAG_Empty ) - { - if ( control_word & CW_Invalid ) - { - /* Masked response */ - FPU_copy_to_regi(st0_ptr, st0_tag, i); - } - FPU_stack_underflow(); - return; - } - clear_C1(); + clear_C1(); - reg_copy(st0_ptr, &t); - reg_copy(sti_ptr, st0_ptr); - reg_copy(&t, sti_ptr); + reg_copy(st0_ptr, &t); + reg_copy(sti_ptr, st0_ptr); + reg_copy(&t, sti_ptr); - tag_word &= ~(3 << (regnr*2)) & ~(3 << (regnri*2)); - tag_word |= (sti_tag << (regnr*2)) | (st0_tag << (regnri*2)); - fpu_tag_word = tag_word; + tag_word &= ~(3 << (regnr * 2)) & ~(3 << (regnri * 2)); + tag_word |= (sti_tag << (regnr * 2)) | (st0_tag << (regnri * 2)); + fpu_tag_word = tag_word; } - void ffree_(void) { - /* ffree st(i) */ - FPU_settagi(FPU_rm, TAG_Empty); + /* ffree st(i) */ + FPU_settagi(FPU_rm, TAG_Empty); } - void ffreep(void) { - /* ffree st(i) + pop - unofficial code */ - FPU_settagi(FPU_rm, TAG_Empty); - FPU_pop(); + /* ffree st(i) + pop - unofficial code */ + FPU_settagi(FPU_rm, TAG_Empty); + FPU_pop(); } - void fst_i_(void) { - /* fst st(i) */ - FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm); + /* fst st(i) */ + FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm); } - void fstp_i(void) { - /* fstp st(i) */ - FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm); - FPU_pop(); + /* fstp st(i) */ + FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm); + FPU_pop(); } - diff --git a/arch/x86/math-emu/fpu_emu.h b/arch/x86/math-emu/fpu_emu.h index 65120f523853..656dd4c04b1b 100644 --- a/arch/x86/math-emu/fpu_emu.h +++ b/arch/x86/math-emu/fpu_emu.h @@ -7,7 +7,6 @@ | | +---------------------------------------------------------------------------*/ - #ifndef _FPU_EMU_H_ #define _FPU_EMU_H_ @@ -28,15 +27,15 @@ #endif #define EXP_BIAS Const(0) -#define EXP_OVER Const(0x4000) /* smallest invalid large exponent */ -#define EXP_UNDER Const(-0x3fff) /* largest invalid small exponent */ -#define EXP_WAY_UNDER Const(-0x6000) /* Below the smallest denormal, but - still a 16 bit nr. */ +#define EXP_OVER Const(0x4000) /* smallest invalid large exponent */ +#define EXP_UNDER Const(-0x3fff) /* largest invalid small exponent */ +#define EXP_WAY_UNDER Const(-0x6000) /* Below the smallest denormal, but + still a 16 bit nr. */ #define EXP_Infinity EXP_OVER #define EXP_NaN EXP_OVER #define EXTENDED_Ebias Const(0x3fff) -#define EXTENDED_Emin (-0x3ffe) /* smallest valid exponent */ +#define EXTENDED_Emin (-0x3ffe) /* smallest valid exponent */ #define SIGN_POS Const(0) #define SIGN_NEG Const(0x80) @@ -44,10 +43,9 @@ #define SIGN_Positive Const(0) #define SIGN_Negative Const(0x8000) - /* Keep the order TAG_Valid, TAG_Zero, TW_Denormal */ /* The following fold to 2 (Special) in the Tag Word */ -#define TW_Denormal Const(4) /* De-normal */ +#define TW_Denormal Const(4) /* De-normal */ #define TW_Infinity Const(5) /* + or - infinity */ #define TW_NaN Const(6) /* Not a Number */ #define TW_Unsupported Const(7) /* Not supported by an 80486 */ @@ -67,14 +65,13 @@ #define DEST_RM 0x20 #define LOADED 0x40 -#define FPU_Exception Const(0x80000000) /* Added to tag returns. */ - +#define FPU_Exception Const(0x80000000) /* Added to tag returns. */ #ifndef __ASSEMBLY__ #include "fpu_system.h" -#include /* for struct _fpstate */ +#include /* for struct _fpstate */ #include #include @@ -112,30 +109,33 @@ extern u_char emulating; #define PREFIX_DEFAULT 7 struct address { - unsigned int offset; - unsigned int selector:16; - unsigned int opcode:11; - unsigned int empty:5; + unsigned int offset; + unsigned int selector:16; + unsigned int opcode:11; + unsigned int empty:5; }; struct fpu__reg { - unsigned sigl; - unsigned sigh; - short exp; + unsigned sigl; + unsigned sigh; + short exp; }; -typedef void (*FUNC)(void); +typedef void (*FUNC) (void); typedef struct fpu__reg FPU_REG; -typedef void (*FUNC_ST0)(FPU_REG *st0_ptr, u_char st0_tag); -typedef struct { u_char address_size, operand_size, segment; } - overrides; +typedef void (*FUNC_ST0) (FPU_REG * st0_ptr, u_char st0_tag); +typedef struct { + u_char address_size, operand_size, segment; +} overrides; /* This structure is 32 bits: */ -typedef struct { overrides override; - u_char default_mode; } fpu_addr_modes; +typedef struct { + overrides override; + u_char default_mode; +} fpu_addr_modes; /* PROTECTED has a restricted meaning in the emulator; it is used to signal that the emulator needs to do special things to ensure that protection is respected in a segmented model. */ #define PROTECTED 4 -#define SIXTEEN 1 /* We rely upon this being 1 (true) */ +#define SIXTEEN 1 /* We rely upon this being 1 (true) */ #define VM86 SIXTEEN #define PM16 (SIXTEEN | PROTECTED) #define SEG32 PROTECTED @@ -166,10 +166,10 @@ extern u_char const data_sizes_16[32]; #define signpositive(a) ( (signbyte(a) & 0x80) == 0 ) #define signnegative(a) (signbyte(a) & 0x80) -static inline void reg_copy(FPU_REG const *x, FPU_REG *y) +static inline void reg_copy(FPU_REG const *x, FPU_REG * y) { - *(short *)&(y->exp) = *(const short *)&(x->exp); - *(long long *)&(y->sigl) = *(const long long *)&(x->sigl); + *(short *)&(y->exp) = *(const short *)&(x->exp); + *(long long *)&(y->sigl) = *(const long long *)&(x->sigl); } #define exponent(x) (((*(short *)&((x)->exp)) & 0x7fff) - EXTENDED_Ebias) @@ -184,29 +184,28 @@ static inline void reg_copy(FPU_REG const *x, FPU_REG *y) #define significand(x) ( ((unsigned long long *)&((x)->sigl))[0] ) - /*----- Prototypes for functions written in assembler -----*/ /* extern void reg_move(FPU_REG *a, FPU_REG *b); */ -asmlinkage int FPU_normalize(FPU_REG *x); -asmlinkage int FPU_normalize_nuo(FPU_REG *x); +asmlinkage int FPU_normalize(FPU_REG * x); +asmlinkage int FPU_normalize_nuo(FPU_REG * x); asmlinkage int FPU_u_sub(FPU_REG const *arg1, FPU_REG const *arg2, - FPU_REG *answ, unsigned int control_w, u_char sign, + FPU_REG * answ, unsigned int control_w, u_char sign, int expa, int expb); asmlinkage int FPU_u_mul(FPU_REG const *arg1, FPU_REG const *arg2, - FPU_REG *answ, unsigned int control_w, u_char sign, + FPU_REG * answ, unsigned int control_w, u_char sign, int expon); asmlinkage int FPU_u_div(FPU_REG const *arg1, FPU_REG const *arg2, - FPU_REG *answ, unsigned int control_w, u_char sign); + FPU_REG * answ, unsigned int control_w, u_char sign); asmlinkage int FPU_u_add(FPU_REG const *arg1, FPU_REG const *arg2, - FPU_REG *answ, unsigned int control_w, u_char sign, + FPU_REG * answ, unsigned int control_w, u_char sign, int expa, int expb); -asmlinkage int wm_sqrt(FPU_REG *n, int dummy1, int dummy2, +asmlinkage int wm_sqrt(FPU_REG * n, int dummy1, int dummy2, unsigned int control_w, u_char sign); -asmlinkage unsigned FPU_shrx(void *l, unsigned x); -asmlinkage unsigned FPU_shrxs(void *v, unsigned x); +asmlinkage unsigned FPU_shrx(void *l, unsigned x); +asmlinkage unsigned FPU_shrxs(void *v, unsigned x); asmlinkage unsigned long FPU_div_small(unsigned long long *x, unsigned long y); -asmlinkage int FPU_round(FPU_REG *arg, unsigned int extent, int dummy, +asmlinkage int FPU_round(FPU_REG * arg, unsigned int extent, int dummy, unsigned int control_w, u_char sign); #ifndef MAKING_PROTO diff --git a/arch/x86/math-emu/fpu_entry.c b/arch/x86/math-emu/fpu_entry.c index 1853524c8b57..cbb8717f09fd 100644 --- a/arch/x86/math-emu/fpu_entry.c +++ b/arch/x86/math-emu/fpu_entry.c @@ -36,726 +36,720 @@ #include "control_w.h" #include "status_w.h" -#define __BAD__ FPU_illegal /* Illegal on an 80486, causes SIGILL */ +#define __BAD__ FPU_illegal /* Illegal on an 80486, causes SIGILL */ -#ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by default. */ +#ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by default. */ /* WARNING: These codes are not documented by Intel in their 80486 manual and may not work on FPU clones or later Intel FPUs. */ /* Changes to support the un-doc codes provided by Linus Torvalds. */ -#define _d9_d8_ fstp_i /* unofficial code (19) */ -#define _dc_d0_ fcom_st /* unofficial code (14) */ -#define _dc_d8_ fcompst /* unofficial code (1c) */ -#define _dd_c8_ fxch_i /* unofficial code (0d) */ -#define _de_d0_ fcompst /* unofficial code (16) */ -#define _df_c0_ ffreep /* unofficial code (07) ffree + pop */ -#define _df_c8_ fxch_i /* unofficial code (0f) */ -#define _df_d0_ fstp_i /* unofficial code (17) */ -#define _df_d8_ fstp_i /* unofficial code (1f) */ +#define _d9_d8_ fstp_i /* unofficial code (19) */ +#define _dc_d0_ fcom_st /* unofficial code (14) */ +#define _dc_d8_ fcompst /* unofficial code (1c) */ +#define _dd_c8_ fxch_i /* unofficial code (0d) */ +#define _de_d0_ fcompst /* unofficial code (16) */ +#define _df_c0_ ffreep /* unofficial code (07) ffree + pop */ +#define _df_c8_ fxch_i /* unofficial code (0f) */ +#define _df_d0_ fstp_i /* unofficial code (17) */ +#define _df_d8_ fstp_i /* unofficial code (1f) */ static FUNC const st_instr_table[64] = { - fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_, - fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_, - fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_, - fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_, - fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_, - fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__, - fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__, - fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__, + fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_, + fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_, + fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_, + fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_, + fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_, + fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__, + fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__, + fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__, }; -#else /* Support only documented FPU op-codes */ +#else /* Support only documented FPU op-codes */ static FUNC const st_instr_table[64] = { - fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__, - fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__, - fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__, - fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__, - fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_, - fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__, - fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__, - fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__, + fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__, + fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__, + fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__, + fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__, + fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_, + fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__, + fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__, + fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__, }; #endif /* NO_UNDOC_CODE */ - -#define _NONE_ 0 /* Take no special action */ -#define _REG0_ 1 /* Need to check for not empty st(0) */ -#define _REGI_ 2 /* Need to check for not empty st(0) and st(rm) */ -#define _REGi_ 0 /* Uses st(rm) */ -#define _PUSH_ 3 /* Need to check for space to push onto stack */ -#define _null_ 4 /* Function illegal or not implemented */ -#define _REGIi 5 /* Uses st(0) and st(rm), result to st(rm) */ -#define _REGIp 6 /* Uses st(0) and st(rm), result to st(rm) then pop */ -#define _REGIc 0 /* Compare st(0) and st(rm) */ -#define _REGIn 0 /* Uses st(0) and st(rm), but handle checks later */ +#define _NONE_ 0 /* Take no special action */ +#define _REG0_ 1 /* Need to check for not empty st(0) */ +#define _REGI_ 2 /* Need to check for not empty st(0) and st(rm) */ +#define _REGi_ 0 /* Uses st(rm) */ +#define _PUSH_ 3 /* Need to check for space to push onto stack */ +#define _null_ 4 /* Function illegal or not implemented */ +#define _REGIi 5 /* Uses st(0) and st(rm), result to st(rm) */ +#define _REGIp 6 /* Uses st(0) and st(rm), result to st(rm) then pop */ +#define _REGIc 0 /* Compare st(0) and st(rm) */ +#define _REGIn 0 /* Uses st(0) and st(rm), but handle checks later */ #ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by default. (see above) */ static u_char const type_table[64] = { - _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_, - _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_, - _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_, - _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_, - _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_, - _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_ + _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_, + _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_, + _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_, + _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_, + _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_, + _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_, + _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_, + _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_ }; -#else /* Support only documented FPU op-codes */ +#else /* Support only documented FPU op-codes */ static u_char const type_table[64] = { - _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_, - _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_, - _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_, - _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_, - _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_ + _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_, + _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_, + _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_, + _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_, + _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_, + _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_, + _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_, + _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_ }; #endif /* NO_UNDOC_CODE */ - #ifdef RE_ENTRANT_CHECKING -u_char emulating=0; +u_char emulating = 0; #endif /* RE_ENTRANT_CHECKING */ -static int valid_prefix(u_char *Byte, u_char __user **fpu_eip, - overrides *override); +static int valid_prefix(u_char * Byte, u_char __user ** fpu_eip, + overrides * override); asmlinkage void math_emulate(long arg) { - u_char FPU_modrm, byte1; - unsigned short code; - fpu_addr_modes addr_modes; - int unmasked; - FPU_REG loaded_data; - FPU_REG *st0_ptr; - u_char loaded_tag, st0_tag; - void __user *data_address; - struct address data_sel_off; - struct address entry_sel_off; - unsigned long code_base = 0; - unsigned long code_limit = 0; /* Initialized to stop compiler warnings */ - struct desc_struct code_descriptor; + u_char FPU_modrm, byte1; + unsigned short code; + fpu_addr_modes addr_modes; + int unmasked; + FPU_REG loaded_data; + FPU_REG *st0_ptr; + u_char loaded_tag, st0_tag; + void __user *data_address; + struct address data_sel_off; + struct address entry_sel_off; + unsigned long code_base = 0; + unsigned long code_limit = 0; /* Initialized to stop compiler warnings */ + struct desc_struct code_descriptor; #ifdef RE_ENTRANT_CHECKING - if ( emulating ) - { - printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n"); - } - RE_ENTRANT_CHECK_ON; + if (emulating) { + printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n"); + } + RE_ENTRANT_CHECK_ON; #endif /* RE_ENTRANT_CHECKING */ - if (!used_math()) - { - finit(); - set_used_math(); - } - - SETUP_DATA_AREA(arg); - - FPU_ORIG_EIP = FPU_EIP; - - if ( (FPU_EFLAGS & 0x00020000) != 0 ) - { - /* Virtual 8086 mode */ - addr_modes.default_mode = VM86; - FPU_EIP += code_base = FPU_CS << 4; - code_limit = code_base + 0xffff; /* Assumes code_base <= 0xffff0000 */ - } - else if ( FPU_CS == __USER_CS && FPU_DS == __USER_DS ) - { - addr_modes.default_mode = 0; - } - else if ( FPU_CS == __KERNEL_CS ) - { - printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP); - panic("Math emulation needed in kernel"); - } - else - { - - if ( (FPU_CS & 4) != 4 ) /* Must be in the LDT */ - { - /* Can only handle segmented addressing via the LDT - for now, and it must be 16 bit */ - printk("FPU emulator: Unsupported addressing mode\n"); - math_abort(FPU_info, SIGILL); + if (!used_math()) { + finit(); + set_used_math(); } - code_descriptor = LDT_DESCRIPTOR(FPU_CS); - if ( SEG_D_SIZE(code_descriptor) ) - { - /* The above test may be wrong, the book is not clear */ - /* Segmented 32 bit protected mode */ - addr_modes.default_mode = SEG32; + SETUP_DATA_AREA(arg); + + FPU_ORIG_EIP = FPU_EIP; + + if ((FPU_EFLAGS & 0x00020000) != 0) { + /* Virtual 8086 mode */ + addr_modes.default_mode = VM86; + FPU_EIP += code_base = FPU_CS << 4; + code_limit = code_base + 0xffff; /* Assumes code_base <= 0xffff0000 */ + } else if (FPU_CS == __USER_CS && FPU_DS == __USER_DS) { + addr_modes.default_mode = 0; + } else if (FPU_CS == __KERNEL_CS) { + printk("math_emulate: %04x:%08lx\n", FPU_CS, FPU_EIP); + panic("Math emulation needed in kernel"); + } else { + + if ((FPU_CS & 4) != 4) { /* Must be in the LDT */ + /* Can only handle segmented addressing via the LDT + for now, and it must be 16 bit */ + printk("FPU emulator: Unsupported addressing mode\n"); + math_abort(FPU_info, SIGILL); + } + + code_descriptor = LDT_DESCRIPTOR(FPU_CS); + if (SEG_D_SIZE(code_descriptor)) { + /* The above test may be wrong, the book is not clear */ + /* Segmented 32 bit protected mode */ + addr_modes.default_mode = SEG32; + } else { + /* 16 bit protected mode */ + addr_modes.default_mode = PM16; + } + FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor); + code_limit = code_base + + (SEG_LIMIT(code_descriptor) + + 1) * SEG_GRANULARITY(code_descriptor) + - 1; + if (code_limit < code_base) + code_limit = 0xffffffff; } - else - { - /* 16 bit protected mode */ - addr_modes.default_mode = PM16; + + FPU_lookahead = 1; + if (current->ptrace & PT_PTRACED) + FPU_lookahead = 0; + + if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP, + &addr_modes.override)) { + RE_ENTRANT_CHECK_OFF; + printk + ("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n" + "FPU emulator: self-modifying code! (emulation impossible)\n", + byte1); + RE_ENTRANT_CHECK_ON; + EXCEPTION(EX_INTERNAL | 0x126); + math_abort(FPU_info, SIGILL); } - FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor); - code_limit = code_base - + (SEG_LIMIT(code_descriptor)+1) * SEG_GRANULARITY(code_descriptor) - - 1; - if ( code_limit < code_base ) code_limit = 0xffffffff; - } - FPU_lookahead = 1; - if (current->ptrace & PT_PTRACED) - FPU_lookahead = 0; + do_another_FPU_instruction: - if ( !valid_prefix(&byte1, (u_char __user **)&FPU_EIP, - &addr_modes.override) ) - { - RE_ENTRANT_CHECK_OFF; - printk("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n" - "FPU emulator: self-modifying code! (emulation impossible)\n", - byte1); - RE_ENTRANT_CHECK_ON; - EXCEPTION(EX_INTERNAL|0x126); - math_abort(FPU_info,SIGILL); - } + no_ip_update = 0; -do_another_FPU_instruction: + FPU_EIP++; /* We have fetched the prefix and first code bytes. */ - no_ip_update = 0; - - FPU_EIP++; /* We have fetched the prefix and first code bytes. */ - - if ( addr_modes.default_mode ) - { - /* This checks for the minimum instruction bytes. - We also need to check any extra (address mode) code access. */ - if ( FPU_EIP > code_limit ) - math_abort(FPU_info,SIGSEGV); - } - - if ( (byte1 & 0xf8) != 0xd8 ) - { - if ( byte1 == FWAIT_OPCODE ) - { - if (partial_status & SW_Summary) - goto do_the_FPU_interrupt; - else - goto FPU_fwait_done; + if (addr_modes.default_mode) { + /* This checks for the minimum instruction bytes. + We also need to check any extra (address mode) code access. */ + if (FPU_EIP > code_limit) + math_abort(FPU_info, SIGSEGV); } + + if ((byte1 & 0xf8) != 0xd8) { + if (byte1 == FWAIT_OPCODE) { + if (partial_status & SW_Summary) + goto do_the_FPU_interrupt; + else + goto FPU_fwait_done; + } #ifdef PARANOID - EXCEPTION(EX_INTERNAL|0x128); - math_abort(FPU_info,SIGILL); + EXCEPTION(EX_INTERNAL | 0x128); + math_abort(FPU_info, SIGILL); #endif /* PARANOID */ - } - - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(1); - FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP); - RE_ENTRANT_CHECK_ON; - FPU_EIP++; - - if (partial_status & SW_Summary) - { - /* Ignore the error for now if the current instruction is a no-wait - control instruction */ - /* The 80486 manual contradicts itself on this topic, - but a real 80486 uses the following instructions: - fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex. - */ - code = (FPU_modrm << 8) | byte1; - if ( ! ( (((code & 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */ - (((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, fnstenv, - fnstsw */ - ((code & 0xc000) != 0xc000))) ) ) - { - /* - * We need to simulate the action of the kernel to FPU - * interrupts here. - */ - do_the_FPU_interrupt: - - FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */ - - RE_ENTRANT_CHECK_OFF; - current->thread.trap_no = 16; - current->thread.error_code = 0; - send_sig(SIGFPE, current, 1); - return; - } - } - - entry_sel_off.offset = FPU_ORIG_EIP; - entry_sel_off.selector = FPU_CS; - entry_sel_off.opcode = (byte1 << 8) | FPU_modrm; - - FPU_rm = FPU_modrm & 7; - - if ( FPU_modrm < 0300 ) - { - /* All of these instructions use the mod/rm byte to get a data address */ - - if ( (addr_modes.default_mode & SIXTEEN) - ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX) ) - data_address = FPU_get_address_16(FPU_modrm, &FPU_EIP, &data_sel_off, - addr_modes); - else - data_address = FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off, - addr_modes); - - if ( addr_modes.default_mode ) - { - if ( FPU_EIP-1 > code_limit ) - math_abort(FPU_info,SIGSEGV); } - if ( !(byte1 & 1) ) - { - unsigned short status1 = partial_status; + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(1); + FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP); + RE_ENTRANT_CHECK_ON; + FPU_EIP++; - st0_ptr = &st(0); - st0_tag = FPU_gettag0(); + if (partial_status & SW_Summary) { + /* Ignore the error for now if the current instruction is a no-wait + control instruction */ + /* The 80486 manual contradicts itself on this topic, + but a real 80486 uses the following instructions: + fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex. + */ + code = (FPU_modrm << 8) | byte1; + if (!((((code & 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */ + (((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, fnstenv, + fnstsw */ + ((code & 0xc000) != 0xc000))))) { + /* + * We need to simulate the action of the kernel to FPU + * interrupts here. + */ + do_the_FPU_interrupt: - /* Stack underflow has priority */ - if ( NOT_EMPTY_ST0 ) - { - if ( addr_modes.default_mode & PROTECTED ) - { - /* This table works for 16 and 32 bit protected mode */ - if ( access_limit < data_sizes_16[(byte1 >> 1) & 3] ) - math_abort(FPU_info,SIGSEGV); + FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */ + + RE_ENTRANT_CHECK_OFF; + current->thread.trap_no = 16; + current->thread.error_code = 0; + send_sig(SIGFPE, current, 1); + return; + } + } + + entry_sel_off.offset = FPU_ORIG_EIP; + entry_sel_off.selector = FPU_CS; + entry_sel_off.opcode = (byte1 << 8) | FPU_modrm; + + FPU_rm = FPU_modrm & 7; + + if (FPU_modrm < 0300) { + /* All of these instructions use the mod/rm byte to get a data address */ + + if ((addr_modes.default_mode & SIXTEEN) + ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX)) + data_address = + FPU_get_address_16(FPU_modrm, &FPU_EIP, + &data_sel_off, addr_modes); + else + data_address = + FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off, + addr_modes); + + if (addr_modes.default_mode) { + if (FPU_EIP - 1 > code_limit) + math_abort(FPU_info, SIGSEGV); } - unmasked = 0; /* Do this here to stop compiler warnings. */ - switch ( (byte1 >> 1) & 3 ) - { - case 0: - unmasked = FPU_load_single((float __user *)data_address, - &loaded_data); - loaded_tag = unmasked & 0xff; - unmasked &= ~0xff; - break; - case 1: - loaded_tag = FPU_load_int32((long __user *)data_address, &loaded_data); - break; - case 2: - unmasked = FPU_load_double((double __user *)data_address, - &loaded_data); - loaded_tag = unmasked & 0xff; - unmasked &= ~0xff; - break; - case 3: - default: /* Used here to suppress gcc warnings. */ - loaded_tag = FPU_load_int16((short __user *)data_address, &loaded_data); - break; - } + if (!(byte1 & 1)) { + unsigned short status1 = partial_status; - /* No more access to user memory, it is safe - to use static data now */ + st0_ptr = &st(0); + st0_tag = FPU_gettag0(); - /* NaN operands have the next priority. */ - /* We have to delay looking at st(0) until after - loading the data, because that data might contain an SNaN */ - if ( ((st0_tag == TAG_Special) && isNaN(st0_ptr)) || - ((loaded_tag == TAG_Special) && isNaN(&loaded_data)) ) - { - /* Restore the status word; we might have loaded a - denormal. */ - partial_status = status1; - if ( (FPU_modrm & 0x30) == 0x10 ) - { - /* fcom or fcomp */ - EXCEPTION(EX_Invalid); - setcc(SW_C3 | SW_C2 | SW_C0); - if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) ) - FPU_pop(); /* fcomp, masked, so we pop. */ - } - else - { - if ( loaded_tag == TAG_Special ) - loaded_tag = FPU_Special(&loaded_data); + /* Stack underflow has priority */ + if (NOT_EMPTY_ST0) { + if (addr_modes.default_mode & PROTECTED) { + /* This table works for 16 and 32 bit protected mode */ + if (access_limit < + data_sizes_16[(byte1 >> 1) & 3]) + math_abort(FPU_info, SIGSEGV); + } + + unmasked = 0; /* Do this here to stop compiler warnings. */ + switch ((byte1 >> 1) & 3) { + case 0: + unmasked = + FPU_load_single((float __user *) + data_address, + &loaded_data); + loaded_tag = unmasked & 0xff; + unmasked &= ~0xff; + break; + case 1: + loaded_tag = + FPU_load_int32((long __user *) + data_address, + &loaded_data); + break; + case 2: + unmasked = + FPU_load_double((double __user *) + data_address, + &loaded_data); + loaded_tag = unmasked & 0xff; + unmasked &= ~0xff; + break; + case 3: + default: /* Used here to suppress gcc warnings. */ + loaded_tag = + FPU_load_int16((short __user *) + data_address, + &loaded_data); + break; + } + + /* No more access to user memory, it is safe + to use static data now */ + + /* NaN operands have the next priority. */ + /* We have to delay looking at st(0) until after + loading the data, because that data might contain an SNaN */ + if (((st0_tag == TAG_Special) && isNaN(st0_ptr)) + || ((loaded_tag == TAG_Special) + && isNaN(&loaded_data))) { + /* Restore the status word; we might have loaded a + denormal. */ + partial_status = status1; + if ((FPU_modrm & 0x30) == 0x10) { + /* fcom or fcomp */ + EXCEPTION(EX_Invalid); + setcc(SW_C3 | SW_C2 | SW_C0); + if ((FPU_modrm & 0x08) + && (control_word & + CW_Invalid)) + FPU_pop(); /* fcomp, masked, so we pop. */ + } else { + if (loaded_tag == TAG_Special) + loaded_tag = + FPU_Special + (&loaded_data); #ifdef PECULIAR_486 - /* This is not really needed, but gives behaviour - identical to an 80486 */ - if ( (FPU_modrm & 0x28) == 0x20 ) - /* fdiv or fsub */ - real_2op_NaN(&loaded_data, loaded_tag, 0, &loaded_data); - else -#endif /* PECULIAR_486 */ - /* fadd, fdivr, fmul, or fsubr */ - real_2op_NaN(&loaded_data, loaded_tag, 0, st0_ptr); - } - goto reg_mem_instr_done; - } + /* This is not really needed, but gives behaviour + identical to an 80486 */ + if ((FPU_modrm & 0x28) == 0x20) + /* fdiv or fsub */ + real_2op_NaN + (&loaded_data, + loaded_tag, 0, + &loaded_data); + else +#endif /* PECULIAR_486 */ + /* fadd, fdivr, fmul, or fsubr */ + real_2op_NaN + (&loaded_data, + loaded_tag, 0, + st0_ptr); + } + goto reg_mem_instr_done; + } - if ( unmasked && !((FPU_modrm & 0x30) == 0x10) ) - { - /* Is not a comparison instruction. */ - if ( (FPU_modrm & 0x38) == 0x38 ) - { - /* fdivr */ - if ( (st0_tag == TAG_Zero) && - ((loaded_tag == TAG_Valid) - || (loaded_tag == TAG_Special - && isdenormal(&loaded_data))) ) - { - if ( FPU_divide_by_zero(0, getsign(&loaded_data)) - < 0 ) - { - /* We use the fact here that the unmasked - exception in the loaded data was for a - denormal operand */ - /* Restore the state of the denormal op bit */ - partial_status &= ~SW_Denorm_Op; - partial_status |= status1 & SW_Denorm_Op; - } - else - setsign(st0_ptr, getsign(&loaded_data)); + if (unmasked && !((FPU_modrm & 0x30) == 0x10)) { + /* Is not a comparison instruction. */ + if ((FPU_modrm & 0x38) == 0x38) { + /* fdivr */ + if ((st0_tag == TAG_Zero) && + ((loaded_tag == TAG_Valid) + || (loaded_tag == + TAG_Special + && + isdenormal + (&loaded_data)))) { + if (FPU_divide_by_zero + (0, + getsign + (&loaded_data)) + < 0) { + /* We use the fact here that the unmasked + exception in the loaded data was for a + denormal operand */ + /* Restore the state of the denormal op bit */ + partial_status + &= + ~SW_Denorm_Op; + partial_status + |= + status1 & + SW_Denorm_Op; + } else + setsign(st0_ptr, + getsign + (&loaded_data)); + } + } + goto reg_mem_instr_done; + } + + switch ((FPU_modrm >> 3) & 7) { + case 0: /* fadd */ + clear_C1(); + FPU_add(&loaded_data, loaded_tag, 0, + control_word); + break; + case 1: /* fmul */ + clear_C1(); + FPU_mul(&loaded_data, loaded_tag, 0, + control_word); + break; + case 2: /* fcom */ + FPU_compare_st_data(&loaded_data, + loaded_tag); + break; + case 3: /* fcomp */ + if (!FPU_compare_st_data + (&loaded_data, loaded_tag) + && !unmasked) + FPU_pop(); + break; + case 4: /* fsub */ + clear_C1(); + FPU_sub(LOADED | loaded_tag, + (int)&loaded_data, + control_word); + break; + case 5: /* fsubr */ + clear_C1(); + FPU_sub(REV | LOADED | loaded_tag, + (int)&loaded_data, + control_word); + break; + case 6: /* fdiv */ + clear_C1(); + FPU_div(LOADED | loaded_tag, + (int)&loaded_data, + control_word); + break; + case 7: /* fdivr */ + clear_C1(); + if (st0_tag == TAG_Zero) + partial_status = status1; /* Undo any denorm tag, + zero-divide has priority. */ + FPU_div(REV | LOADED | loaded_tag, + (int)&loaded_data, + control_word); + break; + } + } else { + if ((FPU_modrm & 0x30) == 0x10) { + /* The instruction is fcom or fcomp */ + EXCEPTION(EX_StackUnder); + setcc(SW_C3 | SW_C2 | SW_C0); + if ((FPU_modrm & 0x08) + && (control_word & CW_Invalid)) + FPU_pop(); /* fcomp */ + } else + FPU_stack_underflow(); + } + reg_mem_instr_done: + operand_address = data_sel_off; + } else { + if (!(no_ip_update = + FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6)) + >> 1, addr_modes, data_address))) { + operand_address = data_sel_off; } - } - goto reg_mem_instr_done; } - switch ( (FPU_modrm >> 3) & 7 ) - { - case 0: /* fadd */ - clear_C1(); - FPU_add(&loaded_data, loaded_tag, 0, control_word); - break; - case 1: /* fmul */ - clear_C1(); - FPU_mul(&loaded_data, loaded_tag, 0, control_word); - break; - case 2: /* fcom */ - FPU_compare_st_data(&loaded_data, loaded_tag); - break; - case 3: /* fcomp */ - if ( !FPU_compare_st_data(&loaded_data, loaded_tag) - && !unmasked ) - FPU_pop(); - break; - case 4: /* fsub */ - clear_C1(); - FPU_sub(LOADED|loaded_tag, (int)&loaded_data, control_word); - break; - case 5: /* fsubr */ - clear_C1(); - FPU_sub(REV|LOADED|loaded_tag, (int)&loaded_data, control_word); - break; - case 6: /* fdiv */ - clear_C1(); - FPU_div(LOADED|loaded_tag, (int)&loaded_data, control_word); - break; - case 7: /* fdivr */ - clear_C1(); - if ( st0_tag == TAG_Zero ) - partial_status = status1; /* Undo any denorm tag, - zero-divide has priority. */ - FPU_div(REV|LOADED|loaded_tag, (int)&loaded_data, control_word); - break; - } - } - else - { - if ( (FPU_modrm & 0x30) == 0x10 ) - { - /* The instruction is fcom or fcomp */ - EXCEPTION(EX_StackUnder); - setcc(SW_C3 | SW_C2 | SW_C0); - if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) ) - FPU_pop(); /* fcomp */ - } - else - FPU_stack_underflow(); - } - reg_mem_instr_done: - operand_address = data_sel_off; - } - else - { - if ( !(no_ip_update = - FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1, - addr_modes, data_address)) ) - { - operand_address = data_sel_off; - } - } - - } - else - { - /* None of these instructions access user memory */ - u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7); + } else { + /* None of these instructions access user memory */ + u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7); #ifdef PECULIAR_486 - /* This is supposed to be undefined, but a real 80486 seems - to do this: */ - operand_address.offset = 0; - operand_address.selector = FPU_DS; + /* This is supposed to be undefined, but a real 80486 seems + to do this: */ + operand_address.offset = 0; + operand_address.selector = FPU_DS; #endif /* PECULIAR_486 */ - st0_ptr = &st(0); - st0_tag = FPU_gettag0(); - switch ( type_table[(int) instr_index] ) - { - case _NONE_: /* also _REGIc: _REGIn */ - break; - case _REG0_: - if ( !NOT_EMPTY_ST0 ) - { - FPU_stack_underflow(); - goto FPU_instruction_done; - } - break; - case _REGIi: - if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) ) - { - FPU_stack_underflow_i(FPU_rm); - goto FPU_instruction_done; - } - break; - case _REGIp: - if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) ) - { - FPU_stack_underflow_pop(FPU_rm); - goto FPU_instruction_done; - } - break; - case _REGI_: - if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) ) - { - FPU_stack_underflow(); - goto FPU_instruction_done; - } - break; - case _PUSH_: /* Only used by the fld st(i) instruction */ - break; - case _null_: - FPU_illegal(); - goto FPU_instruction_done; - default: - EXCEPTION(EX_INTERNAL|0x111); - goto FPU_instruction_done; + st0_ptr = &st(0); + st0_tag = FPU_gettag0(); + switch (type_table[(int)instr_index]) { + case _NONE_: /* also _REGIc: _REGIn */ + break; + case _REG0_: + if (!NOT_EMPTY_ST0) { + FPU_stack_underflow(); + goto FPU_instruction_done; + } + break; + case _REGIi: + if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) { + FPU_stack_underflow_i(FPU_rm); + goto FPU_instruction_done; + } + break; + case _REGIp: + if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) { + FPU_stack_underflow_pop(FPU_rm); + goto FPU_instruction_done; + } + break; + case _REGI_: + if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) { + FPU_stack_underflow(); + goto FPU_instruction_done; + } + break; + case _PUSH_: /* Only used by the fld st(i) instruction */ + break; + case _null_: + FPU_illegal(); + goto FPU_instruction_done; + default: + EXCEPTION(EX_INTERNAL | 0x111); + goto FPU_instruction_done; + } + (*st_instr_table[(int)instr_index]) (); + + FPU_instruction_done: + ; } - (*st_instr_table[(int) instr_index])(); -FPU_instruction_done: - ; - } + if (!no_ip_update) + instruction_address = entry_sel_off; - if ( ! no_ip_update ) - instruction_address = entry_sel_off; - -FPU_fwait_done: + FPU_fwait_done: #ifdef DEBUG - RE_ENTRANT_CHECK_OFF; - FPU_printall(); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_printall(); + RE_ENTRANT_CHECK_ON; #endif /* DEBUG */ - if (FPU_lookahead && !need_resched()) - { - FPU_ORIG_EIP = FPU_EIP - code_base; - if ( valid_prefix(&byte1, (u_char __user **)&FPU_EIP, - &addr_modes.override) ) - goto do_another_FPU_instruction; - } + if (FPU_lookahead && !need_resched()) { + FPU_ORIG_EIP = FPU_EIP - code_base; + if (valid_prefix(&byte1, (u_char __user **) & FPU_EIP, + &addr_modes.override)) + goto do_another_FPU_instruction; + } - if ( addr_modes.default_mode ) - FPU_EIP -= code_base; + if (addr_modes.default_mode) + FPU_EIP -= code_base; - RE_ENTRANT_CHECK_OFF; + RE_ENTRANT_CHECK_OFF; } - /* Support for prefix bytes is not yet complete. To properly handle all prefix bytes, further changes are needed in the emulator code which accesses user address space. Access to separate segments is important for msdos emulation. */ -static int valid_prefix(u_char *Byte, u_char __user **fpu_eip, - overrides *override) +static int valid_prefix(u_char * Byte, u_char __user ** fpu_eip, + overrides * override) { - u_char byte; - u_char __user *ip = *fpu_eip; + u_char byte; + u_char __user *ip = *fpu_eip; - *override = (overrides) { 0, 0, PREFIX_DEFAULT }; /* defaults */ + *override = (overrides) { + 0, 0, PREFIX_DEFAULT}; /* defaults */ - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(1); - FPU_get_user(byte, ip); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(1); + FPU_get_user(byte, ip); + RE_ENTRANT_CHECK_ON; - while ( 1 ) - { - switch ( byte ) - { - case ADDR_SIZE_PREFIX: - override->address_size = ADDR_SIZE_PREFIX; - goto do_next_byte; + while (1) { + switch (byte) { + case ADDR_SIZE_PREFIX: + override->address_size = ADDR_SIZE_PREFIX; + goto do_next_byte; - case OP_SIZE_PREFIX: - override->operand_size = OP_SIZE_PREFIX; - goto do_next_byte; + case OP_SIZE_PREFIX: + override->operand_size = OP_SIZE_PREFIX; + goto do_next_byte; - case PREFIX_CS: - override->segment = PREFIX_CS_; - goto do_next_byte; - case PREFIX_ES: - override->segment = PREFIX_ES_; - goto do_next_byte; - case PREFIX_SS: - override->segment = PREFIX_SS_; - goto do_next_byte; - case PREFIX_FS: - override->segment = PREFIX_FS_; - goto do_next_byte; - case PREFIX_GS: - override->segment = PREFIX_GS_; - goto do_next_byte; - case PREFIX_DS: - override->segment = PREFIX_DS_; - goto do_next_byte; + case PREFIX_CS: + override->segment = PREFIX_CS_; + goto do_next_byte; + case PREFIX_ES: + override->segment = PREFIX_ES_; + goto do_next_byte; + case PREFIX_SS: + override->segment = PREFIX_SS_; + goto do_next_byte; + case PREFIX_FS: + override->segment = PREFIX_FS_; + goto do_next_byte; + case PREFIX_GS: + override->segment = PREFIX_GS_; + goto do_next_byte; + case PREFIX_DS: + override->segment = PREFIX_DS_; + goto do_next_byte; /* lock is not a valid prefix for FPU instructions, let the cpu handle it to generate a SIGILL. */ /* case PREFIX_LOCK: */ - /* rep.. prefixes have no meaning for FPU instructions */ - case PREFIX_REPE: - case PREFIX_REPNE: + /* rep.. prefixes have no meaning for FPU instructions */ + case PREFIX_REPE: + case PREFIX_REPNE: - do_next_byte: - ip++; - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(1); - FPU_get_user(byte, ip); - RE_ENTRANT_CHECK_ON; - break; - case FWAIT_OPCODE: - *Byte = byte; - return 1; - default: - if ( (byte & 0xf8) == 0xd8 ) - { - *Byte = byte; - *fpu_eip = ip; - return 1; - } - else - { - /* Not a valid sequence of prefix bytes followed by - an FPU instruction. */ - *Byte = byte; /* Needed for error message. */ - return 0; - } + do_next_byte: + ip++; + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(1); + FPU_get_user(byte, ip); + RE_ENTRANT_CHECK_ON; + break; + case FWAIT_OPCODE: + *Byte = byte; + return 1; + default: + if ((byte & 0xf8) == 0xd8) { + *Byte = byte; + *fpu_eip = ip; + return 1; + } else { + /* Not a valid sequence of prefix bytes followed by + an FPU instruction. */ + *Byte = byte; /* Needed for error message. */ + return 0; + } + } } - } } - -void math_abort(struct info * info, unsigned int signal) +void math_abort(struct info *info, unsigned int signal) { FPU_EIP = FPU_ORIG_EIP; current->thread.trap_no = 16; current->thread.error_code = 0; - send_sig(signal,current,1); + send_sig(signal, current, 1); RE_ENTRANT_CHECK_OFF; - __asm__("movl %0,%%esp ; ret": :"g" (((long) info)-4)); + __asm__("movl %0,%%esp ; ret": :"g"(((long)info) - 4)); #ifdef PARANOID - printk("ERROR: wm-FPU-emu math_abort failed!\n"); + printk("ERROR: wm-FPU-emu math_abort failed!\n"); #endif /* PARANOID */ } - - #define S387 ((struct i387_soft_struct *)s387) #define sstatus_word() \ ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top)) -int restore_i387_soft(void *s387, struct _fpstate __user *buf) +int restore_i387_soft(void *s387, struct _fpstate __user * buf) { - u_char __user *d = (u_char __user *)buf; - int offset, other, i, tags, regnr, tag, newtop; + u_char __user *d = (u_char __user *) buf; + int offset, other, i, tags, regnr, tag, newtop; - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ, d, 7*4 + 8*10); - if (__copy_from_user(&S387->cwd, d, 7*4)) - return -1; - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, d, 7 * 4 + 8 * 10); + if (__copy_from_user(&S387->cwd, d, 7 * 4)) + return -1; + RE_ENTRANT_CHECK_ON; - d += 7*4; + d += 7 * 4; - S387->ftop = (S387->swd >> SW_Top_Shift) & 7; - offset = (S387->ftop & 7) * 10; - other = 80 - offset; + S387->ftop = (S387->swd >> SW_Top_Shift) & 7; + offset = (S387->ftop & 7) * 10; + other = 80 - offset; - RE_ENTRANT_CHECK_OFF; - /* Copy all registers in stack order. */ - if (__copy_from_user(((u_char *)&S387->st_space)+offset, d, other)) - return -1; - if ( offset ) - if (__copy_from_user((u_char *)&S387->st_space, d+other, offset)) - return -1; - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + /* Copy all registers in stack order. */ + if (__copy_from_user(((u_char *) & S387->st_space) + offset, d, other)) + return -1; + if (offset) + if (__copy_from_user + ((u_char *) & S387->st_space, d + other, offset)) + return -1; + RE_ENTRANT_CHECK_ON; - /* The tags may need to be corrected now. */ - tags = S387->twd; - newtop = S387->ftop; - for ( i = 0; i < 8; i++ ) - { - regnr = (i+newtop) & 7; - if ( ((tags >> ((regnr & 7)*2)) & 3) != TAG_Empty ) - { - /* The loaded data over-rides all other cases. */ - tag = FPU_tagof((FPU_REG *)((u_char *)S387->st_space + 10*regnr)); - tags &= ~(3 << (regnr*2)); - tags |= (tag & 3) << (regnr*2); + /* The tags may need to be corrected now. */ + tags = S387->twd; + newtop = S387->ftop; + for (i = 0; i < 8; i++) { + regnr = (i + newtop) & 7; + if (((tags >> ((regnr & 7) * 2)) & 3) != TAG_Empty) { + /* The loaded data over-rides all other cases. */ + tag = + FPU_tagof((FPU_REG *) ((u_char *) S387->st_space + + 10 * regnr)); + tags &= ~(3 << (regnr * 2)); + tags |= (tag & 3) << (regnr * 2); + } } - } - S387->twd = tags; + S387->twd = tags; - return 0; + return 0; } - int save_i387_soft(void *s387, struct _fpstate __user * buf) { - u_char __user *d = (u_char __user *)buf; - int offset = (S387->ftop & 7) * 10, other = 80 - offset; + u_char __user *d = (u_char __user *) buf; + int offset = (S387->ftop & 7) * 10, other = 80 - offset; - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE, d, 7*4 + 8*10); + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, d, 7 * 4 + 8 * 10); #ifdef PECULIAR_486 - S387->cwd &= ~0xe080; - /* An 80486 sets nearly all of the reserved bits to 1. */ - S387->cwd |= 0xffff0040; - S387->swd = sstatus_word() | 0xffff0000; - S387->twd |= 0xffff0000; - S387->fcs &= ~0xf8000000; - S387->fos |= 0xffff0000; + S387->cwd &= ~0xe080; + /* An 80486 sets nearly all of the reserved bits to 1. */ + S387->cwd |= 0xffff0040; + S387->swd = sstatus_word() | 0xffff0000; + S387->twd |= 0xffff0000; + S387->fcs &= ~0xf8000000; + S387->fos |= 0xffff0000; #endif /* PECULIAR_486 */ - if (__copy_to_user(d, &S387->cwd, 7*4)) - return -1; - RE_ENTRANT_CHECK_ON; + if (__copy_to_user(d, &S387->cwd, 7 * 4)) + return -1; + RE_ENTRANT_CHECK_ON; - d += 7*4; + d += 7 * 4; - RE_ENTRANT_CHECK_OFF; - /* Copy all registers in stack order. */ - if (__copy_to_user(d, ((u_char *)&S387->st_space)+offset, other)) - return -1; - if ( offset ) - if (__copy_to_user(d+other, (u_char *)&S387->st_space, offset)) - return -1; - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + /* Copy all registers in stack order. */ + if (__copy_to_user(d, ((u_char *) & S387->st_space) + offset, other)) + return -1; + if (offset) + if (__copy_to_user + (d + other, (u_char *) & S387->st_space, offset)) + return -1; + RE_ENTRANT_CHECK_ON; - return 1; + return 1; } diff --git a/arch/x86/math-emu/fpu_etc.c b/arch/x86/math-emu/fpu_etc.c index e3b5d465587f..e73631e0cde9 100644 --- a/arch/x86/math-emu/fpu_etc.c +++ b/arch/x86/math-emu/fpu_etc.c @@ -16,128 +16,115 @@ #include "status_w.h" #include "reg_constant.h" - -static void fchs(FPU_REG *st0_ptr, u_char st0tag) +static void fchs(FPU_REG * st0_ptr, u_char st0tag) { - if ( st0tag ^ TAG_Empty ) - { - signbyte(st0_ptr) ^= SIGN_NEG; - clear_C1(); - } - else - FPU_stack_underflow(); + if (st0tag ^ TAG_Empty) { + signbyte(st0_ptr) ^= SIGN_NEG; + clear_C1(); + } else + FPU_stack_underflow(); } - -static void fabs(FPU_REG *st0_ptr, u_char st0tag) +static void fabs(FPU_REG * st0_ptr, u_char st0tag) { - if ( st0tag ^ TAG_Empty ) - { - setpositive(st0_ptr); - clear_C1(); - } - else - FPU_stack_underflow(); + if (st0tag ^ TAG_Empty) { + setpositive(st0_ptr); + clear_C1(); + } else + FPU_stack_underflow(); } - -static void ftst_(FPU_REG *st0_ptr, u_char st0tag) +static void ftst_(FPU_REG * st0_ptr, u_char st0tag) { - switch (st0tag) - { - case TAG_Zero: - setcc(SW_C3); - break; - case TAG_Valid: - if (getsign(st0_ptr) == SIGN_POS) - setcc(0); - else - setcc(SW_C0); - break; - case TAG_Special: - switch ( FPU_Special(st0_ptr) ) - { - case TW_Denormal: - if (getsign(st0_ptr) == SIGN_POS) - setcc(0); - else - setcc(SW_C0); - if ( denormal_operand() < 0 ) - { -#ifdef PECULIAR_486 - /* This is weird! */ - if (getsign(st0_ptr) == SIGN_POS) + switch (st0tag) { + case TAG_Zero: setcc(SW_C3); + break; + case TAG_Valid: + if (getsign(st0_ptr) == SIGN_POS) + setcc(0); + else + setcc(SW_C0); + break; + case TAG_Special: + switch (FPU_Special(st0_ptr)) { + case TW_Denormal: + if (getsign(st0_ptr) == SIGN_POS) + setcc(0); + else + setcc(SW_C0); + if (denormal_operand() < 0) { +#ifdef PECULIAR_486 + /* This is weird! */ + if (getsign(st0_ptr) == SIGN_POS) + setcc(SW_C3); #endif /* PECULIAR_486 */ - return; - } - break; - case TW_NaN: - setcc(SW_C0|SW_C2|SW_C3); /* Operand is not comparable */ - EXCEPTION(EX_Invalid); - break; - case TW_Infinity: - if (getsign(st0_ptr) == SIGN_POS) - setcc(0); - else - setcc(SW_C0); - break; - default: - setcc(SW_C0|SW_C2|SW_C3); /* Operand is not comparable */ - EXCEPTION(EX_INTERNAL|0x14); - break; + return; + } + break; + case TW_NaN: + setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */ + EXCEPTION(EX_Invalid); + break; + case TW_Infinity: + if (getsign(st0_ptr) == SIGN_POS) + setcc(0); + else + setcc(SW_C0); + break; + default: + setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */ + EXCEPTION(EX_INTERNAL | 0x14); + break; + } + break; + case TAG_Empty: + setcc(SW_C0 | SW_C2 | SW_C3); + EXCEPTION(EX_StackUnder); + break; } - break; - case TAG_Empty: - setcc(SW_C0|SW_C2|SW_C3); - EXCEPTION(EX_StackUnder); - break; - } } - -static void fxam(FPU_REG *st0_ptr, u_char st0tag) +static void fxam(FPU_REG * st0_ptr, u_char st0tag) { - int c = 0; - switch (st0tag) - { - case TAG_Empty: - c = SW_C3|SW_C0; - break; - case TAG_Zero: - c = SW_C3; - break; - case TAG_Valid: - c = SW_C2; - break; - case TAG_Special: - switch ( FPU_Special(st0_ptr) ) - { - case TW_Denormal: - c = SW_C2|SW_C3; /* Denormal */ - break; - case TW_NaN: - /* We also use NaN for unsupported types. */ - if ( (st0_ptr->sigh & 0x80000000) && (exponent(st0_ptr) == EXP_OVER) ) - c = SW_C0; - break; - case TW_Infinity: - c = SW_C2|SW_C0; - break; + int c = 0; + switch (st0tag) { + case TAG_Empty: + c = SW_C3 | SW_C0; + break; + case TAG_Zero: + c = SW_C3; + break; + case TAG_Valid: + c = SW_C2; + break; + case TAG_Special: + switch (FPU_Special(st0_ptr)) { + case TW_Denormal: + c = SW_C2 | SW_C3; /* Denormal */ + break; + case TW_NaN: + /* We also use NaN for unsupported types. */ + if ((st0_ptr->sigh & 0x80000000) + && (exponent(st0_ptr) == EXP_OVER)) + c = SW_C0; + break; + case TW_Infinity: + c = SW_C2 | SW_C0; + break; + } } - } - if ( getsign(st0_ptr) == SIGN_NEG ) - c |= SW_C1; - setcc(c); + if (getsign(st0_ptr) == SIGN_NEG) + c |= SW_C1; + setcc(c); } - static FUNC_ST0 const fp_etc_table[] = { - fchs, fabs, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal, - ftst_, fxam, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal + fchs, fabs, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal, + ftst_, fxam, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal }; void FPU_etc(void) { - (fp_etc_table[FPU_rm])(&st(0), FPU_gettag0()); + (fp_etc_table[FPU_rm]) (&st(0), FPU_gettag0()); } diff --git a/arch/x86/math-emu/fpu_proto.h b/arch/x86/math-emu/fpu_proto.h index 37a8a7fe7e2b..0f6384102afd 100644 --- a/arch/x86/math-emu/fpu_proto.h +++ b/arch/x86/math-emu/fpu_proto.h @@ -5,7 +5,7 @@ extern void FPU_illegal(void); extern void FPU_printall(void); asmlinkage void FPU_exception(int n); -extern int real_1op_NaN(FPU_REG *a); +extern int real_1op_NaN(FPU_REG * a); extern int real_2op_NaN(FPU_REG const *b, u_char tagb, int deststnr, FPU_REG const *defaultNaN); asmlinkage int arith_invalid(int deststnr); @@ -14,8 +14,8 @@ extern int set_precision_flag(int flags); asmlinkage void set_precision_flag_up(void); asmlinkage void set_precision_flag_down(void); asmlinkage int denormal_operand(void); -asmlinkage int arith_overflow(FPU_REG *dest); -asmlinkage int arith_underflow(FPU_REG *dest); +asmlinkage int arith_overflow(FPU_REG * dest); +asmlinkage int arith_underflow(FPU_REG * dest); extern void FPU_stack_overflow(void); extern void FPU_stack_underflow(void); extern void FPU_stack_underflow_i(int i); @@ -66,7 +66,7 @@ extern int FPU_Special(FPU_REG const *ptr); extern int isNaN(FPU_REG const *ptr); extern void FPU_pop(void); extern int FPU_empty_i(int stnr); -extern int FPU_stackoverflow(FPU_REG **st_new_ptr); +extern int FPU_stackoverflow(FPU_REG ** st_new_ptr); extern void FPU_copy_to_regi(FPU_REG const *r, u_char tag, int stnr); extern void FPU_copy_to_reg1(FPU_REG const *r, u_char tag); extern void FPU_copy_to_reg0(FPU_REG const *r, u_char tag); @@ -75,26 +75,28 @@ extern void FPU_triga(void); extern void FPU_trigb(void); /* get_address.c */ extern void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip, - struct address *addr, fpu_addr_modes addr_modes); + struct address *addr, + fpu_addr_modes addr_modes); extern void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip, - struct address *addr, fpu_addr_modes addr_modes); + struct address *addr, + fpu_addr_modes addr_modes); /* load_store.c */ extern int FPU_load_store(u_char type, fpu_addr_modes addr_modes, - void __user *data_address); + void __user * data_address); /* poly_2xm1.c */ -extern int poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result); +extern int poly_2xm1(u_char sign, FPU_REG * arg, FPU_REG * result); /* poly_atan.c */ -extern void poly_atan(FPU_REG *st0_ptr, u_char st0_tag, FPU_REG *st1_ptr, +extern void poly_atan(FPU_REG * st0_ptr, u_char st0_tag, FPU_REG * st1_ptr, u_char st1_tag); /* poly_l2.c */ -extern void poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign); -extern int poly_l2p1(u_char s0, u_char s1, FPU_REG *r0, FPU_REG *r1, - FPU_REG *d); +extern void poly_l2(FPU_REG * st0_ptr, FPU_REG * st1_ptr, u_char st1_sign); +extern int poly_l2p1(u_char s0, u_char s1, FPU_REG * r0, FPU_REG * r1, + FPU_REG * d); /* poly_sin.c */ -extern void poly_sine(FPU_REG *st0_ptr); -extern void poly_cos(FPU_REG *st0_ptr); +extern void poly_sine(FPU_REG * st0_ptr); +extern void poly_cos(FPU_REG * st0_ptr); /* poly_tan.c */ -extern void poly_tan(FPU_REG *st0_ptr); +extern void poly_tan(FPU_REG * st0_ptr); /* reg_add_sub.c */ extern int FPU_add(FPU_REG const *b, u_char tagb, int destrnr, int control_w); extern int FPU_sub(int flags, int rm, int control_w); @@ -109,32 +111,34 @@ extern void fucompp(void); /* reg_constant.c */ extern void fconst(void); /* reg_ld_str.c */ -extern int FPU_load_extended(long double __user *s, int stnr); -extern int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data); -extern int FPU_load_single(float __user *single, FPU_REG *loaded_data); -extern int FPU_load_int64(long long __user *_s); -extern int FPU_load_int32(long __user *_s, FPU_REG *loaded_data); -extern int FPU_load_int16(short __user *_s, FPU_REG *loaded_data); -extern int FPU_load_bcd(u_char __user *s); -extern int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, - long double __user *d); -extern int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat); -extern int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single); -extern int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d); -extern int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d); -extern int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d); -extern int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d); -extern int FPU_round_to_int(FPU_REG *r, u_char tag); -extern u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s); -extern void frstor(fpu_addr_modes addr_modes, u_char __user *data_address); -extern u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d); -extern void fsave(fpu_addr_modes addr_modes, u_char __user *data_address); -extern int FPU_tagof(FPU_REG *ptr); +extern int FPU_load_extended(long double __user * s, int stnr); +extern int FPU_load_double(double __user * dfloat, FPU_REG * loaded_data); +extern int FPU_load_single(float __user * single, FPU_REG * loaded_data); +extern int FPU_load_int64(long long __user * _s); +extern int FPU_load_int32(long __user * _s, FPU_REG * loaded_data); +extern int FPU_load_int16(short __user * _s, FPU_REG * loaded_data); +extern int FPU_load_bcd(u_char __user * s); +extern int FPU_store_extended(FPU_REG * st0_ptr, u_char st0_tag, + long double __user * d); +extern int FPU_store_double(FPU_REG * st0_ptr, u_char st0_tag, + double __user * dfloat); +extern int FPU_store_single(FPU_REG * st0_ptr, u_char st0_tag, + float __user * single); +extern int FPU_store_int64(FPU_REG * st0_ptr, u_char st0_tag, + long long __user * d); +extern int FPU_store_int32(FPU_REG * st0_ptr, u_char st0_tag, long __user * d); +extern int FPU_store_int16(FPU_REG * st0_ptr, u_char st0_tag, short __user * d); +extern int FPU_store_bcd(FPU_REG * st0_ptr, u_char st0_tag, u_char __user * d); +extern int FPU_round_to_int(FPU_REG * r, u_char tag); +extern u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user * s); +extern void frstor(fpu_addr_modes addr_modes, u_char __user * data_address); +extern u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user * d); +extern void fsave(fpu_addr_modes addr_modes, u_char __user * data_address); +extern int FPU_tagof(FPU_REG * ptr); /* reg_mul.c */ extern int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w); extern int FPU_div(int flags, int regrm, int control_w); /* reg_convert.c */ -extern int FPU_to_exp16(FPU_REG const *a, FPU_REG *x); +extern int FPU_to_exp16(FPU_REG const *a, FPU_REG * x); #endif /* _FPU_PROTO_H */ - diff --git a/arch/x86/math-emu/fpu_tags.c b/arch/x86/math-emu/fpu_tags.c index cb436fe20e4c..d9c657cd7746 100644 --- a/arch/x86/math-emu/fpu_tags.c +++ b/arch/x86/math-emu/fpu_tags.c @@ -14,114 +14,102 @@ #include "fpu_system.h" #include "exception.h" - void FPU_pop(void) { - fpu_tag_word |= 3 << ((top & 7)*2); - top++; + fpu_tag_word |= 3 << ((top & 7) * 2); + top++; } - int FPU_gettag0(void) { - return (fpu_tag_word >> ((top & 7)*2)) & 3; + return (fpu_tag_word >> ((top & 7) * 2)) & 3; } - int FPU_gettagi(int stnr) { - return (fpu_tag_word >> (((top+stnr) & 7)*2)) & 3; + return (fpu_tag_word >> (((top + stnr) & 7) * 2)) & 3; } - int FPU_gettag(int regnr) { - return (fpu_tag_word >> ((regnr & 7)*2)) & 3; + return (fpu_tag_word >> ((regnr & 7) * 2)) & 3; } - void FPU_settag0(int tag) { - int regnr = top; - regnr &= 7; - fpu_tag_word &= ~(3 << (regnr*2)); - fpu_tag_word |= (tag & 3) << (regnr*2); + int regnr = top; + regnr &= 7; + fpu_tag_word &= ~(3 << (regnr * 2)); + fpu_tag_word |= (tag & 3) << (regnr * 2); } - void FPU_settagi(int stnr, int tag) { - int regnr = stnr+top; - regnr &= 7; - fpu_tag_word &= ~(3 << (regnr*2)); - fpu_tag_word |= (tag & 3) << (regnr*2); + int regnr = stnr + top; + regnr &= 7; + fpu_tag_word &= ~(3 << (regnr * 2)); + fpu_tag_word |= (tag & 3) << (regnr * 2); } - void FPU_settag(int regnr, int tag) { - regnr &= 7; - fpu_tag_word &= ~(3 << (regnr*2)); - fpu_tag_word |= (tag & 3) << (regnr*2); + regnr &= 7; + fpu_tag_word &= ~(3 << (regnr * 2)); + fpu_tag_word |= (tag & 3) << (regnr * 2); } - int FPU_Special(FPU_REG const *ptr) { - int exp = exponent(ptr); + int exp = exponent(ptr); - if ( exp == EXP_BIAS+EXP_UNDER ) - return TW_Denormal; - else if ( exp != EXP_BIAS+EXP_OVER ) - return TW_NaN; - else if ( (ptr->sigh == 0x80000000) && (ptr->sigl == 0) ) - return TW_Infinity; - return TW_NaN; + if (exp == EXP_BIAS + EXP_UNDER) + return TW_Denormal; + else if (exp != EXP_BIAS + EXP_OVER) + return TW_NaN; + else if ((ptr->sigh == 0x80000000) && (ptr->sigl == 0)) + return TW_Infinity; + return TW_NaN; } - int isNaN(FPU_REG const *ptr) { - return ( (exponent(ptr) == EXP_BIAS+EXP_OVER) - && !((ptr->sigh == 0x80000000) && (ptr->sigl == 0)) ); + return ((exponent(ptr) == EXP_BIAS + EXP_OVER) + && !((ptr->sigh == 0x80000000) && (ptr->sigl == 0))); } - int FPU_empty_i(int stnr) { - int regnr = (top+stnr) & 7; + int regnr = (top + stnr) & 7; - return ((fpu_tag_word >> (regnr*2)) & 3) == TAG_Empty; + return ((fpu_tag_word >> (regnr * 2)) & 3) == TAG_Empty; } - -int FPU_stackoverflow(FPU_REG **st_new_ptr) +int FPU_stackoverflow(FPU_REG ** st_new_ptr) { - *st_new_ptr = &st(-1); + *st_new_ptr = &st(-1); - return ((fpu_tag_word >> (((top - 1) & 7)*2)) & 3) != TAG_Empty; + return ((fpu_tag_word >> (((top - 1) & 7) * 2)) & 3) != TAG_Empty; } - void FPU_copy_to_regi(FPU_REG const *r, u_char tag, int stnr) { - reg_copy(r, &st(stnr)); - FPU_settagi(stnr, tag); + reg_copy(r, &st(stnr)); + FPU_settagi(stnr, tag); } void FPU_copy_to_reg1(FPU_REG const *r, u_char tag) { - reg_copy(r, &st(1)); - FPU_settagi(1, tag); + reg_copy(r, &st(1)); + FPU_settagi(1, tag); } void FPU_copy_to_reg0(FPU_REG const *r, u_char tag) { - int regnr = top; - regnr &= 7; + int regnr = top; + regnr &= 7; - reg_copy(r, &st(0)); + reg_copy(r, &st(0)); - fpu_tag_word &= ~(3 << (regnr*2)); - fpu_tag_word |= (tag & 3) << (regnr*2); + fpu_tag_word &= ~(3 << (regnr * 2)); + fpu_tag_word |= (tag & 3) << (regnr * 2); } diff --git a/arch/x86/math-emu/fpu_trig.c b/arch/x86/math-emu/fpu_trig.c index 403cbde1d425..e5316a288a6e 100644 --- a/arch/x86/math-emu/fpu_trig.c +++ b/arch/x86/math-emu/fpu_trig.c @@ -15,11 +15,10 @@ #include "fpu_emu.h" #include "status_w.h" #include "control_w.h" -#include "reg_constant.h" +#include "reg_constant.h" static void rem_kernel(unsigned long long st0, unsigned long long *y, - unsigned long long st1, - unsigned long long q, int n); + unsigned long long st1, unsigned long long q, int n); #define BETTER_THAN_486 @@ -31,791 +30,709 @@ static void rem_kernel(unsigned long long st0, unsigned long long *y, /* Limited measurements show no results worse than 64 bit precision except for the results for arguments close to 2^63, where the precision of the result sometimes degrades to about 63.9 bits */ -static int trig_arg(FPU_REG *st0_ptr, int even) +static int trig_arg(FPU_REG * st0_ptr, int even) { - FPU_REG tmp; - u_char tmptag; - unsigned long long q; - int old_cw = control_word, saved_status = partial_status; - int tag, st0_tag = TAG_Valid; + FPU_REG tmp; + u_char tmptag; + unsigned long long q; + int old_cw = control_word, saved_status = partial_status; + int tag, st0_tag = TAG_Valid; - if ( exponent(st0_ptr) >= 63 ) - { - partial_status |= SW_C2; /* Reduction incomplete. */ - return -1; - } - - control_word &= ~CW_RC; - control_word |= RC_CHOP; - - setpositive(st0_ptr); - tag = FPU_u_div(st0_ptr, &CONST_PI2, &tmp, PR_64_BITS | RC_CHOP | 0x3f, - SIGN_POS); - - FPU_round_to_int(&tmp, tag); /* Fortunately, this can't overflow - to 2^64 */ - q = significand(&tmp); - if ( q ) - { - rem_kernel(significand(st0_ptr), - &significand(&tmp), - significand(&CONST_PI2), - q, exponent(st0_ptr) - exponent(&CONST_PI2)); - setexponent16(&tmp, exponent(&CONST_PI2)); - st0_tag = FPU_normalize(&tmp); - FPU_copy_to_reg0(&tmp, st0_tag); - } - - if ( (even && !(q & 1)) || (!even && (q & 1)) ) - { - st0_tag = FPU_sub(REV|LOADED|TAG_Valid, (int)&CONST_PI2, FULL_PRECISION); - -#ifdef BETTER_THAN_486 - /* So far, the results are exact but based upon a 64 bit - precision approximation to pi/2. The technique used - now is equivalent to using an approximation to pi/2 which - is accurate to about 128 bits. */ - if ( (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64) || (q > 1) ) - { - /* This code gives the effect of having pi/2 to better than - 128 bits precision. */ - - significand(&tmp) = q + 1; - setexponent16(&tmp, 63); - FPU_normalize(&tmp); - tmptag = - FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION, SIGN_POS, - exponent(&CONST_PI2extra) + exponent(&tmp)); - setsign(&tmp, getsign(&CONST_PI2extra)); - st0_tag = FPU_add(&tmp, tmptag, 0, FULL_PRECISION); - if ( signnegative(st0_ptr) ) - { - /* CONST_PI2extra is negative, so the result of the addition - can be negative. This means that the argument is actually - in a different quadrant. The correction is always < pi/2, - so it can't overflow into yet another quadrant. */ - setpositive(st0_ptr); - q++; - } + if (exponent(st0_ptr) >= 63) { + partial_status |= SW_C2; /* Reduction incomplete. */ + return -1; } -#endif /* BETTER_THAN_486 */ - } -#ifdef BETTER_THAN_486 - else - { - /* So far, the results are exact but based upon a 64 bit - precision approximation to pi/2. The technique used - now is equivalent to using an approximation to pi/2 which - is accurate to about 128 bits. */ - if ( ((q > 0) && (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64)) - || (q > 1) ) - { - /* This code gives the effect of having p/2 to better than - 128 bits precision. */ - significand(&tmp) = q; - setexponent16(&tmp, 63); - FPU_normalize(&tmp); /* This must return TAG_Valid */ - tmptag = FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION, - SIGN_POS, - exponent(&CONST_PI2extra) + exponent(&tmp)); - setsign(&tmp, getsign(&CONST_PI2extra)); - st0_tag = FPU_sub(LOADED|(tmptag & 0x0f), (int)&tmp, + control_word &= ~CW_RC; + control_word |= RC_CHOP; + + setpositive(st0_ptr); + tag = FPU_u_div(st0_ptr, &CONST_PI2, &tmp, PR_64_BITS | RC_CHOP | 0x3f, + SIGN_POS); + + FPU_round_to_int(&tmp, tag); /* Fortunately, this can't overflow + to 2^64 */ + q = significand(&tmp); + if (q) { + rem_kernel(significand(st0_ptr), + &significand(&tmp), + significand(&CONST_PI2), + q, exponent(st0_ptr) - exponent(&CONST_PI2)); + setexponent16(&tmp, exponent(&CONST_PI2)); + st0_tag = FPU_normalize(&tmp); + FPU_copy_to_reg0(&tmp, st0_tag); + } + + if ((even && !(q & 1)) || (!even && (q & 1))) { + st0_tag = + FPU_sub(REV | LOADED | TAG_Valid, (int)&CONST_PI2, FULL_PRECISION); - if ( (exponent(st0_ptr) == exponent(&CONST_PI2)) && - ((st0_ptr->sigh > CONST_PI2.sigh) - || ((st0_ptr->sigh == CONST_PI2.sigh) - && (st0_ptr->sigl > CONST_PI2.sigl))) ) - { - /* CONST_PI2extra is negative, so the result of the - subtraction can be larger than pi/2. This means - that the argument is actually in a different quadrant. - The correction is always < pi/2, so it can't overflow - into yet another quadrant. */ - st0_tag = FPU_sub(REV|LOADED|TAG_Valid, (int)&CONST_PI2, - FULL_PRECISION); - q++; - } + +#ifdef BETTER_THAN_486 + /* So far, the results are exact but based upon a 64 bit + precision approximation to pi/2. The technique used + now is equivalent to using an approximation to pi/2 which + is accurate to about 128 bits. */ + if ((exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64) + || (q > 1)) { + /* This code gives the effect of having pi/2 to better than + 128 bits precision. */ + + significand(&tmp) = q + 1; + setexponent16(&tmp, 63); + FPU_normalize(&tmp); + tmptag = + FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, + FULL_PRECISION, SIGN_POS, + exponent(&CONST_PI2extra) + + exponent(&tmp)); + setsign(&tmp, getsign(&CONST_PI2extra)); + st0_tag = FPU_add(&tmp, tmptag, 0, FULL_PRECISION); + if (signnegative(st0_ptr)) { + /* CONST_PI2extra is negative, so the result of the addition + can be negative. This means that the argument is actually + in a different quadrant. The correction is always < pi/2, + so it can't overflow into yet another quadrant. */ + setpositive(st0_ptr); + q++; + } + } +#endif /* BETTER_THAN_486 */ + } +#ifdef BETTER_THAN_486 + else { + /* So far, the results are exact but based upon a 64 bit + precision approximation to pi/2. The technique used + now is equivalent to using an approximation to pi/2 which + is accurate to about 128 bits. */ + if (((q > 0) + && (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64)) + || (q > 1)) { + /* This code gives the effect of having p/2 to better than + 128 bits precision. */ + + significand(&tmp) = q; + setexponent16(&tmp, 63); + FPU_normalize(&tmp); /* This must return TAG_Valid */ + tmptag = + FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, + FULL_PRECISION, SIGN_POS, + exponent(&CONST_PI2extra) + + exponent(&tmp)); + setsign(&tmp, getsign(&CONST_PI2extra)); + st0_tag = FPU_sub(LOADED | (tmptag & 0x0f), (int)&tmp, + FULL_PRECISION); + if ((exponent(st0_ptr) == exponent(&CONST_PI2)) && + ((st0_ptr->sigh > CONST_PI2.sigh) + || ((st0_ptr->sigh == CONST_PI2.sigh) + && (st0_ptr->sigl > CONST_PI2.sigl)))) { + /* CONST_PI2extra is negative, so the result of the + subtraction can be larger than pi/2. This means + that the argument is actually in a different quadrant. + The correction is always < pi/2, so it can't overflow + into yet another quadrant. */ + st0_tag = + FPU_sub(REV | LOADED | TAG_Valid, + (int)&CONST_PI2, FULL_PRECISION); + q++; + } + } } - } #endif /* BETTER_THAN_486 */ - FPU_settag0(st0_tag); - control_word = old_cw; - partial_status = saved_status & ~SW_C2; /* Reduction complete. */ + FPU_settag0(st0_tag); + control_word = old_cw; + partial_status = saved_status & ~SW_C2; /* Reduction complete. */ - return (q & 3) | even; + return (q & 3) | even; } - /* Convert a long to register */ static void convert_l2reg(long const *arg, int deststnr) { - int tag; - long num = *arg; - u_char sign; - FPU_REG *dest = &st(deststnr); + int tag; + long num = *arg; + u_char sign; + FPU_REG *dest = &st(deststnr); - if (num == 0) - { - FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); - return; - } + if (num == 0) { + FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); + return; + } - if (num > 0) - { sign = SIGN_POS; } - else - { num = -num; sign = SIGN_NEG; } + if (num > 0) { + sign = SIGN_POS; + } else { + num = -num; + sign = SIGN_NEG; + } - dest->sigh = num; - dest->sigl = 0; - setexponent16(dest, 31); - tag = FPU_normalize(dest); - FPU_settagi(deststnr, tag); - setsign(dest, sign); - return; + dest->sigh = num; + dest->sigl = 0; + setexponent16(dest, 31); + tag = FPU_normalize(dest); + FPU_settagi(deststnr, tag); + setsign(dest, sign); + return; } - -static void single_arg_error(FPU_REG *st0_ptr, u_char st0_tag) +static void single_arg_error(FPU_REG * st0_ptr, u_char st0_tag) { - if ( st0_tag == TAG_Empty ) - FPU_stack_underflow(); /* Puts a QNaN in st(0) */ - else if ( st0_tag == TW_NaN ) - real_1op_NaN(st0_ptr); /* return with a NaN in st(0) */ + if (st0_tag == TAG_Empty) + FPU_stack_underflow(); /* Puts a QNaN in st(0) */ + else if (st0_tag == TW_NaN) + real_1op_NaN(st0_ptr); /* return with a NaN in st(0) */ #ifdef PARANOID - else - EXCEPTION(EX_INTERNAL|0x0112); + else + EXCEPTION(EX_INTERNAL | 0x0112); #endif /* PARANOID */ } - -static void single_arg_2_error(FPU_REG *st0_ptr, u_char st0_tag) +static void single_arg_2_error(FPU_REG * st0_ptr, u_char st0_tag) { - int isNaN; + int isNaN; - switch ( st0_tag ) - { - case TW_NaN: - isNaN = (exponent(st0_ptr) == EXP_OVER) && (st0_ptr->sigh & 0x80000000); - if ( isNaN && !(st0_ptr->sigh & 0x40000000) ) /* Signaling ? */ - { - EXCEPTION(EX_Invalid); - if ( control_word & CW_Invalid ) - { - /* The masked response */ - /* Convert to a QNaN */ - st0_ptr->sigh |= 0x40000000; - push(); - FPU_copy_to_reg0(st0_ptr, TAG_Special); - } - } - else if ( isNaN ) - { - /* A QNaN */ - push(); - FPU_copy_to_reg0(st0_ptr, TAG_Special); - } - else - { - /* pseudoNaN or other unsupported */ - EXCEPTION(EX_Invalid); - if ( control_word & CW_Invalid ) - { - /* The masked response */ - FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); - push(); - FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); - } - } - break; /* return with a NaN in st(0) */ + switch (st0_tag) { + case TW_NaN: + isNaN = (exponent(st0_ptr) == EXP_OVER) + && (st0_ptr->sigh & 0x80000000); + if (isNaN && !(st0_ptr->sigh & 0x40000000)) { /* Signaling ? */ + EXCEPTION(EX_Invalid); + if (control_word & CW_Invalid) { + /* The masked response */ + /* Convert to a QNaN */ + st0_ptr->sigh |= 0x40000000; + push(); + FPU_copy_to_reg0(st0_ptr, TAG_Special); + } + } else if (isNaN) { + /* A QNaN */ + push(); + FPU_copy_to_reg0(st0_ptr, TAG_Special); + } else { + /* pseudoNaN or other unsupported */ + EXCEPTION(EX_Invalid); + if (control_word & CW_Invalid) { + /* The masked response */ + FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); + push(); + FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); + } + } + break; /* return with a NaN in st(0) */ #ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL|0x0112); + default: + EXCEPTION(EX_INTERNAL | 0x0112); #endif /* PARANOID */ - } + } } - /*---------------------------------------------------------------------------*/ -static void f2xm1(FPU_REG *st0_ptr, u_char tag) +static void f2xm1(FPU_REG * st0_ptr, u_char tag) { - FPU_REG a; + FPU_REG a; - clear_C1(); + clear_C1(); - if ( tag == TAG_Valid ) - { - /* For an 80486 FPU, the result is undefined if the arg is >= 1.0 */ - if ( exponent(st0_ptr) < 0 ) - { - denormal_arg: + if (tag == TAG_Valid) { + /* For an 80486 FPU, the result is undefined if the arg is >= 1.0 */ + if (exponent(st0_ptr) < 0) { + denormal_arg: - FPU_to_exp16(st0_ptr, &a); + FPU_to_exp16(st0_ptr, &a); - /* poly_2xm1(x) requires 0 < st(0) < 1. */ - poly_2xm1(getsign(st0_ptr), &a, st0_ptr); + /* poly_2xm1(x) requires 0 < st(0) < 1. */ + poly_2xm1(getsign(st0_ptr), &a, st0_ptr); + } + set_precision_flag_up(); /* 80486 appears to always do this */ + return; } - set_precision_flag_up(); /* 80486 appears to always do this */ - return; - } - if ( tag == TAG_Zero ) - return; + if (tag == TAG_Zero) + return; - if ( tag == TAG_Special ) - tag = FPU_Special(st0_ptr); + if (tag == TAG_Special) + tag = FPU_Special(st0_ptr); - switch ( tag ) - { - case TW_Denormal: - if ( denormal_operand() < 0 ) - return; - goto denormal_arg; - case TW_Infinity: - if ( signnegative(st0_ptr) ) - { - /* -infinity gives -1 (p16-10) */ - FPU_copy_to_reg0(&CONST_1, TAG_Valid); - setnegative(st0_ptr); + switch (tag) { + case TW_Denormal: + if (denormal_operand() < 0) + return; + goto denormal_arg; + case TW_Infinity: + if (signnegative(st0_ptr)) { + /* -infinity gives -1 (p16-10) */ + FPU_copy_to_reg0(&CONST_1, TAG_Valid); + setnegative(st0_ptr); + } + return; + default: + single_arg_error(st0_ptr, tag); } - return; - default: - single_arg_error(st0_ptr, tag); - } } - -static void fptan(FPU_REG *st0_ptr, u_char st0_tag) +static void fptan(FPU_REG * st0_ptr, u_char st0_tag) { - FPU_REG *st_new_ptr; - int q; - u_char arg_sign = getsign(st0_ptr); + FPU_REG *st_new_ptr; + int q; + u_char arg_sign = getsign(st0_ptr); - /* Stack underflow has higher priority */ - if ( st0_tag == TAG_Empty ) - { - FPU_stack_underflow(); /* Puts a QNaN in st(0) */ - if ( control_word & CW_Invalid ) - { - st_new_ptr = &st(-1); - push(); - FPU_stack_underflow(); /* Puts a QNaN in the new st(0) */ + /* Stack underflow has higher priority */ + if (st0_tag == TAG_Empty) { + FPU_stack_underflow(); /* Puts a QNaN in st(0) */ + if (control_word & CW_Invalid) { + st_new_ptr = &st(-1); + push(); + FPU_stack_underflow(); /* Puts a QNaN in the new st(0) */ + } + return; } - return; - } - if ( STACK_OVERFLOW ) - { FPU_stack_overflow(); return; } - - if ( st0_tag == TAG_Valid ) - { - if ( exponent(st0_ptr) > -40 ) - { - if ( (q = trig_arg(st0_ptr, 0)) == -1 ) - { - /* Operand is out of range */ - return; - } - - poly_tan(st0_ptr); - setsign(st0_ptr, (q & 1) ^ (arg_sign != 0)); - set_precision_flag_up(); /* We do not really know if up or down */ + if (STACK_OVERFLOW) { + FPU_stack_overflow(); + return; } - else - { - /* For a small arg, the result == the argument */ - /* Underflow may happen */ - denormal_arg: + if (st0_tag == TAG_Valid) { + if (exponent(st0_ptr) > -40) { + if ((q = trig_arg(st0_ptr, 0)) == -1) { + /* Operand is out of range */ + return; + } - FPU_to_exp16(st0_ptr, st0_ptr); - - st0_tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign); - FPU_settag0(st0_tag); + poly_tan(st0_ptr); + setsign(st0_ptr, (q & 1) ^ (arg_sign != 0)); + set_precision_flag_up(); /* We do not really know if up or down */ + } else { + /* For a small arg, the result == the argument */ + /* Underflow may happen */ + + denormal_arg: + + FPU_to_exp16(st0_ptr, st0_ptr); + + st0_tag = + FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign); + FPU_settag0(st0_tag); + } + push(); + FPU_copy_to_reg0(&CONST_1, TAG_Valid); + return; } - push(); - FPU_copy_to_reg0(&CONST_1, TAG_Valid); - return; - } - if ( st0_tag == TAG_Zero ) - { - push(); - FPU_copy_to_reg0(&CONST_1, TAG_Valid); - setcc(0); - return; - } - - if ( st0_tag == TAG_Special ) - st0_tag = FPU_Special(st0_ptr); - - if ( st0_tag == TW_Denormal ) - { - if ( denormal_operand() < 0 ) - return; - - goto denormal_arg; - } - - if ( st0_tag == TW_Infinity ) - { - /* The 80486 treats infinity as an invalid operand */ - if ( arith_invalid(0) >= 0 ) - { - st_new_ptr = &st(-1); - push(); - arith_invalid(0); + if (st0_tag == TAG_Zero) { + push(); + FPU_copy_to_reg0(&CONST_1, TAG_Valid); + setcc(0); + return; } - return; - } - single_arg_2_error(st0_ptr, st0_tag); + if (st0_tag == TAG_Special) + st0_tag = FPU_Special(st0_ptr); + + if (st0_tag == TW_Denormal) { + if (denormal_operand() < 0) + return; + + goto denormal_arg; + } + + if (st0_tag == TW_Infinity) { + /* The 80486 treats infinity as an invalid operand */ + if (arith_invalid(0) >= 0) { + st_new_ptr = &st(-1); + push(); + arith_invalid(0); + } + return; + } + + single_arg_2_error(st0_ptr, st0_tag); } - -static void fxtract(FPU_REG *st0_ptr, u_char st0_tag) +static void fxtract(FPU_REG * st0_ptr, u_char st0_tag) { - FPU_REG *st_new_ptr; - u_char sign; - register FPU_REG *st1_ptr = st0_ptr; /* anticipate */ + FPU_REG *st_new_ptr; + u_char sign; + register FPU_REG *st1_ptr = st0_ptr; /* anticipate */ - if ( STACK_OVERFLOW ) - { FPU_stack_overflow(); return; } - - clear_C1(); - - if ( st0_tag == TAG_Valid ) - { - long e; - - push(); - sign = getsign(st1_ptr); - reg_copy(st1_ptr, st_new_ptr); - setexponent16(st_new_ptr, exponent(st_new_ptr)); - - denormal_arg: - - e = exponent16(st_new_ptr); - convert_l2reg(&e, 1); - setexponentpos(st_new_ptr, 0); - setsign(st_new_ptr, sign); - FPU_settag0(TAG_Valid); /* Needed if arg was a denormal */ - return; - } - else if ( st0_tag == TAG_Zero ) - { - sign = getsign(st0_ptr); - - if ( FPU_divide_by_zero(0, SIGN_NEG) < 0 ) - return; - - push(); - FPU_copy_to_reg0(&CONST_Z, TAG_Zero); - setsign(st_new_ptr, sign); - return; - } - - if ( st0_tag == TAG_Special ) - st0_tag = FPU_Special(st0_ptr); - - if ( st0_tag == TW_Denormal ) - { - if (denormal_operand() < 0 ) - return; - - push(); - sign = getsign(st1_ptr); - FPU_to_exp16(st1_ptr, st_new_ptr); - goto denormal_arg; - } - else if ( st0_tag == TW_Infinity ) - { - sign = getsign(st0_ptr); - setpositive(st0_ptr); - push(); - FPU_copy_to_reg0(&CONST_INF, TAG_Special); - setsign(st_new_ptr, sign); - return; - } - else if ( st0_tag == TW_NaN ) - { - if ( real_1op_NaN(st0_ptr) < 0 ) - return; - - push(); - FPU_copy_to_reg0(st0_ptr, TAG_Special); - return; - } - else if ( st0_tag == TAG_Empty ) - { - /* Is this the correct behaviour? */ - if ( control_word & EX_Invalid ) - { - FPU_stack_underflow(); - push(); - FPU_stack_underflow(); + if (STACK_OVERFLOW) { + FPU_stack_overflow(); + return; + } + + clear_C1(); + + if (st0_tag == TAG_Valid) { + long e; + + push(); + sign = getsign(st1_ptr); + reg_copy(st1_ptr, st_new_ptr); + setexponent16(st_new_ptr, exponent(st_new_ptr)); + + denormal_arg: + + e = exponent16(st_new_ptr); + convert_l2reg(&e, 1); + setexponentpos(st_new_ptr, 0); + setsign(st_new_ptr, sign); + FPU_settag0(TAG_Valid); /* Needed if arg was a denormal */ + return; + } else if (st0_tag == TAG_Zero) { + sign = getsign(st0_ptr); + + if (FPU_divide_by_zero(0, SIGN_NEG) < 0) + return; + + push(); + FPU_copy_to_reg0(&CONST_Z, TAG_Zero); + setsign(st_new_ptr, sign); + return; + } + + if (st0_tag == TAG_Special) + st0_tag = FPU_Special(st0_ptr); + + if (st0_tag == TW_Denormal) { + if (denormal_operand() < 0) + return; + + push(); + sign = getsign(st1_ptr); + FPU_to_exp16(st1_ptr, st_new_ptr); + goto denormal_arg; + } else if (st0_tag == TW_Infinity) { + sign = getsign(st0_ptr); + setpositive(st0_ptr); + push(); + FPU_copy_to_reg0(&CONST_INF, TAG_Special); + setsign(st_new_ptr, sign); + return; + } else if (st0_tag == TW_NaN) { + if (real_1op_NaN(st0_ptr) < 0) + return; + + push(); + FPU_copy_to_reg0(st0_ptr, TAG_Special); + return; + } else if (st0_tag == TAG_Empty) { + /* Is this the correct behaviour? */ + if (control_word & EX_Invalid) { + FPU_stack_underflow(); + push(); + FPU_stack_underflow(); + } else + EXCEPTION(EX_StackUnder); } - else - EXCEPTION(EX_StackUnder); - } #ifdef PARANOID - else - EXCEPTION(EX_INTERNAL | 0x119); + else + EXCEPTION(EX_INTERNAL | 0x119); #endif /* PARANOID */ } - static void fdecstp(void) { - clear_C1(); - top--; + clear_C1(); + top--; } static void fincstp(void) { - clear_C1(); - top++; + clear_C1(); + top++; } - -static void fsqrt_(FPU_REG *st0_ptr, u_char st0_tag) +static void fsqrt_(FPU_REG * st0_ptr, u_char st0_tag) { - int expon; + int expon; - clear_C1(); + clear_C1(); - if ( st0_tag == TAG_Valid ) - { - u_char tag; - - if (signnegative(st0_ptr)) - { - arith_invalid(0); /* sqrt(negative) is invalid */ - return; + if (st0_tag == TAG_Valid) { + u_char tag; + + if (signnegative(st0_ptr)) { + arith_invalid(0); /* sqrt(negative) is invalid */ + return; + } + + /* make st(0) in [1.0 .. 4.0) */ + expon = exponent(st0_ptr); + + denormal_arg: + + setexponent16(st0_ptr, (expon & 1)); + + /* Do the computation, the sign of the result will be positive. */ + tag = wm_sqrt(st0_ptr, 0, 0, control_word, SIGN_POS); + addexponent(st0_ptr, expon >> 1); + FPU_settag0(tag); + return; } - /* make st(0) in [1.0 .. 4.0) */ - expon = exponent(st0_ptr); + if (st0_tag == TAG_Zero) + return; - denormal_arg: + if (st0_tag == TAG_Special) + st0_tag = FPU_Special(st0_ptr); - setexponent16(st0_ptr, (expon & 1)); + if (st0_tag == TW_Infinity) { + if (signnegative(st0_ptr)) + arith_invalid(0); /* sqrt(-Infinity) is invalid */ + return; + } else if (st0_tag == TW_Denormal) { + if (signnegative(st0_ptr)) { + arith_invalid(0); /* sqrt(negative) is invalid */ + return; + } - /* Do the computation, the sign of the result will be positive. */ - tag = wm_sqrt(st0_ptr, 0, 0, control_word, SIGN_POS); - addexponent(st0_ptr, expon >> 1); - FPU_settag0(tag); - return; - } + if (denormal_operand() < 0) + return; - if ( st0_tag == TAG_Zero ) - return; + FPU_to_exp16(st0_ptr, st0_ptr); - if ( st0_tag == TAG_Special ) - st0_tag = FPU_Special(st0_ptr); + expon = exponent16(st0_ptr); - if ( st0_tag == TW_Infinity ) - { - if ( signnegative(st0_ptr) ) - arith_invalid(0); /* sqrt(-Infinity) is invalid */ - return; - } - else if ( st0_tag == TW_Denormal ) - { - if (signnegative(st0_ptr)) - { - arith_invalid(0); /* sqrt(negative) is invalid */ - return; + goto denormal_arg; } - if ( denormal_operand() < 0 ) - return; - - FPU_to_exp16(st0_ptr, st0_ptr); - - expon = exponent16(st0_ptr); - - goto denormal_arg; - } - - single_arg_error(st0_ptr, st0_tag); + single_arg_error(st0_ptr, st0_tag); } - -static void frndint_(FPU_REG *st0_ptr, u_char st0_tag) +static void frndint_(FPU_REG * st0_ptr, u_char st0_tag) { - int flags, tag; + int flags, tag; - if ( st0_tag == TAG_Valid ) - { - u_char sign; + if (st0_tag == TAG_Valid) { + u_char sign; - denormal_arg: + denormal_arg: - sign = getsign(st0_ptr); + sign = getsign(st0_ptr); - if (exponent(st0_ptr) > 63) - return; + if (exponent(st0_ptr) > 63) + return; - if ( st0_tag == TW_Denormal ) - { - if (denormal_operand() < 0 ) - return; + if (st0_tag == TW_Denormal) { + if (denormal_operand() < 0) + return; + } + + /* Fortunately, this can't overflow to 2^64 */ + if ((flags = FPU_round_to_int(st0_ptr, st0_tag))) + set_precision_flag(flags); + + setexponent16(st0_ptr, 63); + tag = FPU_normalize(st0_ptr); + setsign(st0_ptr, sign); + FPU_settag0(tag); + return; } - /* Fortunately, this can't overflow to 2^64 */ - if ( (flags = FPU_round_to_int(st0_ptr, st0_tag)) ) - set_precision_flag(flags); + if (st0_tag == TAG_Zero) + return; - setexponent16(st0_ptr, 63); - tag = FPU_normalize(st0_ptr); - setsign(st0_ptr, sign); - FPU_settag0(tag); - return; - } + if (st0_tag == TAG_Special) + st0_tag = FPU_Special(st0_ptr); - if ( st0_tag == TAG_Zero ) - return; - - if ( st0_tag == TAG_Special ) - st0_tag = FPU_Special(st0_ptr); - - if ( st0_tag == TW_Denormal ) - goto denormal_arg; - else if ( st0_tag == TW_Infinity ) - return; - else - single_arg_error(st0_ptr, st0_tag); + if (st0_tag == TW_Denormal) + goto denormal_arg; + else if (st0_tag == TW_Infinity) + return; + else + single_arg_error(st0_ptr, st0_tag); } - -static int fsin(FPU_REG *st0_ptr, u_char tag) +static int fsin(FPU_REG * st0_ptr, u_char tag) { - u_char arg_sign = getsign(st0_ptr); + u_char arg_sign = getsign(st0_ptr); - if ( tag == TAG_Valid ) - { - int q; + if (tag == TAG_Valid) { + int q; - if ( exponent(st0_ptr) > -40 ) - { - if ( (q = trig_arg(st0_ptr, 0)) == -1 ) - { - /* Operand is out of range */ - return 1; - } + if (exponent(st0_ptr) > -40) { + if ((q = trig_arg(st0_ptr, 0)) == -1) { + /* Operand is out of range */ + return 1; + } - poly_sine(st0_ptr); - - if (q & 2) - changesign(st0_ptr); + poly_sine(st0_ptr); - setsign(st0_ptr, getsign(st0_ptr) ^ arg_sign); + if (q & 2) + changesign(st0_ptr); - /* We do not really know if up or down */ - set_precision_flag_up(); - return 0; + setsign(st0_ptr, getsign(st0_ptr) ^ arg_sign); + + /* We do not really know if up or down */ + set_precision_flag_up(); + return 0; + } else { + /* For a small arg, the result == the argument */ + set_precision_flag_up(); /* Must be up. */ + return 0; + } } - else - { - /* For a small arg, the result == the argument */ - set_precision_flag_up(); /* Must be up. */ - return 0; + + if (tag == TAG_Zero) { + setcc(0); + return 0; } - } - if ( tag == TAG_Zero ) - { - setcc(0); - return 0; - } + if (tag == TAG_Special) + tag = FPU_Special(st0_ptr); - if ( tag == TAG_Special ) - tag = FPU_Special(st0_ptr); + if (tag == TW_Denormal) { + if (denormal_operand() < 0) + return 1; - if ( tag == TW_Denormal ) - { - if ( denormal_operand() < 0 ) - return 1; + /* For a small arg, the result == the argument */ + /* Underflow may happen */ + FPU_to_exp16(st0_ptr, st0_ptr); - /* For a small arg, the result == the argument */ - /* Underflow may happen */ - FPU_to_exp16(st0_ptr, st0_ptr); - - tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign); + tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign); - FPU_settag0(tag); + FPU_settag0(tag); - return 0; - } - else if ( tag == TW_Infinity ) - { - /* The 80486 treats infinity as an invalid operand */ - arith_invalid(0); - return 1; - } - else - { - single_arg_error(st0_ptr, tag); - return 1; - } + return 0; + } else if (tag == TW_Infinity) { + /* The 80486 treats infinity as an invalid operand */ + arith_invalid(0); + return 1; + } else { + single_arg_error(st0_ptr, tag); + return 1; + } } - -static int f_cos(FPU_REG *st0_ptr, u_char tag) +static int f_cos(FPU_REG * st0_ptr, u_char tag) { - u_char st0_sign; + u_char st0_sign; - st0_sign = getsign(st0_ptr); + st0_sign = getsign(st0_ptr); - if ( tag == TAG_Valid ) - { - int q; + if (tag == TAG_Valid) { + int q; - if ( exponent(st0_ptr) > -40 ) - { - if ( (exponent(st0_ptr) < 0) - || ((exponent(st0_ptr) == 0) - && (significand(st0_ptr) <= 0xc90fdaa22168c234LL)) ) - { - poly_cos(st0_ptr); + if (exponent(st0_ptr) > -40) { + if ((exponent(st0_ptr) < 0) + || ((exponent(st0_ptr) == 0) + && (significand(st0_ptr) <= + 0xc90fdaa22168c234LL))) { + poly_cos(st0_ptr); - /* We do not really know if up or down */ - set_precision_flag_down(); - - return 0; - } - else if ( (q = trig_arg(st0_ptr, FCOS)) != -1 ) - { - poly_sine(st0_ptr); + /* We do not really know if up or down */ + set_precision_flag_down(); - if ((q+1) & 2) - changesign(st0_ptr); + return 0; + } else if ((q = trig_arg(st0_ptr, FCOS)) != -1) { + poly_sine(st0_ptr); - /* We do not really know if up or down */ - set_precision_flag_down(); - - return 0; - } - else - { - /* Operand is out of range */ - return 1; - } - } - else - { - denormal_arg: + if ((q + 1) & 2) + changesign(st0_ptr); - setcc(0); - FPU_copy_to_reg0(&CONST_1, TAG_Valid); + /* We do not really know if up or down */ + set_precision_flag_down(); + + return 0; + } else { + /* Operand is out of range */ + return 1; + } + } else { + denormal_arg: + + setcc(0); + FPU_copy_to_reg0(&CONST_1, TAG_Valid); #ifdef PECULIAR_486 - set_precision_flag_down(); /* 80486 appears to do this. */ + set_precision_flag_down(); /* 80486 appears to do this. */ #else - set_precision_flag_up(); /* Must be up. */ + set_precision_flag_up(); /* Must be up. */ #endif /* PECULIAR_486 */ - return 0; + return 0; + } + } else if (tag == TAG_Zero) { + FPU_copy_to_reg0(&CONST_1, TAG_Valid); + setcc(0); + return 0; } - } - else if ( tag == TAG_Zero ) - { - FPU_copy_to_reg0(&CONST_1, TAG_Valid); - setcc(0); - return 0; - } - if ( tag == TAG_Special ) - tag = FPU_Special(st0_ptr); + if (tag == TAG_Special) + tag = FPU_Special(st0_ptr); - if ( tag == TW_Denormal ) - { - if ( denormal_operand() < 0 ) - return 1; + if (tag == TW_Denormal) { + if (denormal_operand() < 0) + return 1; - goto denormal_arg; - } - else if ( tag == TW_Infinity ) - { - /* The 80486 treats infinity as an invalid operand */ - arith_invalid(0); - return 1; - } - else - { - single_arg_error(st0_ptr, tag); /* requires st0_ptr == &st(0) */ - return 1; - } + goto denormal_arg; + } else if (tag == TW_Infinity) { + /* The 80486 treats infinity as an invalid operand */ + arith_invalid(0); + return 1; + } else { + single_arg_error(st0_ptr, tag); /* requires st0_ptr == &st(0) */ + return 1; + } } - -static void fcos(FPU_REG *st0_ptr, u_char st0_tag) +static void fcos(FPU_REG * st0_ptr, u_char st0_tag) { - f_cos(st0_ptr, st0_tag); + f_cos(st0_ptr, st0_tag); } - -static void fsincos(FPU_REG *st0_ptr, u_char st0_tag) +static void fsincos(FPU_REG * st0_ptr, u_char st0_tag) { - FPU_REG *st_new_ptr; - FPU_REG arg; - u_char tag; + FPU_REG *st_new_ptr; + FPU_REG arg; + u_char tag; - /* Stack underflow has higher priority */ - if ( st0_tag == TAG_Empty ) - { - FPU_stack_underflow(); /* Puts a QNaN in st(0) */ - if ( control_word & CW_Invalid ) - { - st_new_ptr = &st(-1); - push(); - FPU_stack_underflow(); /* Puts a QNaN in the new st(0) */ + /* Stack underflow has higher priority */ + if (st0_tag == TAG_Empty) { + FPU_stack_underflow(); /* Puts a QNaN in st(0) */ + if (control_word & CW_Invalid) { + st_new_ptr = &st(-1); + push(); + FPU_stack_underflow(); /* Puts a QNaN in the new st(0) */ + } + return; } - return; - } - if ( STACK_OVERFLOW ) - { FPU_stack_overflow(); return; } - - if ( st0_tag == TAG_Special ) - tag = FPU_Special(st0_ptr); - else - tag = st0_tag; - - if ( tag == TW_NaN ) - { - single_arg_2_error(st0_ptr, TW_NaN); - return; - } - else if ( tag == TW_Infinity ) - { - /* The 80486 treats infinity as an invalid operand */ - if ( arith_invalid(0) >= 0 ) - { - /* Masked response */ - push(); - arith_invalid(0); + if (STACK_OVERFLOW) { + FPU_stack_overflow(); + return; } - return; - } - reg_copy(st0_ptr, &arg); - if ( !fsin(st0_ptr, st0_tag) ) - { - push(); - FPU_copy_to_reg0(&arg, st0_tag); - f_cos(&st(0), st0_tag); - } - else - { - /* An error, so restore st(0) */ - FPU_copy_to_reg0(&arg, st0_tag); - } + if (st0_tag == TAG_Special) + tag = FPU_Special(st0_ptr); + else + tag = st0_tag; + + if (tag == TW_NaN) { + single_arg_2_error(st0_ptr, TW_NaN); + return; + } else if (tag == TW_Infinity) { + /* The 80486 treats infinity as an invalid operand */ + if (arith_invalid(0) >= 0) { + /* Masked response */ + push(); + arith_invalid(0); + } + return; + } + + reg_copy(st0_ptr, &arg); + if (!fsin(st0_ptr, st0_tag)) { + push(); + FPU_copy_to_reg0(&arg, st0_tag); + f_cos(&st(0), st0_tag); + } else { + /* An error, so restore st(0) */ + FPU_copy_to_reg0(&arg, st0_tag); + } } - /*---------------------------------------------------------------------------*/ /* The following all require two arguments: st(0) and st(1) */ @@ -826,1020 +743,901 @@ static void fsincos(FPU_REG *st0_ptr, u_char st0_tag) result must be zero. */ static void rem_kernel(unsigned long long st0, unsigned long long *y, - unsigned long long st1, - unsigned long long q, int n) + unsigned long long st1, unsigned long long q, int n) { - int dummy; - unsigned long long x; + int dummy; + unsigned long long x; - x = st0 << n; + x = st0 << n; - /* Do the required multiplication and subtraction in the one operation */ + /* Do the required multiplication and subtraction in the one operation */ - /* lsw x -= lsw st1 * lsw q */ - asm volatile ("mull %4; subl %%eax,%0; sbbl %%edx,%1" - :"=m" (((unsigned *)&x)[0]), "=m" (((unsigned *)&x)[1]), - "=a" (dummy) - :"2" (((unsigned *)&st1)[0]), "m" (((unsigned *)&q)[0]) - :"%dx"); - /* msw x -= msw st1 * lsw q */ - asm volatile ("mull %3; subl %%eax,%0" - :"=m" (((unsigned *)&x)[1]), "=a" (dummy) - :"1" (((unsigned *)&st1)[1]), "m" (((unsigned *)&q)[0]) - :"%dx"); - /* msw x -= lsw st1 * msw q */ - asm volatile ("mull %3; subl %%eax,%0" - :"=m" (((unsigned *)&x)[1]), "=a" (dummy) - :"1" (((unsigned *)&st1)[0]), "m" (((unsigned *)&q)[1]) - :"%dx"); + /* lsw x -= lsw st1 * lsw q */ + asm volatile ("mull %4; subl %%eax,%0; sbbl %%edx,%1":"=m" + (((unsigned *)&x)[0]), "=m"(((unsigned *)&x)[1]), + "=a"(dummy) + :"2"(((unsigned *)&st1)[0]), "m"(((unsigned *)&q)[0]) + :"%dx"); + /* msw x -= msw st1 * lsw q */ + asm volatile ("mull %3; subl %%eax,%0":"=m" (((unsigned *)&x)[1]), + "=a"(dummy) + :"1"(((unsigned *)&st1)[1]), "m"(((unsigned *)&q)[0]) + :"%dx"); + /* msw x -= lsw st1 * msw q */ + asm volatile ("mull %3; subl %%eax,%0":"=m" (((unsigned *)&x)[1]), + "=a"(dummy) + :"1"(((unsigned *)&st1)[0]), "m"(((unsigned *)&q)[1]) + :"%dx"); - *y = x; + *y = x; } - /* Remainder of st(0) / st(1) */ /* This routine produces exact results, i.e. there is never any rounding or truncation, etc of the result. */ -static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round) +static void do_fprem(FPU_REG * st0_ptr, u_char st0_tag, int round) { - FPU_REG *st1_ptr = &st(1); - u_char st1_tag = FPU_gettagi(1); + FPU_REG *st1_ptr = &st(1); + u_char st1_tag = FPU_gettagi(1); - if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) ) - { - FPU_REG tmp, st0, st1; - u_char st0_sign, st1_sign; - u_char tmptag; - int tag; - int old_cw; - int expdif; - long long q; - unsigned short saved_status; - int cc; + if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) { + FPU_REG tmp, st0, st1; + u_char st0_sign, st1_sign; + u_char tmptag; + int tag; + int old_cw; + int expdif; + long long q; + unsigned short saved_status; + int cc; - fprem_valid: - /* Convert registers for internal use. */ - st0_sign = FPU_to_exp16(st0_ptr, &st0); - st1_sign = FPU_to_exp16(st1_ptr, &st1); - expdif = exponent16(&st0) - exponent16(&st1); + fprem_valid: + /* Convert registers for internal use. */ + st0_sign = FPU_to_exp16(st0_ptr, &st0); + st1_sign = FPU_to_exp16(st1_ptr, &st1); + expdif = exponent16(&st0) - exponent16(&st1); - old_cw = control_word; - cc = 0; + old_cw = control_word; + cc = 0; - /* We want the status following the denorm tests, but don't want - the status changed by the arithmetic operations. */ - saved_status = partial_status; - control_word &= ~CW_RC; - control_word |= RC_CHOP; + /* We want the status following the denorm tests, but don't want + the status changed by the arithmetic operations. */ + saved_status = partial_status; + control_word &= ~CW_RC; + control_word |= RC_CHOP; - if ( expdif < 64 ) - { - /* This should be the most common case */ + if (expdif < 64) { + /* This should be the most common case */ - if ( expdif > -2 ) - { - u_char sign = st0_sign ^ st1_sign; - tag = FPU_u_div(&st0, &st1, &tmp, - PR_64_BITS | RC_CHOP | 0x3f, - sign); - setsign(&tmp, sign); + if (expdif > -2) { + u_char sign = st0_sign ^ st1_sign; + tag = FPU_u_div(&st0, &st1, &tmp, + PR_64_BITS | RC_CHOP | 0x3f, + sign); + setsign(&tmp, sign); - if ( exponent(&tmp) >= 0 ) - { - FPU_round_to_int(&tmp, tag); /* Fortunately, this can't - overflow to 2^64 */ - q = significand(&tmp); + if (exponent(&tmp) >= 0) { + FPU_round_to_int(&tmp, tag); /* Fortunately, this can't + overflow to 2^64 */ + q = significand(&tmp); - rem_kernel(significand(&st0), - &significand(&tmp), - significand(&st1), - q, expdif); + rem_kernel(significand(&st0), + &significand(&tmp), + significand(&st1), + q, expdif); - setexponent16(&tmp, exponent16(&st1)); - } - else - { - reg_copy(&st0, &tmp); - q = 0; - } + setexponent16(&tmp, exponent16(&st1)); + } else { + reg_copy(&st0, &tmp); + q = 0; + } - if ( (round == RC_RND) && (tmp.sigh & 0xc0000000) ) - { - /* We may need to subtract st(1) once more, - to get a result <= 1/2 of st(1). */ - unsigned long long x; - expdif = exponent16(&st1) - exponent16(&tmp); - if ( expdif <= 1 ) - { - if ( expdif == 0 ) - x = significand(&st1) - significand(&tmp); - else /* expdif is 1 */ - x = (significand(&st1) << 1) - significand(&tmp); - if ( (x < significand(&tmp)) || - /* or equi-distant (from 0 & st(1)) and q is odd */ - ((x == significand(&tmp)) && (q & 1) ) ) - { - st0_sign = ! st0_sign; - significand(&tmp) = x; - q++; + if ((round == RC_RND) + && (tmp.sigh & 0xc0000000)) { + /* We may need to subtract st(1) once more, + to get a result <= 1/2 of st(1). */ + unsigned long long x; + expdif = + exponent16(&st1) - exponent16(&tmp); + if (expdif <= 1) { + if (expdif == 0) + x = significand(&st1) - + significand(&tmp); + else /* expdif is 1 */ + x = (significand(&st1) + << 1) - + significand(&tmp); + if ((x < significand(&tmp)) || + /* or equi-distant (from 0 & st(1)) and q is odd */ + ((x == significand(&tmp)) + && (q & 1))) { + st0_sign = !st0_sign; + significand(&tmp) = x; + q++; + } + } + } + + if (q & 4) + cc |= SW_C0; + if (q & 2) + cc |= SW_C3; + if (q & 1) + cc |= SW_C1; + } else { + control_word = old_cw; + setcc(0); + return; } - } + } else { + /* There is a large exponent difference ( >= 64 ) */ + /* To make much sense, the code in this section should + be done at high precision. */ + int exp_1, N; + u_char sign; + + /* prevent overflow here */ + /* N is 'a number between 32 and 63' (p26-113) */ + reg_copy(&st0, &tmp); + tmptag = st0_tag; + N = (expdif & 0x0000001f) + 32; /* This choice gives results + identical to an AMD 486 */ + setexponent16(&tmp, N); + exp_1 = exponent16(&st1); + setexponent16(&st1, 0); + expdif -= N; + + sign = getsign(&tmp) ^ st1_sign; + tag = + FPU_u_div(&tmp, &st1, &tmp, + PR_64_BITS | RC_CHOP | 0x3f, sign); + setsign(&tmp, sign); + + FPU_round_to_int(&tmp, tag); /* Fortunately, this can't + overflow to 2^64 */ + + rem_kernel(significand(&st0), + &significand(&tmp), + significand(&st1), + significand(&tmp), exponent(&tmp) + ); + setexponent16(&tmp, exp_1 + expdif); + + /* It is possible for the operation to be complete here. + What does the IEEE standard say? The Intel 80486 manual + implies that the operation will never be completed at this + point, and the behaviour of a real 80486 confirms this. + */ + if (!(tmp.sigh | tmp.sigl)) { + /* The result is zero */ + control_word = old_cw; + partial_status = saved_status; + FPU_copy_to_reg0(&CONST_Z, TAG_Zero); + setsign(&st0, st0_sign); +#ifdef PECULIAR_486 + setcc(SW_C2); +#else + setcc(0); +#endif /* PECULIAR_486 */ + return; + } + cc = SW_C2; } - if (q & 4) cc |= SW_C0; - if (q & 2) cc |= SW_C3; - if (q & 1) cc |= SW_C1; - } - else - { - control_word = old_cw; - setcc(0); - return; - } - } - else - { - /* There is a large exponent difference ( >= 64 ) */ - /* To make much sense, the code in this section should - be done at high precision. */ - int exp_1, N; - u_char sign; + control_word = old_cw; + partial_status = saved_status; + tag = FPU_normalize_nuo(&tmp); + reg_copy(&tmp, st0_ptr); - /* prevent overflow here */ - /* N is 'a number between 32 and 63' (p26-113) */ - reg_copy(&st0, &tmp); - tmptag = st0_tag; - N = (expdif & 0x0000001f) + 32; /* This choice gives results - identical to an AMD 486 */ - setexponent16(&tmp, N); - exp_1 = exponent16(&st1); - setexponent16(&st1, 0); - expdif -= N; + /* The only condition to be looked for is underflow, + and it can occur here only if underflow is unmasked. */ + if ((exponent16(&tmp) <= EXP_UNDER) && (tag != TAG_Zero) + && !(control_word & CW_Underflow)) { + setcc(cc); + tag = arith_underflow(st0_ptr); + setsign(st0_ptr, st0_sign); + FPU_settag0(tag); + return; + } else if ((exponent16(&tmp) > EXP_UNDER) || (tag == TAG_Zero)) { + stdexp(st0_ptr); + setsign(st0_ptr, st0_sign); + } else { + tag = + FPU_round(st0_ptr, 0, 0, FULL_PRECISION, st0_sign); + } + FPU_settag0(tag); + setcc(cc); - sign = getsign(&tmp) ^ st1_sign; - tag = FPU_u_div(&tmp, &st1, &tmp, PR_64_BITS | RC_CHOP | 0x3f, - sign); - setsign(&tmp, sign); - - FPU_round_to_int(&tmp, tag); /* Fortunately, this can't - overflow to 2^64 */ - - rem_kernel(significand(&st0), - &significand(&tmp), - significand(&st1), - significand(&tmp), - exponent(&tmp) - ); - setexponent16(&tmp, exp_1 + expdif); - - /* It is possible for the operation to be complete here. - What does the IEEE standard say? The Intel 80486 manual - implies that the operation will never be completed at this - point, and the behaviour of a real 80486 confirms this. - */ - if ( !(tmp.sigh | tmp.sigl) ) - { - /* The result is zero */ - control_word = old_cw; - partial_status = saved_status; - FPU_copy_to_reg0(&CONST_Z, TAG_Zero); - setsign(&st0, st0_sign); -#ifdef PECULIAR_486 - setcc(SW_C2); -#else - setcc(0); -#endif /* PECULIAR_486 */ - return; - } - cc = SW_C2; + return; } - control_word = old_cw; - partial_status = saved_status; - tag = FPU_normalize_nuo(&tmp); - reg_copy(&tmp, st0_ptr); + if (st0_tag == TAG_Special) + st0_tag = FPU_Special(st0_ptr); + if (st1_tag == TAG_Special) + st1_tag = FPU_Special(st1_ptr); - /* The only condition to be looked for is underflow, - and it can occur here only if underflow is unmasked. */ - if ( (exponent16(&tmp) <= EXP_UNDER) && (tag != TAG_Zero) - && !(control_word & CW_Underflow) ) - { - setcc(cc); - tag = arith_underflow(st0_ptr); - setsign(st0_ptr, st0_sign); - FPU_settag0(tag); - return; - } - else if ( (exponent16(&tmp) > EXP_UNDER) || (tag == TAG_Zero) ) - { - stdexp(st0_ptr); - setsign(st0_ptr, st0_sign); - } - else - { - tag = FPU_round(st0_ptr, 0, 0, FULL_PRECISION, st0_sign); - } - FPU_settag0(tag); - setcc(cc); - - return; - } - - if ( st0_tag == TAG_Special ) - st0_tag = FPU_Special(st0_ptr); - if ( st1_tag == TAG_Special ) - st1_tag = FPU_Special(st1_ptr); - - if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal)) + if (((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal)) || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid)) - || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) ) - { - if ( denormal_operand() < 0 ) - return; - goto fprem_valid; - } - else if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) ) - { - FPU_stack_underflow(); - return; - } - else if ( st0_tag == TAG_Zero ) - { - if ( st1_tag == TAG_Valid ) - { - setcc(0); return; - } - else if ( st1_tag == TW_Denormal ) - { - if ( denormal_operand() < 0 ) - return; - setcc(0); return; - } - else if ( st1_tag == TAG_Zero ) - { arith_invalid(0); return; } /* fprem(?,0) always invalid */ - else if ( st1_tag == TW_Infinity ) - { setcc(0); return; } - } - else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) ) - { - if ( st1_tag == TAG_Zero ) - { - arith_invalid(0); /* fprem(Valid,Zero) is invalid */ - return; - } - else if ( st1_tag != TW_NaN ) - { - if ( ((st0_tag == TW_Denormal) || (st1_tag == TW_Denormal)) - && (denormal_operand() < 0) ) - return; + || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal))) { + if (denormal_operand() < 0) + return; + goto fprem_valid; + } else if ((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) { + FPU_stack_underflow(); + return; + } else if (st0_tag == TAG_Zero) { + if (st1_tag == TAG_Valid) { + setcc(0); + return; + } else if (st1_tag == TW_Denormal) { + if (denormal_operand() < 0) + return; + setcc(0); + return; + } else if (st1_tag == TAG_Zero) { + arith_invalid(0); + return; + } /* fprem(?,0) always invalid */ + else if (st1_tag == TW_Infinity) { + setcc(0); + return; + } + } else if ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) { + if (st1_tag == TAG_Zero) { + arith_invalid(0); /* fprem(Valid,Zero) is invalid */ + return; + } else if (st1_tag != TW_NaN) { + if (((st0_tag == TW_Denormal) + || (st1_tag == TW_Denormal)) + && (denormal_operand() < 0)) + return; - if ( st1_tag == TW_Infinity ) - { - /* fprem(Valid,Infinity) is o.k. */ - setcc(0); return; - } + if (st1_tag == TW_Infinity) { + /* fprem(Valid,Infinity) is o.k. */ + setcc(0); + return; + } + } + } else if (st0_tag == TW_Infinity) { + if (st1_tag != TW_NaN) { + arith_invalid(0); /* fprem(Infinity,?) is invalid */ + return; + } } - } - else if ( st0_tag == TW_Infinity ) - { - if ( st1_tag != TW_NaN ) - { - arith_invalid(0); /* fprem(Infinity,?) is invalid */ - return; - } - } - /* One of the registers must contain a NaN if we got here. */ + /* One of the registers must contain a NaN if we got here. */ #ifdef PARANOID - if ( (st0_tag != TW_NaN) && (st1_tag != TW_NaN) ) - EXCEPTION(EX_INTERNAL | 0x118); + if ((st0_tag != TW_NaN) && (st1_tag != TW_NaN)) + EXCEPTION(EX_INTERNAL | 0x118); #endif /* PARANOID */ - real_2op_NaN(st1_ptr, st1_tag, 0, st1_ptr); + real_2op_NaN(st1_ptr, st1_tag, 0, st1_ptr); } - /* ST(1) <- ST(1) * log ST; pop ST */ -static void fyl2x(FPU_REG *st0_ptr, u_char st0_tag) +static void fyl2x(FPU_REG * st0_ptr, u_char st0_tag) { - FPU_REG *st1_ptr = &st(1), exponent; - u_char st1_tag = FPU_gettagi(1); - u_char sign; - int e, tag; + FPU_REG *st1_ptr = &st(1), exponent; + u_char st1_tag = FPU_gettagi(1); + u_char sign; + int e, tag; - clear_C1(); + clear_C1(); - if ( (st0_tag == TAG_Valid) && (st1_tag == TAG_Valid) ) - { - both_valid: - /* Both regs are Valid or Denormal */ - if ( signpositive(st0_ptr) ) - { - if ( st0_tag == TW_Denormal ) - FPU_to_exp16(st0_ptr, st0_ptr); - else - /* Convert st(0) for internal use. */ - setexponent16(st0_ptr, exponent(st0_ptr)); + if ((st0_tag == TAG_Valid) && (st1_tag == TAG_Valid)) { + both_valid: + /* Both regs are Valid or Denormal */ + if (signpositive(st0_ptr)) { + if (st0_tag == TW_Denormal) + FPU_to_exp16(st0_ptr, st0_ptr); + else + /* Convert st(0) for internal use. */ + setexponent16(st0_ptr, exponent(st0_ptr)); - if ( (st0_ptr->sigh == 0x80000000) && (st0_ptr->sigl == 0) ) - { - /* Special case. The result can be precise. */ - u_char esign; - e = exponent16(st0_ptr); - if ( e >= 0 ) - { - exponent.sigh = e; - esign = SIGN_POS; + if ((st0_ptr->sigh == 0x80000000) + && (st0_ptr->sigl == 0)) { + /* Special case. The result can be precise. */ + u_char esign; + e = exponent16(st0_ptr); + if (e >= 0) { + exponent.sigh = e; + esign = SIGN_POS; + } else { + exponent.sigh = -e; + esign = SIGN_NEG; + } + exponent.sigl = 0; + setexponent16(&exponent, 31); + tag = FPU_normalize_nuo(&exponent); + stdexp(&exponent); + setsign(&exponent, esign); + tag = + FPU_mul(&exponent, tag, 1, FULL_PRECISION); + if (tag >= 0) + FPU_settagi(1, tag); + } else { + /* The usual case */ + sign = getsign(st1_ptr); + if (st1_tag == TW_Denormal) + FPU_to_exp16(st1_ptr, st1_ptr); + else + /* Convert st(1) for internal use. */ + setexponent16(st1_ptr, + exponent(st1_ptr)); + poly_l2(st0_ptr, st1_ptr, sign); + } + } else { + /* negative */ + if (arith_invalid(1) < 0) + return; } - else - { - exponent.sigh = -e; - esign = SIGN_NEG; + + FPU_pop(); + + return; + } + + if (st0_tag == TAG_Special) + st0_tag = FPU_Special(st0_ptr); + if (st1_tag == TAG_Special) + st1_tag = FPU_Special(st1_ptr); + + if ((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) { + FPU_stack_underflow_pop(1); + return; + } else if ((st0_tag <= TW_Denormal) && (st1_tag <= TW_Denormal)) { + if (st0_tag == TAG_Zero) { + if (st1_tag == TAG_Zero) { + /* Both args zero is invalid */ + if (arith_invalid(1) < 0) + return; + } else { + u_char sign; + sign = getsign(st1_ptr) ^ SIGN_NEG; + if (FPU_divide_by_zero(1, sign) < 0) + return; + + setsign(st1_ptr, sign); + } + } else if (st1_tag == TAG_Zero) { + /* st(1) contains zero, st(0) valid <> 0 */ + /* Zero is the valid answer */ + sign = getsign(st1_ptr); + + if (signnegative(st0_ptr)) { + /* log(negative) */ + if (arith_invalid(1) < 0) + return; + } else if ((st0_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; + else { + if (exponent(st0_ptr) < 0) + sign ^= SIGN_NEG; + + FPU_copy_to_reg1(&CONST_Z, TAG_Zero); + setsign(st1_ptr, sign); + } + } else { + /* One or both operands are denormals. */ + if (denormal_operand() < 0) + return; + goto both_valid; } - exponent.sigl = 0; - setexponent16(&exponent, 31); - tag = FPU_normalize_nuo(&exponent); - stdexp(&exponent); - setsign(&exponent, esign); - tag = FPU_mul(&exponent, tag, 1, FULL_PRECISION); - if ( tag >= 0 ) - FPU_settagi(1, tag); - } - else - { - /* The usual case */ - sign = getsign(st1_ptr); - if ( st1_tag == TW_Denormal ) - FPU_to_exp16(st1_ptr, st1_ptr); - else - /* Convert st(1) for internal use. */ - setexponent16(st1_ptr, exponent(st1_ptr)); - poly_l2(st0_ptr, st1_ptr, sign); - } + } else if ((st0_tag == TW_NaN) || (st1_tag == TW_NaN)) { + if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0) + return; } - else - { - /* negative */ - if ( arith_invalid(1) < 0 ) - return; + /* One or both arg must be an infinity */ + else if (st0_tag == TW_Infinity) { + if ((signnegative(st0_ptr)) || (st1_tag == TAG_Zero)) { + /* log(-infinity) or 0*log(infinity) */ + if (arith_invalid(1) < 0) + return; + } else { + u_char sign = getsign(st1_ptr); + + if ((st1_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; + + FPU_copy_to_reg1(&CONST_INF, TAG_Special); + setsign(st1_ptr, sign); + } } + /* st(1) must be infinity here */ + else if (((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) + && (signpositive(st0_ptr))) { + if (exponent(st0_ptr) >= 0) { + if ((exponent(st0_ptr) == 0) && + (st0_ptr->sigh == 0x80000000) && + (st0_ptr->sigl == 0)) { + /* st(0) holds 1.0 */ + /* infinity*log(1) */ + if (arith_invalid(1) < 0) + return; + } + /* else st(0) is positive and > 1.0 */ + } else { + /* st(0) is positive and < 1.0 */ - FPU_pop(); + if ((st0_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; - return; - } - - if ( st0_tag == TAG_Special ) - st0_tag = FPU_Special(st0_ptr); - if ( st1_tag == TAG_Special ) - st1_tag = FPU_Special(st1_ptr); - - if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) ) - { - FPU_stack_underflow_pop(1); - return; - } - else if ( (st0_tag <= TW_Denormal) && (st1_tag <= TW_Denormal) ) - { - if ( st0_tag == TAG_Zero ) - { - if ( st1_tag == TAG_Zero ) - { - /* Both args zero is invalid */ - if ( arith_invalid(1) < 0 ) - return; - } - else - { - u_char sign; - sign = getsign(st1_ptr)^SIGN_NEG; - if ( FPU_divide_by_zero(1, sign) < 0 ) - return; - - setsign(st1_ptr, sign); - } - } - else if ( st1_tag == TAG_Zero ) - { - /* st(1) contains zero, st(0) valid <> 0 */ - /* Zero is the valid answer */ - sign = getsign(st1_ptr); - - if ( signnegative(st0_ptr) ) - { - /* log(negative) */ - if ( arith_invalid(1) < 0 ) - return; - } - else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; - else - { - if ( exponent(st0_ptr) < 0 ) - sign ^= SIGN_NEG; - - FPU_copy_to_reg1(&CONST_Z, TAG_Zero); - setsign(st1_ptr, sign); - } - } - else - { - /* One or both operands are denormals. */ - if ( denormal_operand() < 0 ) - return; - goto both_valid; - } - } - else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) ) - { - if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 ) - return; - } - /* One or both arg must be an infinity */ - else if ( st0_tag == TW_Infinity ) - { - if ( (signnegative(st0_ptr)) || (st1_tag == TAG_Zero) ) - { - /* log(-infinity) or 0*log(infinity) */ - if ( arith_invalid(1) < 0 ) - return; - } - else - { - u_char sign = getsign(st1_ptr); - - if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; - - FPU_copy_to_reg1(&CONST_INF, TAG_Special); - setsign(st1_ptr, sign); - } - } - /* st(1) must be infinity here */ - else if ( ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) - && ( signpositive(st0_ptr) ) ) - { - if ( exponent(st0_ptr) >= 0 ) - { - if ( (exponent(st0_ptr) == 0) && - (st0_ptr->sigh == 0x80000000) && - (st0_ptr->sigl == 0) ) - { - /* st(0) holds 1.0 */ - /* infinity*log(1) */ - if ( arith_invalid(1) < 0 ) - return; - } - /* else st(0) is positive and > 1.0 */ - } - else - { - /* st(0) is positive and < 1.0 */ - - if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; - - changesign(st1_ptr); - } - } - else - { - /* st(0) must be zero or negative */ - if ( st0_tag == TAG_Zero ) - { - /* This should be invalid, but a real 80486 is happy with it. */ + changesign(st1_ptr); + } + } else { + /* st(0) must be zero or negative */ + if (st0_tag == TAG_Zero) { + /* This should be invalid, but a real 80486 is happy with it. */ #ifndef PECULIAR_486 - sign = getsign(st1_ptr); - if ( FPU_divide_by_zero(1, sign) < 0 ) - return; + sign = getsign(st1_ptr); + if (FPU_divide_by_zero(1, sign) < 0) + return; #endif /* PECULIAR_486 */ - changesign(st1_ptr); + changesign(st1_ptr); + } else if (arith_invalid(1) < 0) /* log(negative) */ + return; } - else if ( arith_invalid(1) < 0 ) /* log(negative) */ - return; - } - FPU_pop(); + FPU_pop(); } - -static void fpatan(FPU_REG *st0_ptr, u_char st0_tag) +static void fpatan(FPU_REG * st0_ptr, u_char st0_tag) { - FPU_REG *st1_ptr = &st(1); - u_char st1_tag = FPU_gettagi(1); - int tag; + FPU_REG *st1_ptr = &st(1); + u_char st1_tag = FPU_gettagi(1); + int tag; - clear_C1(); - if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) ) - { - valid_atan: + clear_C1(); + if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) { + valid_atan: - poly_atan(st0_ptr, st0_tag, st1_ptr, st1_tag); + poly_atan(st0_ptr, st0_tag, st1_ptr, st1_tag); - FPU_pop(); + FPU_pop(); - return; - } - - if ( st0_tag == TAG_Special ) - st0_tag = FPU_Special(st0_ptr); - if ( st1_tag == TAG_Special ) - st1_tag = FPU_Special(st1_ptr); - - if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal)) - || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid)) - || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) ) - { - if ( denormal_operand() < 0 ) - return; - - goto valid_atan; - } - else if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) ) - { - FPU_stack_underflow_pop(1); - return; - } - else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) ) - { - if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) >= 0 ) - FPU_pop(); - return; - } - else if ( (st0_tag == TW_Infinity) || (st1_tag == TW_Infinity) ) - { - u_char sign = getsign(st1_ptr); - if ( st0_tag == TW_Infinity ) - { - if ( st1_tag == TW_Infinity ) - { - if ( signpositive(st0_ptr) ) - { - FPU_copy_to_reg1(&CONST_PI4, TAG_Valid); - } - else - { - setpositive(st1_ptr); - tag = FPU_u_add(&CONST_PI4, &CONST_PI2, st1_ptr, - FULL_PRECISION, SIGN_POS, - exponent(&CONST_PI4), exponent(&CONST_PI2)); - if ( tag >= 0 ) - FPU_settagi(1, tag); - } - } - else - { - if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) ) return; + } - if ( signpositive(st0_ptr) ) - { - FPU_copy_to_reg1(&CONST_Z, TAG_Zero); - setsign(st1_ptr, sign); /* An 80486 preserves the sign */ - FPU_pop(); - return; + if (st0_tag == TAG_Special) + st0_tag = FPU_Special(st0_ptr); + if (st1_tag == TAG_Special) + st1_tag = FPU_Special(st1_ptr); + + if (((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal)) + || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid)) + || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal))) { + if (denormal_operand() < 0) + return; + + goto valid_atan; + } else if ((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) { + FPU_stack_underflow_pop(1); + return; + } else if ((st0_tag == TW_NaN) || (st1_tag == TW_NaN)) { + if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) >= 0) + FPU_pop(); + return; + } else if ((st0_tag == TW_Infinity) || (st1_tag == TW_Infinity)) { + u_char sign = getsign(st1_ptr); + if (st0_tag == TW_Infinity) { + if (st1_tag == TW_Infinity) { + if (signpositive(st0_ptr)) { + FPU_copy_to_reg1(&CONST_PI4, TAG_Valid); + } else { + setpositive(st1_ptr); + tag = + FPU_u_add(&CONST_PI4, &CONST_PI2, + st1_ptr, FULL_PRECISION, + SIGN_POS, + exponent(&CONST_PI4), + exponent(&CONST_PI2)); + if (tag >= 0) + FPU_settagi(1, tag); + } + } else { + if ((st1_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; + + if (signpositive(st0_ptr)) { + FPU_copy_to_reg1(&CONST_Z, TAG_Zero); + setsign(st1_ptr, sign); /* An 80486 preserves the sign */ + FPU_pop(); + return; + } else { + FPU_copy_to_reg1(&CONST_PI, TAG_Valid); + } + } + } else { + /* st(1) is infinity, st(0) not infinity */ + if ((st0_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; + + FPU_copy_to_reg1(&CONST_PI2, TAG_Valid); } - else - { - FPU_copy_to_reg1(&CONST_PI, TAG_Valid); + setsign(st1_ptr, sign); + } else if (st1_tag == TAG_Zero) { + /* st(0) must be valid or zero */ + u_char sign = getsign(st1_ptr); + + if ((st0_tag == TW_Denormal) && (denormal_operand() < 0)) + return; + + if (signpositive(st0_ptr)) { + /* An 80486 preserves the sign */ + FPU_pop(); + return; } - } + + FPU_copy_to_reg1(&CONST_PI, TAG_Valid); + setsign(st1_ptr, sign); + } else if (st0_tag == TAG_Zero) { + /* st(1) must be TAG_Valid here */ + u_char sign = getsign(st1_ptr); + + if ((st1_tag == TW_Denormal) && (denormal_operand() < 0)) + return; + + FPU_copy_to_reg1(&CONST_PI2, TAG_Valid); + setsign(st1_ptr, sign); } - else - { - /* st(1) is infinity, st(0) not infinity */ - if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; - - FPU_copy_to_reg1(&CONST_PI2, TAG_Valid); - } - setsign(st1_ptr, sign); - } - else if ( st1_tag == TAG_Zero ) - { - /* st(0) must be valid or zero */ - u_char sign = getsign(st1_ptr); - - if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; - - if ( signpositive(st0_ptr) ) - { - /* An 80486 preserves the sign */ - FPU_pop(); - return; - } - - FPU_copy_to_reg1(&CONST_PI, TAG_Valid); - setsign(st1_ptr, sign); - } - else if ( st0_tag == TAG_Zero ) - { - /* st(1) must be TAG_Valid here */ - u_char sign = getsign(st1_ptr); - - if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; - - FPU_copy_to_reg1(&CONST_PI2, TAG_Valid); - setsign(st1_ptr, sign); - } #ifdef PARANOID - else - EXCEPTION(EX_INTERNAL | 0x125); + else + EXCEPTION(EX_INTERNAL | 0x125); #endif /* PARANOID */ - FPU_pop(); - set_precision_flag_up(); /* We do not really know if up or down */ + FPU_pop(); + set_precision_flag_up(); /* We do not really know if up or down */ } - -static void fprem(FPU_REG *st0_ptr, u_char st0_tag) +static void fprem(FPU_REG * st0_ptr, u_char st0_tag) { - do_fprem(st0_ptr, st0_tag, RC_CHOP); + do_fprem(st0_ptr, st0_tag, RC_CHOP); } - -static void fprem1(FPU_REG *st0_ptr, u_char st0_tag) +static void fprem1(FPU_REG * st0_ptr, u_char st0_tag) { - do_fprem(st0_ptr, st0_tag, RC_RND); + do_fprem(st0_ptr, st0_tag, RC_RND); } - -static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag) +static void fyl2xp1(FPU_REG * st0_ptr, u_char st0_tag) { - u_char sign, sign1; - FPU_REG *st1_ptr = &st(1), a, b; - u_char st1_tag = FPU_gettagi(1); + u_char sign, sign1; + FPU_REG *st1_ptr = &st(1), a, b; + u_char st1_tag = FPU_gettagi(1); - clear_C1(); - if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) ) - { - valid_yl2xp1: + clear_C1(); + if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) { + valid_yl2xp1: - sign = getsign(st0_ptr); - sign1 = getsign(st1_ptr); + sign = getsign(st0_ptr); + sign1 = getsign(st1_ptr); - FPU_to_exp16(st0_ptr, &a); - FPU_to_exp16(st1_ptr, &b); + FPU_to_exp16(st0_ptr, &a); + FPU_to_exp16(st1_ptr, &b); - if ( poly_l2p1(sign, sign1, &a, &b, st1_ptr) ) - return; + if (poly_l2p1(sign, sign1, &a, &b, st1_ptr)) + return; - FPU_pop(); - return; - } + FPU_pop(); + return; + } - if ( st0_tag == TAG_Special ) - st0_tag = FPU_Special(st0_ptr); - if ( st1_tag == TAG_Special ) - st1_tag = FPU_Special(st1_ptr); + if (st0_tag == TAG_Special) + st0_tag = FPU_Special(st0_ptr); + if (st1_tag == TAG_Special) + st1_tag = FPU_Special(st1_ptr); - if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal)) + if (((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal)) || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid)) - || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) ) - { - if ( denormal_operand() < 0 ) - return; + || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal))) { + if (denormal_operand() < 0) + return; - goto valid_yl2xp1; - } - else if ( (st0_tag == TAG_Empty) | (st1_tag == TAG_Empty) ) - { - FPU_stack_underflow_pop(1); - return; - } - else if ( st0_tag == TAG_Zero ) - { - switch ( st1_tag ) - { - case TW_Denormal: - if ( denormal_operand() < 0 ) - return; + goto valid_yl2xp1; + } else if ((st0_tag == TAG_Empty) | (st1_tag == TAG_Empty)) { + FPU_stack_underflow_pop(1); + return; + } else if (st0_tag == TAG_Zero) { + switch (st1_tag) { + case TW_Denormal: + if (denormal_operand() < 0) + return; - case TAG_Zero: - case TAG_Valid: - setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr)); - FPU_copy_to_reg1(st0_ptr, st0_tag); - break; + case TAG_Zero: + case TAG_Valid: + setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr)); + FPU_copy_to_reg1(st0_ptr, st0_tag); + break; - case TW_Infinity: - /* Infinity*log(1) */ - if ( arith_invalid(1) < 0 ) - return; - break; + case TW_Infinity: + /* Infinity*log(1) */ + if (arith_invalid(1) < 0) + return; + break; - case TW_NaN: - if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 ) - return; - break; + case TW_NaN: + if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0) + return; + break; - default: + default: #ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x116); - return; + EXCEPTION(EX_INTERNAL | 0x116); + return; #endif /* PARANOID */ - break; - } - } - else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) ) - { - switch ( st1_tag ) - { - case TAG_Zero: - if ( signnegative(st0_ptr) ) - { - if ( exponent(st0_ptr) >= 0 ) - { - /* st(0) holds <= -1.0 */ -#ifdef PECULIAR_486 /* Stupid 80486 doesn't worry about log(negative). */ - changesign(st1_ptr); -#else - if ( arith_invalid(1) < 0 ) - return; -#endif /* PECULIAR_486 */ + break; } - else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; - else - changesign(st1_ptr); - } - else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; - break; - - case TW_Infinity: - if ( signnegative(st0_ptr) ) - { - if ( (exponent(st0_ptr) >= 0) && - !((st0_ptr->sigh == 0x80000000) && - (st0_ptr->sigl == 0)) ) - { - /* st(0) holds < -1.0 */ -#ifdef PECULIAR_486 /* Stupid 80486 doesn't worry about log(negative). */ - changesign(st1_ptr); + } else if ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) { + switch (st1_tag) { + case TAG_Zero: + if (signnegative(st0_ptr)) { + if (exponent(st0_ptr) >= 0) { + /* st(0) holds <= -1.0 */ +#ifdef PECULIAR_486 /* Stupid 80486 doesn't worry about log(negative). */ + changesign(st1_ptr); #else - if ( arith_invalid(1) < 0 ) return; + if (arith_invalid(1) < 0) + return; #endif /* PECULIAR_486 */ + } else if ((st0_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; + else + changesign(st1_ptr); + } else if ((st0_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; + break; + + case TW_Infinity: + if (signnegative(st0_ptr)) { + if ((exponent(st0_ptr) >= 0) && + !((st0_ptr->sigh == 0x80000000) && + (st0_ptr->sigl == 0))) { + /* st(0) holds < -1.0 */ +#ifdef PECULIAR_486 /* Stupid 80486 doesn't worry about log(negative). */ + changesign(st1_ptr); +#else + if (arith_invalid(1) < 0) + return; +#endif /* PECULIAR_486 */ + } else if ((st0_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; + else + changesign(st1_ptr); + } else if ((st0_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; + break; + + case TW_NaN: + if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0) + return; } - else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; - else - changesign(st1_ptr); - } - else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; - break; - case TW_NaN: - if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 ) - return; - } - - } - else if ( st0_tag == TW_NaN ) - { - if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 ) - return; - } - else if ( st0_tag == TW_Infinity ) - { - if ( st1_tag == TW_NaN ) - { - if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 ) - return; - } - else if ( signnegative(st0_ptr) ) - { + } else if (st0_tag == TW_NaN) { + if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0) + return; + } else if (st0_tag == TW_Infinity) { + if (st1_tag == TW_NaN) { + if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0) + return; + } else if (signnegative(st0_ptr)) { #ifndef PECULIAR_486 - /* This should have higher priority than denormals, but... */ - if ( arith_invalid(1) < 0 ) /* log(-infinity) */ - return; + /* This should have higher priority than denormals, but... */ + if (arith_invalid(1) < 0) /* log(-infinity) */ + return; #endif /* PECULIAR_486 */ - if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; + if ((st1_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; #ifdef PECULIAR_486 - /* Denormal operands actually get higher priority */ - if ( arith_invalid(1) < 0 ) /* log(-infinity) */ - return; + /* Denormal operands actually get higher priority */ + if (arith_invalid(1) < 0) /* log(-infinity) */ + return; #endif /* PECULIAR_486 */ - } - else if ( st1_tag == TAG_Zero ) - { - /* log(infinity) */ - if ( arith_invalid(1) < 0 ) - return; - } - - /* st(1) must be valid here. */ + } else if (st1_tag == TAG_Zero) { + /* log(infinity) */ + if (arith_invalid(1) < 0) + return; + } - else if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; + /* st(1) must be valid here. */ - /* The Manual says that log(Infinity) is invalid, but a real - 80486 sensibly says that it is o.k. */ - else - { - u_char sign = getsign(st1_ptr); - FPU_copy_to_reg1(&CONST_INF, TAG_Special); - setsign(st1_ptr, sign); + else if ((st1_tag == TW_Denormal) && (denormal_operand() < 0)) + return; + + /* The Manual says that log(Infinity) is invalid, but a real + 80486 sensibly says that it is o.k. */ + else { + u_char sign = getsign(st1_ptr); + FPU_copy_to_reg1(&CONST_INF, TAG_Special); + setsign(st1_ptr, sign); + } } - } #ifdef PARANOID - else - { - EXCEPTION(EX_INTERNAL | 0x117); - return; - } + else { + EXCEPTION(EX_INTERNAL | 0x117); + return; + } #endif /* PARANOID */ - FPU_pop(); - return; + FPU_pop(); + return; } - -static void fscale(FPU_REG *st0_ptr, u_char st0_tag) +static void fscale(FPU_REG * st0_ptr, u_char st0_tag) { - FPU_REG *st1_ptr = &st(1); - u_char st1_tag = FPU_gettagi(1); - int old_cw = control_word; - u_char sign = getsign(st0_ptr); + FPU_REG *st1_ptr = &st(1); + u_char st1_tag = FPU_gettagi(1); + int old_cw = control_word; + u_char sign = getsign(st0_ptr); - clear_C1(); - if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) ) - { - long scale; - FPU_REG tmp; + clear_C1(); + if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) { + long scale; + FPU_REG tmp; - /* Convert register for internal use. */ - setexponent16(st0_ptr, exponent(st0_ptr)); + /* Convert register for internal use. */ + setexponent16(st0_ptr, exponent(st0_ptr)); - valid_scale: + valid_scale: - if ( exponent(st1_ptr) > 30 ) - { - /* 2^31 is far too large, would require 2^(2^30) or 2^(-2^30) */ + if (exponent(st1_ptr) > 30) { + /* 2^31 is far too large, would require 2^(2^30) or 2^(-2^30) */ - if ( signpositive(st1_ptr) ) - { - EXCEPTION(EX_Overflow); - FPU_copy_to_reg0(&CONST_INF, TAG_Special); - } - else - { - EXCEPTION(EX_Underflow); - FPU_copy_to_reg0(&CONST_Z, TAG_Zero); - } - setsign(st0_ptr, sign); - return; + if (signpositive(st1_ptr)) { + EXCEPTION(EX_Overflow); + FPU_copy_to_reg0(&CONST_INF, TAG_Special); + } else { + EXCEPTION(EX_Underflow); + FPU_copy_to_reg0(&CONST_Z, TAG_Zero); + } + setsign(st0_ptr, sign); + return; + } + + control_word &= ~CW_RC; + control_word |= RC_CHOP; + reg_copy(st1_ptr, &tmp); + FPU_round_to_int(&tmp, st1_tag); /* This can never overflow here */ + control_word = old_cw; + scale = signnegative(st1_ptr) ? -tmp.sigl : tmp.sigl; + scale += exponent16(st0_ptr); + + setexponent16(st0_ptr, scale); + + /* Use FPU_round() to properly detect under/overflow etc */ + FPU_round(st0_ptr, 0, 0, control_word, sign); + + return; } - control_word &= ~CW_RC; - control_word |= RC_CHOP; - reg_copy(st1_ptr, &tmp); - FPU_round_to_int(&tmp, st1_tag); /* This can never overflow here */ - control_word = old_cw; - scale = signnegative(st1_ptr) ? -tmp.sigl : tmp.sigl; - scale += exponent16(st0_ptr); + if (st0_tag == TAG_Special) + st0_tag = FPU_Special(st0_ptr); + if (st1_tag == TAG_Special) + st1_tag = FPU_Special(st1_ptr); - setexponent16(st0_ptr, scale); + if ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) { + switch (st1_tag) { + case TAG_Valid: + /* st(0) must be a denormal */ + if ((st0_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; - /* Use FPU_round() to properly detect under/overflow etc */ - FPU_round(st0_ptr, 0, 0, control_word, sign); + FPU_to_exp16(st0_ptr, st0_ptr); /* Will not be left on stack */ + goto valid_scale; - return; - } + case TAG_Zero: + if (st0_tag == TW_Denormal) + denormal_operand(); + return; - if ( st0_tag == TAG_Special ) - st0_tag = FPU_Special(st0_ptr); - if ( st1_tag == TAG_Special ) - st1_tag = FPU_Special(st1_ptr); + case TW_Denormal: + denormal_operand(); + return; - if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) ) - { - switch ( st1_tag ) - { - case TAG_Valid: - /* st(0) must be a denormal */ - if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; + case TW_Infinity: + if ((st0_tag == TW_Denormal) + && (denormal_operand() < 0)) + return; - FPU_to_exp16(st0_ptr, st0_ptr); /* Will not be left on stack */ - goto valid_scale; + if (signpositive(st1_ptr)) + FPU_copy_to_reg0(&CONST_INF, TAG_Special); + else + FPU_copy_to_reg0(&CONST_Z, TAG_Zero); + setsign(st0_ptr, sign); + return; - case TAG_Zero: - if ( st0_tag == TW_Denormal ) - denormal_operand(); - return; + case TW_NaN: + real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); + return; + } + } else if (st0_tag == TAG_Zero) { + switch (st1_tag) { + case TAG_Valid: + case TAG_Zero: + return; - case TW_Denormal: - denormal_operand(); - return; + case TW_Denormal: + denormal_operand(); + return; - case TW_Infinity: - if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) ) - return; + case TW_Infinity: + if (signpositive(st1_ptr)) + arith_invalid(0); /* Zero scaled by +Infinity */ + return; - if ( signpositive(st1_ptr) ) - FPU_copy_to_reg0(&CONST_INF, TAG_Special); - else - FPU_copy_to_reg0(&CONST_Z, TAG_Zero); - setsign(st0_ptr, sign); - return; + case TW_NaN: + real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); + return; + } + } else if (st0_tag == TW_Infinity) { + switch (st1_tag) { + case TAG_Valid: + case TAG_Zero: + return; - case TW_NaN: - real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); - return; + case TW_Denormal: + denormal_operand(); + return; + + case TW_Infinity: + if (signnegative(st1_ptr)) + arith_invalid(0); /* Infinity scaled by -Infinity */ + return; + + case TW_NaN: + real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); + return; + } + } else if (st0_tag == TW_NaN) { + if (st1_tag != TAG_Empty) { + real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); + return; + } } - } - else if ( st0_tag == TAG_Zero ) - { - switch ( st1_tag ) - { - case TAG_Valid: - case TAG_Zero: - return; - - case TW_Denormal: - denormal_operand(); - return; - - case TW_Infinity: - if ( signpositive(st1_ptr) ) - arith_invalid(0); /* Zero scaled by +Infinity */ - return; - - case TW_NaN: - real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); - return; - } - } - else if ( st0_tag == TW_Infinity ) - { - switch ( st1_tag ) - { - case TAG_Valid: - case TAG_Zero: - return; - - case TW_Denormal: - denormal_operand(); - return; - - case TW_Infinity: - if ( signnegative(st1_ptr) ) - arith_invalid(0); /* Infinity scaled by -Infinity */ - return; - - case TW_NaN: - real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); - return; - } - } - else if ( st0_tag == TW_NaN ) - { - if ( st1_tag != TAG_Empty ) - { real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); return; } - } - #ifdef PARANOID - if ( !((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) ) - { - EXCEPTION(EX_INTERNAL | 0x115); - return; - } + if (!((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty))) { + EXCEPTION(EX_INTERNAL | 0x115); + return; + } #endif - /* At least one of st(0), st(1) must be empty */ - FPU_stack_underflow(); + /* At least one of st(0), st(1) must be empty */ + FPU_stack_underflow(); } - /*---------------------------------------------------------------------------*/ static FUNC_ST0 const trig_table_a[] = { - f2xm1, fyl2x, fptan, fpatan, - fxtract, fprem1, (FUNC_ST0)fdecstp, (FUNC_ST0)fincstp + f2xm1, fyl2x, fptan, fpatan, + fxtract, fprem1, (FUNC_ST0) fdecstp, (FUNC_ST0) fincstp }; void FPU_triga(void) { - (trig_table_a[FPU_rm])(&st(0), FPU_gettag0()); + (trig_table_a[FPU_rm]) (&st(0), FPU_gettag0()); } - -static FUNC_ST0 const trig_table_b[] = - { - fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, (FUNC_ST0)fsin, fcos - }; +static FUNC_ST0 const trig_table_b[] = { + fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, (FUNC_ST0) fsin, fcos +}; void FPU_trigb(void) { - (trig_table_b[FPU_rm])(&st(0), FPU_gettag0()); + (trig_table_b[FPU_rm]) (&st(0), FPU_gettag0()); } diff --git a/arch/x86/math-emu/get_address.c b/arch/x86/math-emu/get_address.c index 2e2c51a8bd3a..d701e2b39e44 100644 --- a/arch/x86/math-emu/get_address.c +++ b/arch/x86/math-emu/get_address.c @@ -17,7 +17,6 @@ | other processes using the emulator while swapping is in progress. | +---------------------------------------------------------------------------*/ - #include #include @@ -27,31 +26,30 @@ #include "exception.h" #include "fpu_emu.h" - #define FPU_WRITE_BIT 0x10 static int reg_offset[] = { - offsetof(struct info,___eax), - offsetof(struct info,___ecx), - offsetof(struct info,___edx), - offsetof(struct info,___ebx), - offsetof(struct info,___esp), - offsetof(struct info,___ebp), - offsetof(struct info,___esi), - offsetof(struct info,___edi) + offsetof(struct info, ___eax), + offsetof(struct info, ___ecx), + offsetof(struct info, ___edx), + offsetof(struct info, ___ebx), + offsetof(struct info, ___esp), + offsetof(struct info, ___ebp), + offsetof(struct info, ___esi), + offsetof(struct info, ___edi) }; #define REG_(x) (*(long *)(reg_offset[(x)]+(u_char *) FPU_info)) static int reg_offset_vm86[] = { - offsetof(struct info,___cs), - offsetof(struct info,___vm86_ds), - offsetof(struct info,___vm86_es), - offsetof(struct info,___vm86_fs), - offsetof(struct info,___vm86_gs), - offsetof(struct info,___ss), - offsetof(struct info,___vm86_ds) - }; + offsetof(struct info, ___cs), + offsetof(struct info, ___vm86_ds), + offsetof(struct info, ___vm86_es), + offsetof(struct info, ___vm86_fs), + offsetof(struct info, ___vm86_gs), + offsetof(struct info, ___ss), + offsetof(struct info, ___vm86_ds) +}; #define VM86_REG_(x) (*(unsigned short *) \ (reg_offset_vm86[((unsigned)x)]+(u_char *) FPU_info)) @@ -60,158 +58,141 @@ static int reg_offset_vm86[] = { #define ___GS ___ds static int reg_offset_pm[] = { - offsetof(struct info,___cs), - offsetof(struct info,___ds), - offsetof(struct info,___es), - offsetof(struct info,___fs), - offsetof(struct info,___GS), - offsetof(struct info,___ss), - offsetof(struct info,___ds) - }; + offsetof(struct info, ___cs), + offsetof(struct info, ___ds), + offsetof(struct info, ___es), + offsetof(struct info, ___fs), + offsetof(struct info, ___GS), + offsetof(struct info, ___ss), + offsetof(struct info, ___ds) +}; #define PM_REG_(x) (*(unsigned short *) \ (reg_offset_pm[((unsigned)x)]+(u_char *) FPU_info)) - /* Decode the SIB byte. This function assumes mod != 0 */ static int sib(int mod, unsigned long *fpu_eip) { - u_char ss,index,base; - long offset; + u_char ss, index, base; + long offset; - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(1); - FPU_get_user(base, (u_char __user *) (*fpu_eip)); /* The SIB byte */ - RE_ENTRANT_CHECK_ON; - (*fpu_eip)++; - ss = base >> 6; - index = (base >> 3) & 7; - base &= 7; + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(1); + FPU_get_user(base, (u_char __user *) (*fpu_eip)); /* The SIB byte */ + RE_ENTRANT_CHECK_ON; + (*fpu_eip)++; + ss = base >> 6; + index = (base >> 3) & 7; + base &= 7; - if ((mod == 0) && (base == 5)) - offset = 0; /* No base register */ - else - offset = REG_(base); + if ((mod == 0) && (base == 5)) + offset = 0; /* No base register */ + else + offset = REG_(base); - if (index == 4) - { - /* No index register */ - /* A non-zero ss is illegal */ - if ( ss ) - EXCEPTION(EX_Invalid); - } - else - { - offset += (REG_(index)) << ss; - } + if (index == 4) { + /* No index register */ + /* A non-zero ss is illegal */ + if (ss) + EXCEPTION(EX_Invalid); + } else { + offset += (REG_(index)) << ss; + } - if (mod == 1) - { - /* 8 bit signed displacement */ - long displacement; - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(1); - FPU_get_user(displacement, (signed char __user *) (*fpu_eip)); - offset += displacement; - RE_ENTRANT_CHECK_ON; - (*fpu_eip)++; - } - else if (mod == 2 || base == 5) /* The second condition also has mod==0 */ - { - /* 32 bit displacement */ - long displacement; - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(4); - FPU_get_user(displacement, (long __user *) (*fpu_eip)); - offset += displacement; - RE_ENTRANT_CHECK_ON; - (*fpu_eip) += 4; - } + if (mod == 1) { + /* 8 bit signed displacement */ + long displacement; + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(1); + FPU_get_user(displacement, (signed char __user *)(*fpu_eip)); + offset += displacement; + RE_ENTRANT_CHECK_ON; + (*fpu_eip)++; + } else if (mod == 2 || base == 5) { /* The second condition also has mod==0 */ + /* 32 bit displacement */ + long displacement; + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(4); + FPU_get_user(displacement, (long __user *)(*fpu_eip)); + offset += displacement; + RE_ENTRANT_CHECK_ON; + (*fpu_eip) += 4; + } - return offset; + return offset; } - -static unsigned long vm86_segment(u_char segment, - struct address *addr) +static unsigned long vm86_segment(u_char segment, struct address *addr) { - segment--; + segment--; #ifdef PARANOID - if ( segment > PREFIX_SS_ ) - { - EXCEPTION(EX_INTERNAL|0x130); - math_abort(FPU_info,SIGSEGV); - } + if (segment > PREFIX_SS_) { + EXCEPTION(EX_INTERNAL | 0x130); + math_abort(FPU_info, SIGSEGV); + } #endif /* PARANOID */ - addr->selector = VM86_REG_(segment); - return (unsigned long)VM86_REG_(segment) << 4; + addr->selector = VM86_REG_(segment); + return (unsigned long)VM86_REG_(segment) << 4; } - /* This should work for 16 and 32 bit protected mode. */ static long pm_address(u_char FPU_modrm, u_char segment, struct address *addr, long offset) -{ - struct desc_struct descriptor; - unsigned long base_address, limit, address, seg_top; +{ + struct desc_struct descriptor; + unsigned long base_address, limit, address, seg_top; - segment--; + segment--; #ifdef PARANOID - /* segment is unsigned, so this also detects if segment was 0: */ - if ( segment > PREFIX_SS_ ) - { - EXCEPTION(EX_INTERNAL|0x132); - math_abort(FPU_info,SIGSEGV); - } + /* segment is unsigned, so this also detects if segment was 0: */ + if (segment > PREFIX_SS_) { + EXCEPTION(EX_INTERNAL | 0x132); + math_abort(FPU_info, SIGSEGV); + } #endif /* PARANOID */ - switch ( segment ) - { - /* gs isn't used by the kernel, so it still has its - user-space value. */ - case PREFIX_GS_-1: - /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */ - savesegment(gs, addr->selector); - break; - default: - addr->selector = PM_REG_(segment); - } - - descriptor = LDT_DESCRIPTOR(PM_REG_(segment)); - base_address = SEG_BASE_ADDR(descriptor); - address = base_address + offset; - limit = base_address - + (SEG_LIMIT(descriptor)+1) * SEG_GRANULARITY(descriptor) - 1; - if ( limit < base_address ) limit = 0xffffffff; - - if ( SEG_EXPAND_DOWN(descriptor) ) - { - if ( SEG_G_BIT(descriptor) ) - seg_top = 0xffffffff; - else - { - seg_top = base_address + (1 << 20); - if ( seg_top < base_address ) seg_top = 0xffffffff; + switch (segment) { + /* gs isn't used by the kernel, so it still has its + user-space value. */ + case PREFIX_GS_ - 1: + /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */ + savesegment(gs, addr->selector); + break; + default: + addr->selector = PM_REG_(segment); } - access_limit = - (address <= limit) || (address >= seg_top) ? 0 : - ((seg_top-address) >= 255 ? 255 : seg_top-address); - } - else - { - access_limit = - (address > limit) || (address < base_address) ? 0 : - ((limit-address) >= 254 ? 255 : limit-address+1); - } - if ( SEG_EXECUTE_ONLY(descriptor) || - (!SEG_WRITE_PERM(descriptor) && (FPU_modrm & FPU_WRITE_BIT)) ) - { - access_limit = 0; - } - return address; -} + descriptor = LDT_DESCRIPTOR(PM_REG_(segment)); + base_address = SEG_BASE_ADDR(descriptor); + address = base_address + offset; + limit = base_address + + (SEG_LIMIT(descriptor) + 1) * SEG_GRANULARITY(descriptor) - 1; + if (limit < base_address) + limit = 0xffffffff; + + if (SEG_EXPAND_DOWN(descriptor)) { + if (SEG_G_BIT(descriptor)) + seg_top = 0xffffffff; + else { + seg_top = base_address + (1 << 20); + if (seg_top < base_address) + seg_top = 0xffffffff; + } + access_limit = + (address <= limit) || (address >= seg_top) ? 0 : + ((seg_top - address) >= 255 ? 255 : seg_top - address); + } else { + access_limit = + (address > limit) || (address < base_address) ? 0 : + ((limit - address) >= 254 ? 255 : limit - address + 1); + } + if (SEG_EXECUTE_ONLY(descriptor) || + (!SEG_WRITE_PERM(descriptor) && (FPU_modrm & FPU_WRITE_BIT))) { + access_limit = 0; + } + return address; +} /* MOD R/M byte: MOD == 3 has a special use for the FPU @@ -221,7 +202,6 @@ static long pm_address(u_char FPU_modrm, u_char segment, ..... ......... ......... MOD OPCODE(2) R/M - SIB byte 7 6 5 4 3 2 1 0 @@ -231,208 +211,194 @@ static long pm_address(u_char FPU_modrm, u_char segment, */ void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip, - struct address *addr, - fpu_addr_modes addr_modes) + struct address *addr, fpu_addr_modes addr_modes) { - u_char mod; - unsigned rm = FPU_modrm & 7; - long *cpu_reg_ptr; - int address = 0; /* Initialized just to stop compiler warnings. */ + u_char mod; + unsigned rm = FPU_modrm & 7; + long *cpu_reg_ptr; + int address = 0; /* Initialized just to stop compiler warnings. */ - /* Memory accessed via the cs selector is write protected - in `non-segmented' 32 bit protected mode. */ - if ( !addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT) - && (addr_modes.override.segment == PREFIX_CS_) ) - { - math_abort(FPU_info,SIGSEGV); - } - - addr->selector = FPU_DS; /* Default, for 32 bit non-segmented mode. */ - - mod = (FPU_modrm >> 6) & 3; - - if (rm == 4 && mod != 3) - { - address = sib(mod, fpu_eip); - } - else - { - cpu_reg_ptr = & REG_(rm); - switch (mod) - { - case 0: - if (rm == 5) - { - /* Special case: disp32 */ - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(4); - FPU_get_user(address, (unsigned long __user *) (*fpu_eip)); - (*fpu_eip) += 4; - RE_ENTRANT_CHECK_ON; - addr->offset = address; - return (void __user *) address; - } - else - { - address = *cpu_reg_ptr; /* Just return the contents - of the cpu register */ - addr->offset = address; - return (void __user *) address; - } - case 1: - /* 8 bit signed displacement */ - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(1); - FPU_get_user(address, (signed char __user *) (*fpu_eip)); - RE_ENTRANT_CHECK_ON; - (*fpu_eip)++; - break; - case 2: - /* 32 bit displacement */ - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(4); - FPU_get_user(address, (long __user *) (*fpu_eip)); - (*fpu_eip) += 4; - RE_ENTRANT_CHECK_ON; - break; - case 3: - /* Not legal for the FPU */ - EXCEPTION(EX_Invalid); + /* Memory accessed via the cs selector is write protected + in `non-segmented' 32 bit protected mode. */ + if (!addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT) + && (addr_modes.override.segment == PREFIX_CS_)) { + math_abort(FPU_info, SIGSEGV); } - address += *cpu_reg_ptr; - } - addr->offset = address; + addr->selector = FPU_DS; /* Default, for 32 bit non-segmented mode. */ - switch ( addr_modes.default_mode ) - { - case 0: - break; - case VM86: - address += vm86_segment(addr_modes.override.segment, addr); - break; - case PM16: - case SEG32: - address = pm_address(FPU_modrm, addr_modes.override.segment, - addr, address); - break; - default: - EXCEPTION(EX_INTERNAL|0x133); - } + mod = (FPU_modrm >> 6) & 3; - return (void __user *)address; + if (rm == 4 && mod != 3) { + address = sib(mod, fpu_eip); + } else { + cpu_reg_ptr = ®_(rm); + switch (mod) { + case 0: + if (rm == 5) { + /* Special case: disp32 */ + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(4); + FPU_get_user(address, + (unsigned long __user + *)(*fpu_eip)); + (*fpu_eip) += 4; + RE_ENTRANT_CHECK_ON; + addr->offset = address; + return (void __user *)address; + } else { + address = *cpu_reg_ptr; /* Just return the contents + of the cpu register */ + addr->offset = address; + return (void __user *)address; + } + case 1: + /* 8 bit signed displacement */ + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(1); + FPU_get_user(address, (signed char __user *)(*fpu_eip)); + RE_ENTRANT_CHECK_ON; + (*fpu_eip)++; + break; + case 2: + /* 32 bit displacement */ + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(4); + FPU_get_user(address, (long __user *)(*fpu_eip)); + (*fpu_eip) += 4; + RE_ENTRANT_CHECK_ON; + break; + case 3: + /* Not legal for the FPU */ + EXCEPTION(EX_Invalid); + } + address += *cpu_reg_ptr; + } + + addr->offset = address; + + switch (addr_modes.default_mode) { + case 0: + break; + case VM86: + address += vm86_segment(addr_modes.override.segment, addr); + break; + case PM16: + case SEG32: + address = pm_address(FPU_modrm, addr_modes.override.segment, + addr, address); + break; + default: + EXCEPTION(EX_INTERNAL | 0x133); + } + + return (void __user *)address; } - void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip, - struct address *addr, - fpu_addr_modes addr_modes) + struct address *addr, fpu_addr_modes addr_modes) { - u_char mod; - unsigned rm = FPU_modrm & 7; - int address = 0; /* Default used for mod == 0 */ + u_char mod; + unsigned rm = FPU_modrm & 7; + int address = 0; /* Default used for mod == 0 */ - /* Memory accessed via the cs selector is write protected - in `non-segmented' 32 bit protected mode. */ - if ( !addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT) - && (addr_modes.override.segment == PREFIX_CS_) ) - { - math_abort(FPU_info,SIGSEGV); - } - - addr->selector = FPU_DS; /* Default, for 32 bit non-segmented mode. */ - - mod = (FPU_modrm >> 6) & 3; - - switch (mod) - { - case 0: - if (rm == 6) - { - /* Special case: disp16 */ - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(2); - FPU_get_user(address, (unsigned short __user *) (*fpu_eip)); - (*fpu_eip) += 2; - RE_ENTRANT_CHECK_ON; - goto add_segment; + /* Memory accessed via the cs selector is write protected + in `non-segmented' 32 bit protected mode. */ + if (!addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT) + && (addr_modes.override.segment == PREFIX_CS_)) { + math_abort(FPU_info, SIGSEGV); } - break; - case 1: - /* 8 bit signed displacement */ - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(1); - FPU_get_user(address, (signed char __user *) (*fpu_eip)); - RE_ENTRANT_CHECK_ON; - (*fpu_eip)++; - break; - case 2: - /* 16 bit displacement */ - RE_ENTRANT_CHECK_OFF; - FPU_code_access_ok(2); - FPU_get_user(address, (unsigned short __user *) (*fpu_eip)); - (*fpu_eip) += 2; - RE_ENTRANT_CHECK_ON; - break; - case 3: - /* Not legal for the FPU */ - EXCEPTION(EX_Invalid); - break; - } - switch ( rm ) - { - case 0: - address += FPU_info->___ebx + FPU_info->___esi; - break; - case 1: - address += FPU_info->___ebx + FPU_info->___edi; - break; - case 2: - address += FPU_info->___ebp + FPU_info->___esi; - if ( addr_modes.override.segment == PREFIX_DEFAULT ) - addr_modes.override.segment = PREFIX_SS_; - break; - case 3: - address += FPU_info->___ebp + FPU_info->___edi; - if ( addr_modes.override.segment == PREFIX_DEFAULT ) - addr_modes.override.segment = PREFIX_SS_; - break; - case 4: - address += FPU_info->___esi; - break; - case 5: - address += FPU_info->___edi; - break; - case 6: - address += FPU_info->___ebp; - if ( addr_modes.override.segment == PREFIX_DEFAULT ) - addr_modes.override.segment = PREFIX_SS_; - break; - case 7: - address += FPU_info->___ebx; - break; - } - add_segment: - address &= 0xffff; + addr->selector = FPU_DS; /* Default, for 32 bit non-segmented mode. */ - addr->offset = address; + mod = (FPU_modrm >> 6) & 3; - switch ( addr_modes.default_mode ) - { - case 0: - break; - case VM86: - address += vm86_segment(addr_modes.override.segment, addr); - break; - case PM16: - case SEG32: - address = pm_address(FPU_modrm, addr_modes.override.segment, - addr, address); - break; - default: - EXCEPTION(EX_INTERNAL|0x131); - } + switch (mod) { + case 0: + if (rm == 6) { + /* Special case: disp16 */ + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(2); + FPU_get_user(address, + (unsigned short __user *)(*fpu_eip)); + (*fpu_eip) += 2; + RE_ENTRANT_CHECK_ON; + goto add_segment; + } + break; + case 1: + /* 8 bit signed displacement */ + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(1); + FPU_get_user(address, (signed char __user *)(*fpu_eip)); + RE_ENTRANT_CHECK_ON; + (*fpu_eip)++; + break; + case 2: + /* 16 bit displacement */ + RE_ENTRANT_CHECK_OFF; + FPU_code_access_ok(2); + FPU_get_user(address, (unsigned short __user *)(*fpu_eip)); + (*fpu_eip) += 2; + RE_ENTRANT_CHECK_ON; + break; + case 3: + /* Not legal for the FPU */ + EXCEPTION(EX_Invalid); + break; + } + switch (rm) { + case 0: + address += FPU_info->___ebx + FPU_info->___esi; + break; + case 1: + address += FPU_info->___ebx + FPU_info->___edi; + break; + case 2: + address += FPU_info->___ebp + FPU_info->___esi; + if (addr_modes.override.segment == PREFIX_DEFAULT) + addr_modes.override.segment = PREFIX_SS_; + break; + case 3: + address += FPU_info->___ebp + FPU_info->___edi; + if (addr_modes.override.segment == PREFIX_DEFAULT) + addr_modes.override.segment = PREFIX_SS_; + break; + case 4: + address += FPU_info->___esi; + break; + case 5: + address += FPU_info->___edi; + break; + case 6: + address += FPU_info->___ebp; + if (addr_modes.override.segment == PREFIX_DEFAULT) + addr_modes.override.segment = PREFIX_SS_; + break; + case 7: + address += FPU_info->___ebx; + break; + } - return (void __user *)address ; + add_segment: + address &= 0xffff; + + addr->offset = address; + + switch (addr_modes.default_mode) { + case 0: + break; + case VM86: + address += vm86_segment(addr_modes.override.segment, addr); + break; + case PM16: + case SEG32: + address = pm_address(FPU_modrm, addr_modes.override.segment, + addr, address); + break; + default: + EXCEPTION(EX_INTERNAL | 0x131); + } + + return (void __user *)address; } diff --git a/arch/x86/math-emu/load_store.c b/arch/x86/math-emu/load_store.c index eebd6fb1c8a8..2931ff355218 100644 --- a/arch/x86/math-emu/load_store.c +++ b/arch/x86/math-emu/load_store.c @@ -26,247 +26,257 @@ #include "status_w.h" #include "control_w.h" - -#define _NONE_ 0 /* st0_ptr etc not needed */ -#define _REG0_ 1 /* Will be storing st(0) */ -#define _PUSH_ 3 /* Need to check for space to push onto stack */ -#define _null_ 4 /* Function illegal or not implemented */ +#define _NONE_ 0 /* st0_ptr etc not needed */ +#define _REG0_ 1 /* Will be storing st(0) */ +#define _PUSH_ 3 /* Need to check for space to push onto stack */ +#define _null_ 4 /* Function illegal or not implemented */ #define pop_0() { FPU_settag0(TAG_Empty); top++; } - static u_char const type_table[32] = { - _PUSH_, _PUSH_, _PUSH_, _PUSH_, - _null_, _null_, _null_, _null_, - _REG0_, _REG0_, _REG0_, _REG0_, - _REG0_, _REG0_, _REG0_, _REG0_, - _NONE_, _null_, _NONE_, _PUSH_, - _NONE_, _PUSH_, _null_, _PUSH_, - _NONE_, _null_, _NONE_, _REG0_, - _NONE_, _REG0_, _NONE_, _REG0_ - }; + _PUSH_, _PUSH_, _PUSH_, _PUSH_, + _null_, _null_, _null_, _null_, + _REG0_, _REG0_, _REG0_, _REG0_, + _REG0_, _REG0_, _REG0_, _REG0_, + _NONE_, _null_, _NONE_, _PUSH_, + _NONE_, _PUSH_, _null_, _PUSH_, + _NONE_, _null_, _NONE_, _REG0_, + _NONE_, _REG0_, _NONE_, _REG0_ +}; u_char const data_sizes_16[32] = { - 4, 4, 8, 2, 0, 0, 0, 0, - 4, 4, 8, 2, 4, 4, 8, 2, - 14, 0, 94, 10, 2, 10, 0, 8, - 14, 0, 94, 10, 2, 10, 2, 8 + 4, 4, 8, 2, 0, 0, 0, 0, + 4, 4, 8, 2, 4, 4, 8, 2, + 14, 0, 94, 10, 2, 10, 0, 8, + 14, 0, 94, 10, 2, 10, 2, 8 }; static u_char const data_sizes_32[32] = { - 4, 4, 8, 2, 0, 0, 0, 0, - 4, 4, 8, 2, 4, 4, 8, 2, - 28, 0,108, 10, 2, 10, 0, 8, - 28, 0,108, 10, 2, 10, 2, 8 + 4, 4, 8, 2, 0, 0, 0, 0, + 4, 4, 8, 2, 4, 4, 8, 2, + 28, 0, 108, 10, 2, 10, 0, 8, + 28, 0, 108, 10, 2, 10, 2, 8 }; int FPU_load_store(u_char type, fpu_addr_modes addr_modes, - void __user *data_address) + void __user * data_address) { - FPU_REG loaded_data; - FPU_REG *st0_ptr; - u_char st0_tag = TAG_Empty; /* This is just to stop a gcc warning. */ - u_char loaded_tag; + FPU_REG loaded_data; + FPU_REG *st0_ptr; + u_char st0_tag = TAG_Empty; /* This is just to stop a gcc warning. */ + u_char loaded_tag; - st0_ptr = NULL; /* Initialized just to stop compiler warnings. */ + st0_ptr = NULL; /* Initialized just to stop compiler warnings. */ - if ( addr_modes.default_mode & PROTECTED ) - { - if ( addr_modes.default_mode == SEG32 ) - { - if ( access_limit < data_sizes_32[type] ) - math_abort(FPU_info,SIGSEGV); - } - else if ( addr_modes.default_mode == PM16 ) - { - if ( access_limit < data_sizes_16[type] ) - math_abort(FPU_info,SIGSEGV); - } + if (addr_modes.default_mode & PROTECTED) { + if (addr_modes.default_mode == SEG32) { + if (access_limit < data_sizes_32[type]) + math_abort(FPU_info, SIGSEGV); + } else if (addr_modes.default_mode == PM16) { + if (access_limit < data_sizes_16[type]) + math_abort(FPU_info, SIGSEGV); + } #ifdef PARANOID - else - EXCEPTION(EX_INTERNAL|0x140); + else + EXCEPTION(EX_INTERNAL | 0x140); #endif /* PARANOID */ - } + } - switch ( type_table[type] ) - { - case _NONE_: - break; - case _REG0_: - st0_ptr = &st(0); /* Some of these instructions pop after - storing */ - st0_tag = FPU_gettag0(); - break; - case _PUSH_: - { - if ( FPU_gettagi(-1) != TAG_Empty ) - { FPU_stack_overflow(); return 0; } - top--; - st0_ptr = &st(0); - } - break; - case _null_: - FPU_illegal(); - return 0; + switch (type_table[type]) { + case _NONE_: + break; + case _REG0_: + st0_ptr = &st(0); /* Some of these instructions pop after + storing */ + st0_tag = FPU_gettag0(); + break; + case _PUSH_: + { + if (FPU_gettagi(-1) != TAG_Empty) { + FPU_stack_overflow(); + return 0; + } + top--; + st0_ptr = &st(0); + } + break; + case _null_: + FPU_illegal(); + return 0; #ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL|0x141); - return 0; + default: + EXCEPTION(EX_INTERNAL | 0x141); + return 0; #endif /* PARANOID */ - } + } - switch ( type ) - { - case 000: /* fld m32real */ - clear_C1(); - loaded_tag = FPU_load_single((float __user *)data_address, &loaded_data); - if ( (loaded_tag == TAG_Special) - && isNaN(&loaded_data) - && (real_1op_NaN(&loaded_data) < 0) ) - { - top++; - break; - } - FPU_copy_to_reg0(&loaded_data, loaded_tag); - break; - case 001: /* fild m32int */ - clear_C1(); - loaded_tag = FPU_load_int32((long __user *)data_address, &loaded_data); - FPU_copy_to_reg0(&loaded_data, loaded_tag); - break; - case 002: /* fld m64real */ - clear_C1(); - loaded_tag = FPU_load_double((double __user *)data_address, &loaded_data); - if ( (loaded_tag == TAG_Special) - && isNaN(&loaded_data) - && (real_1op_NaN(&loaded_data) < 0) ) - { - top++; - break; - } - FPU_copy_to_reg0(&loaded_data, loaded_tag); - break; - case 003: /* fild m16int */ - clear_C1(); - loaded_tag = FPU_load_int16((short __user *)data_address, &loaded_data); - FPU_copy_to_reg0(&loaded_data, loaded_tag); - break; - case 010: /* fst m32real */ - clear_C1(); - FPU_store_single(st0_ptr, st0_tag, (float __user *)data_address); - break; - case 011: /* fist m32int */ - clear_C1(); - FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address); - break; - case 012: /* fst m64real */ - clear_C1(); - FPU_store_double(st0_ptr, st0_tag, (double __user *)data_address); - break; - case 013: /* fist m16int */ - clear_C1(); - FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address); - break; - case 014: /* fstp m32real */ - clear_C1(); - if ( FPU_store_single(st0_ptr, st0_tag, (float __user *)data_address) ) - pop_0(); /* pop only if the number was actually stored - (see the 80486 manual p16-28) */ - break; - case 015: /* fistp m32int */ - clear_C1(); - if ( FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address) ) - pop_0(); /* pop only if the number was actually stored - (see the 80486 manual p16-28) */ - break; - case 016: /* fstp m64real */ - clear_C1(); - if ( FPU_store_double(st0_ptr, st0_tag, (double __user *)data_address) ) - pop_0(); /* pop only if the number was actually stored - (see the 80486 manual p16-28) */ - break; - case 017: /* fistp m16int */ - clear_C1(); - if ( FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address) ) - pop_0(); /* pop only if the number was actually stored - (see the 80486 manual p16-28) */ - break; - case 020: /* fldenv m14/28byte */ - fldenv(addr_modes, (u_char __user *)data_address); - /* Ensure that the values just loaded are not changed by - fix-up operations. */ - return 1; - case 022: /* frstor m94/108byte */ - frstor(addr_modes, (u_char __user *)data_address); - /* Ensure that the values just loaded are not changed by - fix-up operations. */ - return 1; - case 023: /* fbld m80dec */ - clear_C1(); - loaded_tag = FPU_load_bcd((u_char __user *)data_address); - FPU_settag0(loaded_tag); - break; - case 024: /* fldcw */ - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ, data_address, 2); - FPU_get_user(control_word, (unsigned short __user *) data_address); - RE_ENTRANT_CHECK_ON; - if ( partial_status & ~control_word & CW_Exceptions ) - partial_status |= (SW_Summary | SW_Backward); - else - partial_status &= ~(SW_Summary | SW_Backward); + switch (type) { + case 000: /* fld m32real */ + clear_C1(); + loaded_tag = + FPU_load_single((float __user *)data_address, &loaded_data); + if ((loaded_tag == TAG_Special) + && isNaN(&loaded_data) + && (real_1op_NaN(&loaded_data) < 0)) { + top++; + break; + } + FPU_copy_to_reg0(&loaded_data, loaded_tag); + break; + case 001: /* fild m32int */ + clear_C1(); + loaded_tag = + FPU_load_int32((long __user *)data_address, &loaded_data); + FPU_copy_to_reg0(&loaded_data, loaded_tag); + break; + case 002: /* fld m64real */ + clear_C1(); + loaded_tag = + FPU_load_double((double __user *)data_address, + &loaded_data); + if ((loaded_tag == TAG_Special) + && isNaN(&loaded_data) + && (real_1op_NaN(&loaded_data) < 0)) { + top++; + break; + } + FPU_copy_to_reg0(&loaded_data, loaded_tag); + break; + case 003: /* fild m16int */ + clear_C1(); + loaded_tag = + FPU_load_int16((short __user *)data_address, &loaded_data); + FPU_copy_to_reg0(&loaded_data, loaded_tag); + break; + case 010: /* fst m32real */ + clear_C1(); + FPU_store_single(st0_ptr, st0_tag, + (float __user *)data_address); + break; + case 011: /* fist m32int */ + clear_C1(); + FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address); + break; + case 012: /* fst m64real */ + clear_C1(); + FPU_store_double(st0_ptr, st0_tag, + (double __user *)data_address); + break; + case 013: /* fist m16int */ + clear_C1(); + FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address); + break; + case 014: /* fstp m32real */ + clear_C1(); + if (FPU_store_single + (st0_ptr, st0_tag, (float __user *)data_address)) + pop_0(); /* pop only if the number was actually stored + (see the 80486 manual p16-28) */ + break; + case 015: /* fistp m32int */ + clear_C1(); + if (FPU_store_int32 + (st0_ptr, st0_tag, (long __user *)data_address)) + pop_0(); /* pop only if the number was actually stored + (see the 80486 manual p16-28) */ + break; + case 016: /* fstp m64real */ + clear_C1(); + if (FPU_store_double + (st0_ptr, st0_tag, (double __user *)data_address)) + pop_0(); /* pop only if the number was actually stored + (see the 80486 manual p16-28) */ + break; + case 017: /* fistp m16int */ + clear_C1(); + if (FPU_store_int16 + (st0_ptr, st0_tag, (short __user *)data_address)) + pop_0(); /* pop only if the number was actually stored + (see the 80486 manual p16-28) */ + break; + case 020: /* fldenv m14/28byte */ + fldenv(addr_modes, (u_char __user *) data_address); + /* Ensure that the values just loaded are not changed by + fix-up operations. */ + return 1; + case 022: /* frstor m94/108byte */ + frstor(addr_modes, (u_char __user *) data_address); + /* Ensure that the values just loaded are not changed by + fix-up operations. */ + return 1; + case 023: /* fbld m80dec */ + clear_C1(); + loaded_tag = FPU_load_bcd((u_char __user *) data_address); + FPU_settag0(loaded_tag); + break; + case 024: /* fldcw */ + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, data_address, 2); + FPU_get_user(control_word, + (unsigned short __user *)data_address); + RE_ENTRANT_CHECK_ON; + if (partial_status & ~control_word & CW_Exceptions) + partial_status |= (SW_Summary | SW_Backward); + else + partial_status &= ~(SW_Summary | SW_Backward); #ifdef PECULIAR_486 - control_word |= 0x40; /* An 80486 appears to always set this bit */ + control_word |= 0x40; /* An 80486 appears to always set this bit */ #endif /* PECULIAR_486 */ - return 1; - case 025: /* fld m80real */ - clear_C1(); - loaded_tag = FPU_load_extended((long double __user *)data_address, 0); - FPU_settag0(loaded_tag); - break; - case 027: /* fild m64int */ - clear_C1(); - loaded_tag = FPU_load_int64((long long __user *)data_address); - if (loaded_tag == TAG_Error) + return 1; + case 025: /* fld m80real */ + clear_C1(); + loaded_tag = + FPU_load_extended((long double __user *)data_address, 0); + FPU_settag0(loaded_tag); + break; + case 027: /* fild m64int */ + clear_C1(); + loaded_tag = FPU_load_int64((long long __user *)data_address); + if (loaded_tag == TAG_Error) + return 0; + FPU_settag0(loaded_tag); + break; + case 030: /* fstenv m14/28byte */ + fstenv(addr_modes, (u_char __user *) data_address); + return 1; + case 032: /* fsave */ + fsave(addr_modes, (u_char __user *) data_address); + return 1; + case 033: /* fbstp m80dec */ + clear_C1(); + if (FPU_store_bcd + (st0_ptr, st0_tag, (u_char __user *) data_address)) + pop_0(); /* pop only if the number was actually stored + (see the 80486 manual p16-28) */ + break; + case 034: /* fstcw m16int */ + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, data_address, 2); + FPU_put_user(control_word, + (unsigned short __user *)data_address); + RE_ENTRANT_CHECK_ON; + return 1; + case 035: /* fstp m80real */ + clear_C1(); + if (FPU_store_extended + (st0_ptr, st0_tag, (long double __user *)data_address)) + pop_0(); /* pop only if the number was actually stored + (see the 80486 manual p16-28) */ + break; + case 036: /* fstsw m2byte */ + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, data_address, 2); + FPU_put_user(status_word(), + (unsigned short __user *)data_address); + RE_ENTRANT_CHECK_ON; + return 1; + case 037: /* fistp m64int */ + clear_C1(); + if (FPU_store_int64 + (st0_ptr, st0_tag, (long long __user *)data_address)) + pop_0(); /* pop only if the number was actually stored + (see the 80486 manual p16-28) */ + break; + } return 0; - FPU_settag0(loaded_tag); - break; - case 030: /* fstenv m14/28byte */ - fstenv(addr_modes, (u_char __user *)data_address); - return 1; - case 032: /* fsave */ - fsave(addr_modes, (u_char __user *)data_address); - return 1; - case 033: /* fbstp m80dec */ - clear_C1(); - if ( FPU_store_bcd(st0_ptr, st0_tag, (u_char __user *)data_address) ) - pop_0(); /* pop only if the number was actually stored - (see the 80486 manual p16-28) */ - break; - case 034: /* fstcw m16int */ - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,data_address,2); - FPU_put_user(control_word, (unsigned short __user *) data_address); - RE_ENTRANT_CHECK_ON; - return 1; - case 035: /* fstp m80real */ - clear_C1(); - if ( FPU_store_extended(st0_ptr, st0_tag, (long double __user *)data_address) ) - pop_0(); /* pop only if the number was actually stored - (see the 80486 manual p16-28) */ - break; - case 036: /* fstsw m2byte */ - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,data_address,2); - FPU_put_user(status_word(),(unsigned short __user *) data_address); - RE_ENTRANT_CHECK_ON; - return 1; - case 037: /* fistp m64int */ - clear_C1(); - if ( FPU_store_int64(st0_ptr, st0_tag, (long long __user *)data_address) ) - pop_0(); /* pop only if the number was actually stored - (see the 80486 manual p16-28) */ - break; - } - return 0; } diff --git a/arch/x86/math-emu/poly.h b/arch/x86/math-emu/poly.h index 4db798114923..f317de7d8864 100644 --- a/arch/x86/math-emu/poly.h +++ b/arch/x86/math-emu/poly.h @@ -21,9 +21,9 @@ allows. 9-byte would probably be sufficient. */ typedef struct { - unsigned long lsw; - unsigned long midw; - unsigned long msw; + unsigned long lsw; + unsigned long midw; + unsigned long msw; } Xsig; asmlinkage void mul64(unsigned long long const *a, unsigned long long const *b, @@ -33,12 +33,12 @@ asmlinkage void polynomial_Xsig(Xsig *, const unsigned long long *x, asmlinkage void mul32_Xsig(Xsig *, const unsigned long mult); asmlinkage void mul64_Xsig(Xsig *, const unsigned long long *mult); -asmlinkage void mul_Xsig_Xsig(Xsig *dest, const Xsig *mult); +asmlinkage void mul_Xsig_Xsig(Xsig * dest, const Xsig * mult); asmlinkage void shr_Xsig(Xsig *, const int n); asmlinkage int round_Xsig(Xsig *); asmlinkage int norm_Xsig(Xsig *); -asmlinkage void div_Xsig(Xsig *x1, const Xsig *x2, const Xsig *dest); +asmlinkage void div_Xsig(Xsig * x1, const Xsig * x2, const Xsig * dest); /* Macro to extract the most significant 32 bits from a long long */ #define LL_MSW(x) (((unsigned long *)&x)[1]) @@ -49,7 +49,6 @@ asmlinkage void div_Xsig(Xsig *x1, const Xsig *x2, const Xsig *dest); /* Macro to access the 8 ms bytes of an Xsig as a long long */ #define XSIG_LL(x) (*(unsigned long long *)&x.midw) - /* Need to run gcc with optimizations on to get these to actually be in-line. @@ -63,59 +62,53 @@ asmlinkage void div_Xsig(Xsig *x1, const Xsig *x2, const Xsig *dest); static inline unsigned long mul_32_32(const unsigned long arg1, const unsigned long arg2) { - int retval; - asm volatile ("mull %2; movl %%edx,%%eax" \ - :"=a" (retval) \ - :"0" (arg1), "g" (arg2) \ - :"dx"); - return retval; + int retval; + asm volatile ("mull %2; movl %%edx,%%eax":"=a" (retval) + :"0"(arg1), "g"(arg2) + :"dx"); + return retval; } - /* Add the 12 byte Xsig x2 to Xsig dest, with no checks for overflow. */ -static inline void add_Xsig_Xsig(Xsig *dest, const Xsig *x2) +static inline void add_Xsig_Xsig(Xsig * dest, const Xsig * x2) { - asm volatile ("movl %1,%%edi; movl %2,%%esi;\n" - "movl (%%esi),%%eax; addl %%eax,(%%edi);\n" - "movl 4(%%esi),%%eax; adcl %%eax,4(%%edi);\n" - "movl 8(%%esi),%%eax; adcl %%eax,8(%%edi);\n" - :"=g" (*dest):"g" (dest), "g" (x2) - :"ax","si","di"); + asm volatile ("movl %1,%%edi; movl %2,%%esi;\n" + "movl (%%esi),%%eax; addl %%eax,(%%edi);\n" + "movl 4(%%esi),%%eax; adcl %%eax,4(%%edi);\n" + "movl 8(%%esi),%%eax; adcl %%eax,8(%%edi);\n":"=g" + (*dest):"g"(dest), "g"(x2) + :"ax", "si", "di"); } - /* Add the 12 byte Xsig x2 to Xsig dest, adjust exp if overflow occurs. */ /* Note: the constraints in the asm statement didn't always work properly with gcc 2.5.8. Changing from using edi to using ecx got around the problem, but keep fingers crossed! */ -static inline void add_two_Xsig(Xsig *dest, const Xsig *x2, long int *exp) +static inline void add_two_Xsig(Xsig * dest, const Xsig * x2, long int *exp) { - asm volatile ("movl %2,%%ecx; movl %3,%%esi;\n" - "movl (%%esi),%%eax; addl %%eax,(%%ecx);\n" - "movl 4(%%esi),%%eax; adcl %%eax,4(%%ecx);\n" - "movl 8(%%esi),%%eax; adcl %%eax,8(%%ecx);\n" - "jnc 0f;\n" - "rcrl 8(%%ecx); rcrl 4(%%ecx); rcrl (%%ecx)\n" - "movl %4,%%ecx; incl (%%ecx)\n" - "movl $1,%%eax; jmp 1f;\n" - "0: xorl %%eax,%%eax;\n" - "1:\n" - :"=g" (*exp), "=g" (*dest) - :"g" (dest), "g" (x2), "g" (exp) - :"cx","si","ax"); + asm volatile ("movl %2,%%ecx; movl %3,%%esi;\n" + "movl (%%esi),%%eax; addl %%eax,(%%ecx);\n" + "movl 4(%%esi),%%eax; adcl %%eax,4(%%ecx);\n" + "movl 8(%%esi),%%eax; adcl %%eax,8(%%ecx);\n" + "jnc 0f;\n" + "rcrl 8(%%ecx); rcrl 4(%%ecx); rcrl (%%ecx)\n" + "movl %4,%%ecx; incl (%%ecx)\n" + "movl $1,%%eax; jmp 1f;\n" + "0: xorl %%eax,%%eax;\n" "1:\n":"=g" (*exp), "=g"(*dest) + :"g"(dest), "g"(x2), "g"(exp) + :"cx", "si", "ax"); } - /* Negate (subtract from 1.0) the 12 byte Xsig */ /* This is faster in a loop on my 386 than using the "neg" instruction. */ -static inline void negate_Xsig(Xsig *x) +static inline void negate_Xsig(Xsig * x) { - asm volatile("movl %1,%%esi;\n" - "xorl %%ecx,%%ecx;\n" - "movl %%ecx,%%eax; subl (%%esi),%%eax; movl %%eax,(%%esi);\n" - "movl %%ecx,%%eax; sbbl 4(%%esi),%%eax; movl %%eax,4(%%esi);\n" - "movl %%ecx,%%eax; sbbl 8(%%esi),%%eax; movl %%eax,8(%%esi);\n" - :"=g" (*x):"g" (x):"si","ax","cx"); + asm volatile ("movl %1,%%esi;\n" + "xorl %%ecx,%%ecx;\n" + "movl %%ecx,%%eax; subl (%%esi),%%eax; movl %%eax,(%%esi);\n" + "movl %%ecx,%%eax; sbbl 4(%%esi),%%eax; movl %%eax,4(%%esi);\n" + "movl %%ecx,%%eax; sbbl 8(%%esi),%%eax; movl %%eax,8(%%esi);\n":"=g" + (*x):"g"(x):"si", "ax", "cx"); } #endif /* _POLY_H */ diff --git a/arch/x86/math-emu/poly_2xm1.c b/arch/x86/math-emu/poly_2xm1.c index 9766ad5e9743..d8f2be3c8383 100644 --- a/arch/x86/math-emu/poly_2xm1.c +++ b/arch/x86/math-emu/poly_2xm1.c @@ -17,21 +17,19 @@ #include "control_w.h" #include "poly.h" - #define HIPOWER 11 -static const unsigned long long lterms[HIPOWER] = -{ - 0x0000000000000000LL, /* This term done separately as 12 bytes */ - 0xf5fdeffc162c7543LL, - 0x1c6b08d704a0bfa6LL, - 0x0276556df749cc21LL, - 0x002bb0ffcf14f6b8LL, - 0x0002861225ef751cLL, - 0x00001ffcbfcd5422LL, - 0x00000162c005d5f1LL, - 0x0000000da96ccb1bLL, - 0x0000000078d1b897LL, - 0x000000000422b029LL +static const unsigned long long lterms[HIPOWER] = { + 0x0000000000000000LL, /* This term done separately as 12 bytes */ + 0xf5fdeffc162c7543LL, + 0x1c6b08d704a0bfa6LL, + 0x0276556df749cc21LL, + 0x002bb0ffcf14f6b8LL, + 0x0002861225ef751cLL, + 0x00001ffcbfcd5422LL, + 0x00000162c005d5f1LL, + 0x0000000da96ccb1bLL, + 0x0000000078d1b897LL, + 0x000000000422b029LL }; static const Xsig hiterm = MK_XSIG(0xb17217f7, 0xd1cf79ab, 0xc8a39194); @@ -45,112 +43,103 @@ static const Xsig shiftterm2 = MK_XSIG(0xb504f333, 0xf9de6484, 0x597d89b3); static const Xsig shiftterm3 = MK_XSIG(0xd744fcca, 0xd69d6af4, 0x39a68bb9); static const Xsig *shiftterm[] = { &shiftterm0, &shiftterm1, - &shiftterm2, &shiftterm3 }; - + &shiftterm2, &shiftterm3 +}; /*--- poly_2xm1() -----------------------------------------------------------+ | Requires st(0) which is TAG_Valid and < 1. | +---------------------------------------------------------------------------*/ -int poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result) +int poly_2xm1(u_char sign, FPU_REG * arg, FPU_REG * result) { - long int exponent, shift; - unsigned long long Xll; - Xsig accumulator, Denom, argSignif; - u_char tag; + long int exponent, shift; + unsigned long long Xll; + Xsig accumulator, Denom, argSignif; + u_char tag; - exponent = exponent16(arg); + exponent = exponent16(arg); #ifdef PARANOID - if ( exponent >= 0 ) /* Don't want a |number| >= 1.0 */ - { - /* Number negative, too large, or not Valid. */ - EXCEPTION(EX_INTERNAL|0x127); - return 1; - } + if (exponent >= 0) { /* Don't want a |number| >= 1.0 */ + /* Number negative, too large, or not Valid. */ + EXCEPTION(EX_INTERNAL | 0x127); + return 1; + } #endif /* PARANOID */ - argSignif.lsw = 0; - XSIG_LL(argSignif) = Xll = significand(arg); + argSignif.lsw = 0; + XSIG_LL(argSignif) = Xll = significand(arg); - if ( exponent == -1 ) - { - shift = (argSignif.msw & 0x40000000) ? 3 : 2; - /* subtract 0.5 or 0.75 */ - exponent -= 2; - XSIG_LL(argSignif) <<= 2; - Xll <<= 2; - } - else if ( exponent == -2 ) - { - shift = 1; - /* subtract 0.25 */ - exponent--; - XSIG_LL(argSignif) <<= 1; - Xll <<= 1; - } - else - shift = 0; + if (exponent == -1) { + shift = (argSignif.msw & 0x40000000) ? 3 : 2; + /* subtract 0.5 or 0.75 */ + exponent -= 2; + XSIG_LL(argSignif) <<= 2; + Xll <<= 2; + } else if (exponent == -2) { + shift = 1; + /* subtract 0.25 */ + exponent--; + XSIG_LL(argSignif) <<= 1; + Xll <<= 1; + } else + shift = 0; - if ( exponent < -2 ) - { - /* Shift the argument right by the required places. */ - if ( FPU_shrx(&Xll, -2-exponent) >= 0x80000000U ) - Xll++; /* round up */ - } - - accumulator.lsw = accumulator.midw = accumulator.msw = 0; - polynomial_Xsig(&accumulator, &Xll, lterms, HIPOWER-1); - mul_Xsig_Xsig(&accumulator, &argSignif); - shr_Xsig(&accumulator, 3); - - mul_Xsig_Xsig(&argSignif, &hiterm); /* The leading term */ - add_two_Xsig(&accumulator, &argSignif, &exponent); - - if ( shift ) - { - /* The argument is large, use the identity: - f(x+a) = f(a) * (f(x) + 1) - 1; - */ - shr_Xsig(&accumulator, - exponent); - accumulator.msw |= 0x80000000; /* add 1.0 */ - mul_Xsig_Xsig(&accumulator, shiftterm[shift]); - accumulator.msw &= 0x3fffffff; /* subtract 1.0 */ - exponent = 1; - } - - if ( sign != SIGN_POS ) - { - /* The argument is negative, use the identity: - f(-x) = -f(x) / (1 + f(x)) - */ - Denom.lsw = accumulator.lsw; - XSIG_LL(Denom) = XSIG_LL(accumulator); - if ( exponent < 0 ) - shr_Xsig(&Denom, - exponent); - else if ( exponent > 0 ) - { - /* exponent must be 1 here */ - XSIG_LL(Denom) <<= 1; - if ( Denom.lsw & 0x80000000 ) - XSIG_LL(Denom) |= 1; - (Denom.lsw) <<= 1; + if (exponent < -2) { + /* Shift the argument right by the required places. */ + if (FPU_shrx(&Xll, -2 - exponent) >= 0x80000000U) + Xll++; /* round up */ } - Denom.msw |= 0x80000000; /* add 1.0 */ - div_Xsig(&accumulator, &Denom, &accumulator); - } - /* Convert to 64 bit signed-compatible */ - exponent += round_Xsig(&accumulator); + accumulator.lsw = accumulator.midw = accumulator.msw = 0; + polynomial_Xsig(&accumulator, &Xll, lterms, HIPOWER - 1); + mul_Xsig_Xsig(&accumulator, &argSignif); + shr_Xsig(&accumulator, 3); - result = &st(0); - significand(result) = XSIG_LL(accumulator); - setexponent16(result, exponent); + mul_Xsig_Xsig(&argSignif, &hiterm); /* The leading term */ + add_two_Xsig(&accumulator, &argSignif, &exponent); - tag = FPU_round(result, 1, 0, FULL_PRECISION, sign); + if (shift) { + /* The argument is large, use the identity: + f(x+a) = f(a) * (f(x) + 1) - 1; + */ + shr_Xsig(&accumulator, -exponent); + accumulator.msw |= 0x80000000; /* add 1.0 */ + mul_Xsig_Xsig(&accumulator, shiftterm[shift]); + accumulator.msw &= 0x3fffffff; /* subtract 1.0 */ + exponent = 1; + } - setsign(result, sign); - FPU_settag0(tag); + if (sign != SIGN_POS) { + /* The argument is negative, use the identity: + f(-x) = -f(x) / (1 + f(x)) + */ + Denom.lsw = accumulator.lsw; + XSIG_LL(Denom) = XSIG_LL(accumulator); + if (exponent < 0) + shr_Xsig(&Denom, -exponent); + else if (exponent > 0) { + /* exponent must be 1 here */ + XSIG_LL(Denom) <<= 1; + if (Denom.lsw & 0x80000000) + XSIG_LL(Denom) |= 1; + (Denom.lsw) <<= 1; + } + Denom.msw |= 0x80000000; /* add 1.0 */ + div_Xsig(&accumulator, &Denom, &accumulator); + } - return 0; + /* Convert to 64 bit signed-compatible */ + exponent += round_Xsig(&accumulator); + + result = &st(0); + significand(result) = XSIG_LL(accumulator); + setexponent16(result, exponent); + + tag = FPU_round(result, 1, 0, FULL_PRECISION, sign); + + setsign(result, sign); + FPU_settag0(tag); + + return 0; } diff --git a/arch/x86/math-emu/poly_atan.c b/arch/x86/math-emu/poly_atan.c index 82f702952f69..2f4ac8143fc3 100644 --- a/arch/x86/math-emu/poly_atan.c +++ b/arch/x86/math-emu/poly_atan.c @@ -18,28 +18,25 @@ #include "control_w.h" #include "poly.h" - #define HIPOWERon 6 /* odd poly, negative terms */ -static const unsigned long long oddnegterms[HIPOWERon] = -{ - 0x0000000000000000LL, /* Dummy (not for - 1.0) */ - 0x015328437f756467LL, - 0x0005dda27b73dec6LL, - 0x0000226bf2bfb91aLL, - 0x000000ccc439c5f7LL, - 0x0000000355438407LL -} ; +static const unsigned long long oddnegterms[HIPOWERon] = { + 0x0000000000000000LL, /* Dummy (not for - 1.0) */ + 0x015328437f756467LL, + 0x0005dda27b73dec6LL, + 0x0000226bf2bfb91aLL, + 0x000000ccc439c5f7LL, + 0x0000000355438407LL +}; #define HIPOWERop 6 /* odd poly, positive terms */ -static const unsigned long long oddplterms[HIPOWERop] = -{ +static const unsigned long long oddplterms[HIPOWERop] = { /* 0xaaaaaaaaaaaaaaabLL, transferred to fixedpterm[] */ - 0x0db55a71875c9ac2LL, - 0x0029fce2d67880b0LL, - 0x0000dfd3908b4596LL, - 0x00000550fd61dab4LL, - 0x0000001c9422b3f9LL, - 0x000000003e3301e1LL + 0x0db55a71875c9ac2LL, + 0x0029fce2d67880b0LL, + 0x0000dfd3908b4596LL, + 0x00000550fd61dab4LL, + 0x0000001c9422b3f9LL, + 0x000000003e3301e1LL }; static const unsigned long long denomterm = 0xebd9b842c5c53a0eLL; @@ -48,182 +45,164 @@ static const Xsig fixedpterm = MK_XSIG(0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa); static const Xsig pi_signif = MK_XSIG(0xc90fdaa2, 0x2168c234, 0xc4c6628b); - /*--- poly_atan() -----------------------------------------------------------+ | | +---------------------------------------------------------------------------*/ -void poly_atan(FPU_REG *st0_ptr, u_char st0_tag, - FPU_REG *st1_ptr, u_char st1_tag) +void poly_atan(FPU_REG * st0_ptr, u_char st0_tag, + FPU_REG * st1_ptr, u_char st1_tag) { - u_char transformed, inverted, - sign1, sign2; - int exponent; - long int dummy_exp; - Xsig accumulator, Numer, Denom, accumulatore, argSignif, - argSq, argSqSq; - u_char tag; - - sign1 = getsign(st0_ptr); - sign2 = getsign(st1_ptr); - if ( st0_tag == TAG_Valid ) - { - exponent = exponent(st0_ptr); - } - else - { - /* This gives non-compatible stack contents... */ - FPU_to_exp16(st0_ptr, st0_ptr); - exponent = exponent16(st0_ptr); - } - if ( st1_tag == TAG_Valid ) - { - exponent -= exponent(st1_ptr); - } - else - { - /* This gives non-compatible stack contents... */ - FPU_to_exp16(st1_ptr, st1_ptr); - exponent -= exponent16(st1_ptr); - } + u_char transformed, inverted, sign1, sign2; + int exponent; + long int dummy_exp; + Xsig accumulator, Numer, Denom, accumulatore, argSignif, argSq, argSqSq; + u_char tag; - if ( (exponent < 0) || ((exponent == 0) && - ((st0_ptr->sigh < st1_ptr->sigh) || - ((st0_ptr->sigh == st1_ptr->sigh) && - (st0_ptr->sigl < st1_ptr->sigl))) ) ) - { - inverted = 1; - Numer.lsw = Denom.lsw = 0; - XSIG_LL(Numer) = significand(st0_ptr); - XSIG_LL(Denom) = significand(st1_ptr); - } - else - { - inverted = 0; - exponent = -exponent; - Numer.lsw = Denom.lsw = 0; - XSIG_LL(Numer) = significand(st1_ptr); - XSIG_LL(Denom) = significand(st0_ptr); - } - div_Xsig(&Numer, &Denom, &argSignif); - exponent += norm_Xsig(&argSignif); + sign1 = getsign(st0_ptr); + sign2 = getsign(st1_ptr); + if (st0_tag == TAG_Valid) { + exponent = exponent(st0_ptr); + } else { + /* This gives non-compatible stack contents... */ + FPU_to_exp16(st0_ptr, st0_ptr); + exponent = exponent16(st0_ptr); + } + if (st1_tag == TAG_Valid) { + exponent -= exponent(st1_ptr); + } else { + /* This gives non-compatible stack contents... */ + FPU_to_exp16(st1_ptr, st1_ptr); + exponent -= exponent16(st1_ptr); + } - if ( (exponent >= -1) - || ((exponent == -2) && (argSignif.msw > 0xd413ccd0)) ) - { - /* The argument is greater than sqrt(2)-1 (=0.414213562...) */ - /* Convert the argument by an identity for atan */ - transformed = 1; + if ((exponent < 0) || ((exponent == 0) && + ((st0_ptr->sigh < st1_ptr->sigh) || + ((st0_ptr->sigh == st1_ptr->sigh) && + (st0_ptr->sigl < st1_ptr->sigl))))) { + inverted = 1; + Numer.lsw = Denom.lsw = 0; + XSIG_LL(Numer) = significand(st0_ptr); + XSIG_LL(Denom) = significand(st1_ptr); + } else { + inverted = 0; + exponent = -exponent; + Numer.lsw = Denom.lsw = 0; + XSIG_LL(Numer) = significand(st1_ptr); + XSIG_LL(Denom) = significand(st0_ptr); + } + div_Xsig(&Numer, &Denom, &argSignif); + exponent += norm_Xsig(&argSignif); - if ( exponent >= 0 ) - { + if ((exponent >= -1) + || ((exponent == -2) && (argSignif.msw > 0xd413ccd0))) { + /* The argument is greater than sqrt(2)-1 (=0.414213562...) */ + /* Convert the argument by an identity for atan */ + transformed = 1; + + if (exponent >= 0) { #ifdef PARANOID - if ( !( (exponent == 0) && - (argSignif.lsw == 0) && (argSignif.midw == 0) && - (argSignif.msw == 0x80000000) ) ) - { - EXCEPTION(EX_INTERNAL|0x104); /* There must be a logic error */ - return; - } + if (!((exponent == 0) && + (argSignif.lsw == 0) && (argSignif.midw == 0) && + (argSignif.msw == 0x80000000))) { + EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic error */ + return; + } #endif /* PARANOID */ - argSignif.msw = 0; /* Make the transformed arg -> 0.0 */ + argSignif.msw = 0; /* Make the transformed arg -> 0.0 */ + } else { + Numer.lsw = Denom.lsw = argSignif.lsw; + XSIG_LL(Numer) = XSIG_LL(Denom) = XSIG_LL(argSignif); + + if (exponent < -1) + shr_Xsig(&Numer, -1 - exponent); + negate_Xsig(&Numer); + + shr_Xsig(&Denom, -exponent); + Denom.msw |= 0x80000000; + + div_Xsig(&Numer, &Denom, &argSignif); + + exponent = -1 + norm_Xsig(&argSignif); + } + } else { + transformed = 0; } - else - { - Numer.lsw = Denom.lsw = argSignif.lsw; - XSIG_LL(Numer) = XSIG_LL(Denom) = XSIG_LL(argSignif); - if ( exponent < -1 ) - shr_Xsig(&Numer, -1-exponent); - negate_Xsig(&Numer); - - shr_Xsig(&Denom, -exponent); - Denom.msw |= 0x80000000; - - div_Xsig(&Numer, &Denom, &argSignif); + argSq.lsw = argSignif.lsw; + argSq.midw = argSignif.midw; + argSq.msw = argSignif.msw; + mul_Xsig_Xsig(&argSq, &argSq); - exponent = -1 + norm_Xsig(&argSignif); + argSqSq.lsw = argSq.lsw; + argSqSq.midw = argSq.midw; + argSqSq.msw = argSq.msw; + mul_Xsig_Xsig(&argSqSq, &argSqSq); + + accumulatore.lsw = argSq.lsw; + XSIG_LL(accumulatore) = XSIG_LL(argSq); + + shr_Xsig(&argSq, 2 * (-1 - exponent - 1)); + shr_Xsig(&argSqSq, 4 * (-1 - exponent - 1)); + + /* Now have argSq etc with binary point at the left + .1xxxxxxxx */ + + /* Do the basic fixed point polynomial evaluation */ + accumulator.msw = accumulator.midw = accumulator.lsw = 0; + polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq), + oddplterms, HIPOWERop - 1); + mul64_Xsig(&accumulator, &XSIG_LL(argSq)); + negate_Xsig(&accumulator); + polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq), oddnegterms, + HIPOWERon - 1); + negate_Xsig(&accumulator); + add_two_Xsig(&accumulator, &fixedpterm, &dummy_exp); + + mul64_Xsig(&accumulatore, &denomterm); + shr_Xsig(&accumulatore, 1 + 2 * (-1 - exponent)); + accumulatore.msw |= 0x80000000; + + div_Xsig(&accumulator, &accumulatore, &accumulator); + + mul_Xsig_Xsig(&accumulator, &argSignif); + mul_Xsig_Xsig(&accumulator, &argSq); + + shr_Xsig(&accumulator, 3); + negate_Xsig(&accumulator); + add_Xsig_Xsig(&accumulator, &argSignif); + + if (transformed) { + /* compute pi/4 - accumulator */ + shr_Xsig(&accumulator, -1 - exponent); + negate_Xsig(&accumulator); + add_Xsig_Xsig(&accumulator, &pi_signif); + exponent = -1; } - } - else - { - transformed = 0; - } - argSq.lsw = argSignif.lsw; argSq.midw = argSignif.midw; - argSq.msw = argSignif.msw; - mul_Xsig_Xsig(&argSq, &argSq); - - argSqSq.lsw = argSq.lsw; argSqSq.midw = argSq.midw; argSqSq.msw = argSq.msw; - mul_Xsig_Xsig(&argSqSq, &argSqSq); + if (inverted) { + /* compute pi/2 - accumulator */ + shr_Xsig(&accumulator, -exponent); + negate_Xsig(&accumulator); + add_Xsig_Xsig(&accumulator, &pi_signif); + exponent = 0; + } - accumulatore.lsw = argSq.lsw; - XSIG_LL(accumulatore) = XSIG_LL(argSq); + if (sign1) { + /* compute pi - accumulator */ + shr_Xsig(&accumulator, 1 - exponent); + negate_Xsig(&accumulator); + add_Xsig_Xsig(&accumulator, &pi_signif); + exponent = 1; + } - shr_Xsig(&argSq, 2*(-1-exponent-1)); - shr_Xsig(&argSqSq, 4*(-1-exponent-1)); + exponent += round_Xsig(&accumulator); - /* Now have argSq etc with binary point at the left - .1xxxxxxxx */ + significand(st1_ptr) = XSIG_LL(accumulator); + setexponent16(st1_ptr, exponent); - /* Do the basic fixed point polynomial evaluation */ - accumulator.msw = accumulator.midw = accumulator.lsw = 0; - polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq), - oddplterms, HIPOWERop-1); - mul64_Xsig(&accumulator, &XSIG_LL(argSq)); - negate_Xsig(&accumulator); - polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq), oddnegterms, HIPOWERon-1); - negate_Xsig(&accumulator); - add_two_Xsig(&accumulator, &fixedpterm, &dummy_exp); + tag = FPU_round(st1_ptr, 1, 0, FULL_PRECISION, sign2); + FPU_settagi(1, tag); - mul64_Xsig(&accumulatore, &denomterm); - shr_Xsig(&accumulatore, 1 + 2*(-1-exponent)); - accumulatore.msw |= 0x80000000; - - div_Xsig(&accumulator, &accumulatore, &accumulator); - - mul_Xsig_Xsig(&accumulator, &argSignif); - mul_Xsig_Xsig(&accumulator, &argSq); - - shr_Xsig(&accumulator, 3); - negate_Xsig(&accumulator); - add_Xsig_Xsig(&accumulator, &argSignif); - - if ( transformed ) - { - /* compute pi/4 - accumulator */ - shr_Xsig(&accumulator, -1-exponent); - negate_Xsig(&accumulator); - add_Xsig_Xsig(&accumulator, &pi_signif); - exponent = -1; - } - - if ( inverted ) - { - /* compute pi/2 - accumulator */ - shr_Xsig(&accumulator, -exponent); - negate_Xsig(&accumulator); - add_Xsig_Xsig(&accumulator, &pi_signif); - exponent = 0; - } - - if ( sign1 ) - { - /* compute pi - accumulator */ - shr_Xsig(&accumulator, 1 - exponent); - negate_Xsig(&accumulator); - add_Xsig_Xsig(&accumulator, &pi_signif); - exponent = 1; - } - - exponent += round_Xsig(&accumulator); - - significand(st1_ptr) = XSIG_LL(accumulator); - setexponent16(st1_ptr, exponent); - - tag = FPU_round(st1_ptr, 1, 0, FULL_PRECISION, sign2); - FPU_settagi(1, tag); - - set_precision_flag_up(); /* We do not really know if up or down, - use this as the default. */ + set_precision_flag_up(); /* We do not really know if up or down, + use this as the default. */ } diff --git a/arch/x86/math-emu/poly_l2.c b/arch/x86/math-emu/poly_l2.c index dd00e1d5b074..c0102ae87511 100644 --- a/arch/x86/math-emu/poly_l2.c +++ b/arch/x86/math-emu/poly_l2.c @@ -10,7 +10,6 @@ | | +---------------------------------------------------------------------------*/ - #include "exception.h" #include "reg_constant.h" #include "fpu_emu.h" @@ -18,255 +17,228 @@ #include "control_w.h" #include "poly.h" - static void log2_kernel(FPU_REG const *arg, u_char argsign, - Xsig *accum_result, long int *expon); - + Xsig * accum_result, long int *expon); /*--- poly_l2() -------------------------------------------------------------+ | Base 2 logarithm by a polynomial approximation. | +---------------------------------------------------------------------------*/ -void poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign) +void poly_l2(FPU_REG * st0_ptr, FPU_REG * st1_ptr, u_char st1_sign) { - long int exponent, expon, expon_expon; - Xsig accumulator, expon_accum, yaccum; - u_char sign, argsign; - FPU_REG x; - int tag; + long int exponent, expon, expon_expon; + Xsig accumulator, expon_accum, yaccum; + u_char sign, argsign; + FPU_REG x; + int tag; - exponent = exponent16(st0_ptr); + exponent = exponent16(st0_ptr); - /* From st0_ptr, make a number > sqrt(2)/2 and < sqrt(2) */ - if ( st0_ptr->sigh > (unsigned)0xb504f334 ) - { - /* Treat as sqrt(2)/2 < st0_ptr < 1 */ - significand(&x) = - significand(st0_ptr); - setexponent16(&x, -1); - exponent++; - argsign = SIGN_NEG; - } - else - { - /* Treat as 1 <= st0_ptr < sqrt(2) */ - x.sigh = st0_ptr->sigh - 0x80000000; - x.sigl = st0_ptr->sigl; - setexponent16(&x, 0); - argsign = SIGN_POS; - } - tag = FPU_normalize_nuo(&x); + /* From st0_ptr, make a number > sqrt(2)/2 and < sqrt(2) */ + if (st0_ptr->sigh > (unsigned)0xb504f334) { + /* Treat as sqrt(2)/2 < st0_ptr < 1 */ + significand(&x) = -significand(st0_ptr); + setexponent16(&x, -1); + exponent++; + argsign = SIGN_NEG; + } else { + /* Treat as 1 <= st0_ptr < sqrt(2) */ + x.sigh = st0_ptr->sigh - 0x80000000; + x.sigl = st0_ptr->sigl; + setexponent16(&x, 0); + argsign = SIGN_POS; + } + tag = FPU_normalize_nuo(&x); - if ( tag == TAG_Zero ) - { - expon = 0; - accumulator.msw = accumulator.midw = accumulator.lsw = 0; - } - else - { - log2_kernel(&x, argsign, &accumulator, &expon); - } + if (tag == TAG_Zero) { + expon = 0; + accumulator.msw = accumulator.midw = accumulator.lsw = 0; + } else { + log2_kernel(&x, argsign, &accumulator, &expon); + } - if ( exponent < 0 ) - { - sign = SIGN_NEG; - exponent = -exponent; - } - else - sign = SIGN_POS; - expon_accum.msw = exponent; expon_accum.midw = expon_accum.lsw = 0; - if ( exponent ) - { - expon_expon = 31 + norm_Xsig(&expon_accum); - shr_Xsig(&accumulator, expon_expon - expon); + if (exponent < 0) { + sign = SIGN_NEG; + exponent = -exponent; + } else + sign = SIGN_POS; + expon_accum.msw = exponent; + expon_accum.midw = expon_accum.lsw = 0; + if (exponent) { + expon_expon = 31 + norm_Xsig(&expon_accum); + shr_Xsig(&accumulator, expon_expon - expon); - if ( sign ^ argsign ) - negate_Xsig(&accumulator); - add_Xsig_Xsig(&accumulator, &expon_accum); - } - else - { - expon_expon = expon; - sign = argsign; - } + if (sign ^ argsign) + negate_Xsig(&accumulator); + add_Xsig_Xsig(&accumulator, &expon_accum); + } else { + expon_expon = expon; + sign = argsign; + } - yaccum.lsw = 0; XSIG_LL(yaccum) = significand(st1_ptr); - mul_Xsig_Xsig(&accumulator, &yaccum); + yaccum.lsw = 0; + XSIG_LL(yaccum) = significand(st1_ptr); + mul_Xsig_Xsig(&accumulator, &yaccum); - expon_expon += round_Xsig(&accumulator); + expon_expon += round_Xsig(&accumulator); - if ( accumulator.msw == 0 ) - { - FPU_copy_to_reg1(&CONST_Z, TAG_Zero); - return; - } + if (accumulator.msw == 0) { + FPU_copy_to_reg1(&CONST_Z, TAG_Zero); + return; + } - significand(st1_ptr) = XSIG_LL(accumulator); - setexponent16(st1_ptr, expon_expon + exponent16(st1_ptr) + 1); + significand(st1_ptr) = XSIG_LL(accumulator); + setexponent16(st1_ptr, expon_expon + exponent16(st1_ptr) + 1); - tag = FPU_round(st1_ptr, 1, 0, FULL_PRECISION, sign ^ st1_sign); - FPU_settagi(1, tag); + tag = FPU_round(st1_ptr, 1, 0, FULL_PRECISION, sign ^ st1_sign); + FPU_settagi(1, tag); - set_precision_flag_up(); /* 80486 appears to always do this */ + set_precision_flag_up(); /* 80486 appears to always do this */ - return; + return; } - /*--- poly_l2p1() -----------------------------------------------------------+ | Base 2 logarithm by a polynomial approximation. | | log2(x+1) | +---------------------------------------------------------------------------*/ -int poly_l2p1(u_char sign0, u_char sign1, - FPU_REG *st0_ptr, FPU_REG *st1_ptr, FPU_REG *dest) +int poly_l2p1(u_char sign0, u_char sign1, + FPU_REG * st0_ptr, FPU_REG * st1_ptr, FPU_REG * dest) { - u_char tag; - long int exponent; - Xsig accumulator, yaccum; + u_char tag; + long int exponent; + Xsig accumulator, yaccum; - if ( exponent16(st0_ptr) < 0 ) - { - log2_kernel(st0_ptr, sign0, &accumulator, &exponent); + if (exponent16(st0_ptr) < 0) { + log2_kernel(st0_ptr, sign0, &accumulator, &exponent); - yaccum.lsw = 0; - XSIG_LL(yaccum) = significand(st1_ptr); - mul_Xsig_Xsig(&accumulator, &yaccum); + yaccum.lsw = 0; + XSIG_LL(yaccum) = significand(st1_ptr); + mul_Xsig_Xsig(&accumulator, &yaccum); - exponent += round_Xsig(&accumulator); + exponent += round_Xsig(&accumulator); - exponent += exponent16(st1_ptr) + 1; - if ( exponent < EXP_WAY_UNDER ) exponent = EXP_WAY_UNDER; + exponent += exponent16(st1_ptr) + 1; + if (exponent < EXP_WAY_UNDER) + exponent = EXP_WAY_UNDER; - significand(dest) = XSIG_LL(accumulator); - setexponent16(dest, exponent); + significand(dest) = XSIG_LL(accumulator); + setexponent16(dest, exponent); - tag = FPU_round(dest, 1, 0, FULL_PRECISION, sign0 ^ sign1); - FPU_settagi(1, tag); + tag = FPU_round(dest, 1, 0, FULL_PRECISION, sign0 ^ sign1); + FPU_settagi(1, tag); - if ( tag == TAG_Valid ) - set_precision_flag_up(); /* 80486 appears to always do this */ - } - else - { - /* The magnitude of st0_ptr is far too large. */ + if (tag == TAG_Valid) + set_precision_flag_up(); /* 80486 appears to always do this */ + } else { + /* The magnitude of st0_ptr is far too large. */ - if ( sign0 != SIGN_POS ) - { - /* Trying to get the log of a negative number. */ -#ifdef PECULIAR_486 /* Stupid 80486 doesn't worry about log(negative). */ - changesign(st1_ptr); + if (sign0 != SIGN_POS) { + /* Trying to get the log of a negative number. */ +#ifdef PECULIAR_486 /* Stupid 80486 doesn't worry about log(negative). */ + changesign(st1_ptr); #else - if ( arith_invalid(1) < 0 ) - return 1; + if (arith_invalid(1) < 0) + return 1; #endif /* PECULIAR_486 */ + } + + /* 80486 appears to do this */ + if (sign0 == SIGN_NEG) + set_precision_flag_down(); + else + set_precision_flag_up(); } - /* 80486 appears to do this */ - if ( sign0 == SIGN_NEG ) - set_precision_flag_down(); - else - set_precision_flag_up(); - } + if (exponent(dest) <= EXP_UNDER) + EXCEPTION(EX_Underflow); - if ( exponent(dest) <= EXP_UNDER ) - EXCEPTION(EX_Underflow); - - return 0; + return 0; } - - - #undef HIPOWER #define HIPOWER 10 -static const unsigned long long logterms[HIPOWER] = -{ - 0x2a8eca5705fc2ef0LL, - 0xf6384ee1d01febceLL, - 0x093bb62877cdf642LL, - 0x006985d8a9ec439bLL, - 0x0005212c4f55a9c8LL, - 0x00004326a16927f0LL, - 0x0000038d1d80a0e7LL, - 0x0000003141cc80c6LL, - 0x00000002b1668c9fLL, - 0x000000002c7a46aaLL +static const unsigned long long logterms[HIPOWER] = { + 0x2a8eca5705fc2ef0LL, + 0xf6384ee1d01febceLL, + 0x093bb62877cdf642LL, + 0x006985d8a9ec439bLL, + 0x0005212c4f55a9c8LL, + 0x00004326a16927f0LL, + 0x0000038d1d80a0e7LL, + 0x0000003141cc80c6LL, + 0x00000002b1668c9fLL, + 0x000000002c7a46aaLL }; static const unsigned long leadterm = 0xb8000000; - /*--- log2_kernel() ---------------------------------------------------------+ | Base 2 logarithm by a polynomial approximation. | | log2(x+1) | +---------------------------------------------------------------------------*/ -static void log2_kernel(FPU_REG const *arg, u_char argsign, Xsig *accum_result, +static void log2_kernel(FPU_REG const *arg, u_char argsign, Xsig * accum_result, long int *expon) { - long int exponent, adj; - unsigned long long Xsq; - Xsig accumulator, Numer, Denom, argSignif, arg_signif; + long int exponent, adj; + unsigned long long Xsq; + Xsig accumulator, Numer, Denom, argSignif, arg_signif; - exponent = exponent16(arg); - Numer.lsw = Denom.lsw = 0; - XSIG_LL(Numer) = XSIG_LL(Denom) = significand(arg); - if ( argsign == SIGN_POS ) - { - shr_Xsig(&Denom, 2 - (1 + exponent)); - Denom.msw |= 0x80000000; - div_Xsig(&Numer, &Denom, &argSignif); - } - else - { - shr_Xsig(&Denom, 1 - (1 + exponent)); - negate_Xsig(&Denom); - if ( Denom.msw & 0x80000000 ) - { - div_Xsig(&Numer, &Denom, &argSignif); - exponent ++; + exponent = exponent16(arg); + Numer.lsw = Denom.lsw = 0; + XSIG_LL(Numer) = XSIG_LL(Denom) = significand(arg); + if (argsign == SIGN_POS) { + shr_Xsig(&Denom, 2 - (1 + exponent)); + Denom.msw |= 0x80000000; + div_Xsig(&Numer, &Denom, &argSignif); + } else { + shr_Xsig(&Denom, 1 - (1 + exponent)); + negate_Xsig(&Denom); + if (Denom.msw & 0x80000000) { + div_Xsig(&Numer, &Denom, &argSignif); + exponent++; + } else { + /* Denom must be 1.0 */ + argSignif.lsw = Numer.lsw; + argSignif.midw = Numer.midw; + argSignif.msw = Numer.msw; + } } - else - { - /* Denom must be 1.0 */ - argSignif.lsw = Numer.lsw; argSignif.midw = Numer.midw; - argSignif.msw = Numer.msw; - } - } #ifndef PECULIAR_486 - /* Should check here that |local_arg| is within the valid range */ - if ( exponent >= -2 ) - { - if ( (exponent > -2) || - (argSignif.msw > (unsigned)0xafb0ccc0) ) - { - /* The argument is too large */ + /* Should check here that |local_arg| is within the valid range */ + if (exponent >= -2) { + if ((exponent > -2) || (argSignif.msw > (unsigned)0xafb0ccc0)) { + /* The argument is too large */ + } } - } #endif /* PECULIAR_486 */ - arg_signif.lsw = argSignif.lsw; XSIG_LL(arg_signif) = XSIG_LL(argSignif); - adj = norm_Xsig(&argSignif); - accumulator.lsw = argSignif.lsw; XSIG_LL(accumulator) = XSIG_LL(argSignif); - mul_Xsig_Xsig(&accumulator, &accumulator); - shr_Xsig(&accumulator, 2*(-1 - (1 + exponent + adj))); - Xsq = XSIG_LL(accumulator); - if ( accumulator.lsw & 0x80000000 ) - Xsq++; + arg_signif.lsw = argSignif.lsw; + XSIG_LL(arg_signif) = XSIG_LL(argSignif); + adj = norm_Xsig(&argSignif); + accumulator.lsw = argSignif.lsw; + XSIG_LL(accumulator) = XSIG_LL(argSignif); + mul_Xsig_Xsig(&accumulator, &accumulator); + shr_Xsig(&accumulator, 2 * (-1 - (1 + exponent + adj))); + Xsq = XSIG_LL(accumulator); + if (accumulator.lsw & 0x80000000) + Xsq++; - accumulator.msw = accumulator.midw = accumulator.lsw = 0; - /* Do the basic fixed point polynomial evaluation */ - polynomial_Xsig(&accumulator, &Xsq, logterms, HIPOWER-1); + accumulator.msw = accumulator.midw = accumulator.lsw = 0; + /* Do the basic fixed point polynomial evaluation */ + polynomial_Xsig(&accumulator, &Xsq, logterms, HIPOWER - 1); - mul_Xsig_Xsig(&accumulator, &argSignif); - shr_Xsig(&accumulator, 6 - adj); + mul_Xsig_Xsig(&accumulator, &argSignif); + shr_Xsig(&accumulator, 6 - adj); - mul32_Xsig(&arg_signif, leadterm); - add_two_Xsig(&accumulator, &arg_signif, &exponent); + mul32_Xsig(&arg_signif, leadterm); + add_two_Xsig(&accumulator, &arg_signif, &exponent); - *expon = exponent + 1; - accum_result->lsw = accumulator.lsw; - accum_result->midw = accumulator.midw; - accum_result->msw = accumulator.msw; + *expon = exponent + 1; + accum_result->lsw = accumulator.lsw; + accum_result->midw = accumulator.midw; + accum_result->msw = accumulator.msw; } diff --git a/arch/x86/math-emu/poly_sin.c b/arch/x86/math-emu/poly_sin.c index a36313fb06f1..7273ae0c7692 100644 --- a/arch/x86/math-emu/poly_sin.c +++ b/arch/x86/math-emu/poly_sin.c @@ -11,7 +11,6 @@ | | +---------------------------------------------------------------------------*/ - #include "exception.h" #include "reg_constant.h" #include "fpu_emu.h" @@ -19,379 +18,361 @@ #include "control_w.h" #include "poly.h" - #define N_COEFF_P 4 #define N_COEFF_N 4 -static const unsigned long long pos_terms_l[N_COEFF_P] = -{ - 0xaaaaaaaaaaaaaaabLL, - 0x00d00d00d00cf906LL, - 0x000006b99159a8bbLL, - 0x000000000d7392e6LL +static const unsigned long long pos_terms_l[N_COEFF_P] = { + 0xaaaaaaaaaaaaaaabLL, + 0x00d00d00d00cf906LL, + 0x000006b99159a8bbLL, + 0x000000000d7392e6LL }; -static const unsigned long long neg_terms_l[N_COEFF_N] = -{ - 0x2222222222222167LL, - 0x0002e3bc74aab624LL, - 0x0000000b09229062LL, - 0x00000000000c7973LL +static const unsigned long long neg_terms_l[N_COEFF_N] = { + 0x2222222222222167LL, + 0x0002e3bc74aab624LL, + 0x0000000b09229062LL, + 0x00000000000c7973LL }; - - #define N_COEFF_PH 4 #define N_COEFF_NH 4 -static const unsigned long long pos_terms_h[N_COEFF_PH] = -{ - 0x0000000000000000LL, - 0x05b05b05b05b0406LL, - 0x000049f93edd91a9LL, - 0x00000000c9c9ed62LL +static const unsigned long long pos_terms_h[N_COEFF_PH] = { + 0x0000000000000000LL, + 0x05b05b05b05b0406LL, + 0x000049f93edd91a9LL, + 0x00000000c9c9ed62LL }; -static const unsigned long long neg_terms_h[N_COEFF_NH] = -{ - 0xaaaaaaaaaaaaaa98LL, - 0x001a01a01a019064LL, - 0x0000008f76c68a77LL, - 0x0000000000d58f5eLL +static const unsigned long long neg_terms_h[N_COEFF_NH] = { + 0xaaaaaaaaaaaaaa98LL, + 0x001a01a01a019064LL, + 0x0000008f76c68a77LL, + 0x0000000000d58f5eLL }; - /*--- poly_sine() -----------------------------------------------------------+ | | +---------------------------------------------------------------------------*/ -void poly_sine(FPU_REG *st0_ptr) +void poly_sine(FPU_REG * st0_ptr) { - int exponent, echange; - Xsig accumulator, argSqrd, argTo4; - unsigned long fix_up, adj; - unsigned long long fixed_arg; - FPU_REG result; + int exponent, echange; + Xsig accumulator, argSqrd, argTo4; + unsigned long fix_up, adj; + unsigned long long fixed_arg; + FPU_REG result; - exponent = exponent(st0_ptr); + exponent = exponent(st0_ptr); - accumulator.lsw = accumulator.midw = accumulator.msw = 0; + accumulator.lsw = accumulator.midw = accumulator.msw = 0; - /* Split into two ranges, for arguments below and above 1.0 */ - /* The boundary between upper and lower is approx 0.88309101259 */ - if ( (exponent < -1) || ((exponent == -1) && (st0_ptr->sigh <= 0xe21240aa)) ) - { - /* The argument is <= 0.88309101259 */ + /* Split into two ranges, for arguments below and above 1.0 */ + /* The boundary between upper and lower is approx 0.88309101259 */ + if ((exponent < -1) + || ((exponent == -1) && (st0_ptr->sigh <= 0xe21240aa))) { + /* The argument is <= 0.88309101259 */ - argSqrd.msw = st0_ptr->sigh; argSqrd.midw = st0_ptr->sigl; argSqrd.lsw = 0; - mul64_Xsig(&argSqrd, &significand(st0_ptr)); - shr_Xsig(&argSqrd, 2*(-1-exponent)); - argTo4.msw = argSqrd.msw; argTo4.midw = argSqrd.midw; - argTo4.lsw = argSqrd.lsw; - mul_Xsig_Xsig(&argTo4, &argTo4); + argSqrd.msw = st0_ptr->sigh; + argSqrd.midw = st0_ptr->sigl; + argSqrd.lsw = 0; + mul64_Xsig(&argSqrd, &significand(st0_ptr)); + shr_Xsig(&argSqrd, 2 * (-1 - exponent)); + argTo4.msw = argSqrd.msw; + argTo4.midw = argSqrd.midw; + argTo4.lsw = argSqrd.lsw; + mul_Xsig_Xsig(&argTo4, &argTo4); - polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_l, - N_COEFF_N-1); - mul_Xsig_Xsig(&accumulator, &argSqrd); - negate_Xsig(&accumulator); + polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_l, + N_COEFF_N - 1); + mul_Xsig_Xsig(&accumulator, &argSqrd); + negate_Xsig(&accumulator); - polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_l, - N_COEFF_P-1); + polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_l, + N_COEFF_P - 1); - shr_Xsig(&accumulator, 2); /* Divide by four */ - accumulator.msw |= 0x80000000; /* Add 1.0 */ + shr_Xsig(&accumulator, 2); /* Divide by four */ + accumulator.msw |= 0x80000000; /* Add 1.0 */ - mul64_Xsig(&accumulator, &significand(st0_ptr)); - mul64_Xsig(&accumulator, &significand(st0_ptr)); - mul64_Xsig(&accumulator, &significand(st0_ptr)); + mul64_Xsig(&accumulator, &significand(st0_ptr)); + mul64_Xsig(&accumulator, &significand(st0_ptr)); + mul64_Xsig(&accumulator, &significand(st0_ptr)); - /* Divide by four, FPU_REG compatible, etc */ - exponent = 3*exponent; + /* Divide by four, FPU_REG compatible, etc */ + exponent = 3 * exponent; - /* The minimum exponent difference is 3 */ - shr_Xsig(&accumulator, exponent(st0_ptr) - exponent); + /* The minimum exponent difference is 3 */ + shr_Xsig(&accumulator, exponent(st0_ptr) - exponent); - negate_Xsig(&accumulator); - XSIG_LL(accumulator) += significand(st0_ptr); + negate_Xsig(&accumulator); + XSIG_LL(accumulator) += significand(st0_ptr); - echange = round_Xsig(&accumulator); + echange = round_Xsig(&accumulator); - setexponentpos(&result, exponent(st0_ptr) + echange); - } - else - { - /* The argument is > 0.88309101259 */ - /* We use sin(st(0)) = cos(pi/2-st(0)) */ + setexponentpos(&result, exponent(st0_ptr) + echange); + } else { + /* The argument is > 0.88309101259 */ + /* We use sin(st(0)) = cos(pi/2-st(0)) */ - fixed_arg = significand(st0_ptr); + fixed_arg = significand(st0_ptr); - if ( exponent == 0 ) - { - /* The argument is >= 1.0 */ + if (exponent == 0) { + /* The argument is >= 1.0 */ - /* Put the binary point at the left. */ - fixed_arg <<= 1; + /* Put the binary point at the left. */ + fixed_arg <<= 1; + } + /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */ + fixed_arg = 0x921fb54442d18469LL - fixed_arg; + /* There is a special case which arises due to rounding, to fix here. */ + if (fixed_arg == 0xffffffffffffffffLL) + fixed_arg = 0; + + XSIG_LL(argSqrd) = fixed_arg; + argSqrd.lsw = 0; + mul64_Xsig(&argSqrd, &fixed_arg); + + XSIG_LL(argTo4) = XSIG_LL(argSqrd); + argTo4.lsw = argSqrd.lsw; + mul_Xsig_Xsig(&argTo4, &argTo4); + + polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_h, + N_COEFF_NH - 1); + mul_Xsig_Xsig(&accumulator, &argSqrd); + negate_Xsig(&accumulator); + + polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_h, + N_COEFF_PH - 1); + negate_Xsig(&accumulator); + + mul64_Xsig(&accumulator, &fixed_arg); + mul64_Xsig(&accumulator, &fixed_arg); + + shr_Xsig(&accumulator, 3); + negate_Xsig(&accumulator); + + add_Xsig_Xsig(&accumulator, &argSqrd); + + shr_Xsig(&accumulator, 1); + + accumulator.lsw |= 1; /* A zero accumulator here would cause problems */ + negate_Xsig(&accumulator); + + /* The basic computation is complete. Now fix the answer to + compensate for the error due to the approximation used for + pi/2 + */ + + /* This has an exponent of -65 */ + fix_up = 0x898cc517; + /* The fix-up needs to be improved for larger args */ + if (argSqrd.msw & 0xffc00000) { + /* Get about 32 bit precision in these: */ + fix_up -= mul_32_32(0x898cc517, argSqrd.msw) / 6; + } + fix_up = mul_32_32(fix_up, LL_MSW(fixed_arg)); + + adj = accumulator.lsw; /* temp save */ + accumulator.lsw -= fix_up; + if (accumulator.lsw > adj) + XSIG_LL(accumulator)--; + + echange = round_Xsig(&accumulator); + + setexponentpos(&result, echange - 1); } - /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */ - fixed_arg = 0x921fb54442d18469LL - fixed_arg; - /* There is a special case which arises due to rounding, to fix here. */ - if ( fixed_arg == 0xffffffffffffffffLL ) - fixed_arg = 0; - XSIG_LL(argSqrd) = fixed_arg; argSqrd.lsw = 0; - mul64_Xsig(&argSqrd, &fixed_arg); - - XSIG_LL(argTo4) = XSIG_LL(argSqrd); argTo4.lsw = argSqrd.lsw; - mul_Xsig_Xsig(&argTo4, &argTo4); - - polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_h, - N_COEFF_NH-1); - mul_Xsig_Xsig(&accumulator, &argSqrd); - negate_Xsig(&accumulator); - - polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_h, - N_COEFF_PH-1); - negate_Xsig(&accumulator); - - mul64_Xsig(&accumulator, &fixed_arg); - mul64_Xsig(&accumulator, &fixed_arg); - - shr_Xsig(&accumulator, 3); - negate_Xsig(&accumulator); - - add_Xsig_Xsig(&accumulator, &argSqrd); - - shr_Xsig(&accumulator, 1); - - accumulator.lsw |= 1; /* A zero accumulator here would cause problems */ - negate_Xsig(&accumulator); - - /* The basic computation is complete. Now fix the answer to - compensate for the error due to the approximation used for - pi/2 - */ - - /* This has an exponent of -65 */ - fix_up = 0x898cc517; - /* The fix-up needs to be improved for larger args */ - if ( argSqrd.msw & 0xffc00000 ) - { - /* Get about 32 bit precision in these: */ - fix_up -= mul_32_32(0x898cc517, argSqrd.msw) / 6; - } - fix_up = mul_32_32(fix_up, LL_MSW(fixed_arg)); - - adj = accumulator.lsw; /* temp save */ - accumulator.lsw -= fix_up; - if ( accumulator.lsw > adj ) - XSIG_LL(accumulator) --; - - echange = round_Xsig(&accumulator); - - setexponentpos(&result, echange - 1); - } - - significand(&result) = XSIG_LL(accumulator); - setsign(&result, getsign(st0_ptr)); - FPU_copy_to_reg0(&result, TAG_Valid); + significand(&result) = XSIG_LL(accumulator); + setsign(&result, getsign(st0_ptr)); + FPU_copy_to_reg0(&result, TAG_Valid); #ifdef PARANOID - if ( (exponent(&result) >= 0) - && (significand(&result) > 0x8000000000000000LL) ) - { - EXCEPTION(EX_INTERNAL|0x150); - } + if ((exponent(&result) >= 0) + && (significand(&result) > 0x8000000000000000LL)) { + EXCEPTION(EX_INTERNAL | 0x150); + } #endif /* PARANOID */ } - - /*--- poly_cos() ------------------------------------------------------------+ | | +---------------------------------------------------------------------------*/ -void poly_cos(FPU_REG *st0_ptr) +void poly_cos(FPU_REG * st0_ptr) { - FPU_REG result; - long int exponent, exp2, echange; - Xsig accumulator, argSqrd, fix_up, argTo4; - unsigned long long fixed_arg; + FPU_REG result; + long int exponent, exp2, echange; + Xsig accumulator, argSqrd, fix_up, argTo4; + unsigned long long fixed_arg; #ifdef PARANOID - if ( (exponent(st0_ptr) > 0) - || ((exponent(st0_ptr) == 0) - && (significand(st0_ptr) > 0xc90fdaa22168c234LL)) ) - { - EXCEPTION(EX_Invalid); - FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); - return; - } + if ((exponent(st0_ptr) > 0) + || ((exponent(st0_ptr) == 0) + && (significand(st0_ptr) > 0xc90fdaa22168c234LL))) { + EXCEPTION(EX_Invalid); + FPU_copy_to_reg0(&CONST_QNaN, TAG_Special); + return; + } #endif /* PARANOID */ - exponent = exponent(st0_ptr); + exponent = exponent(st0_ptr); - accumulator.lsw = accumulator.midw = accumulator.msw = 0; + accumulator.lsw = accumulator.midw = accumulator.msw = 0; - if ( (exponent < -1) || ((exponent == -1) && (st0_ptr->sigh <= 0xb00d6f54)) ) - { - /* arg is < 0.687705 */ + if ((exponent < -1) + || ((exponent == -1) && (st0_ptr->sigh <= 0xb00d6f54))) { + /* arg is < 0.687705 */ - argSqrd.msw = st0_ptr->sigh; argSqrd.midw = st0_ptr->sigl; - argSqrd.lsw = 0; - mul64_Xsig(&argSqrd, &significand(st0_ptr)); + argSqrd.msw = st0_ptr->sigh; + argSqrd.midw = st0_ptr->sigl; + argSqrd.lsw = 0; + mul64_Xsig(&argSqrd, &significand(st0_ptr)); - if ( exponent < -1 ) - { - /* shift the argument right by the required places */ - shr_Xsig(&argSqrd, 2*(-1-exponent)); + if (exponent < -1) { + /* shift the argument right by the required places */ + shr_Xsig(&argSqrd, 2 * (-1 - exponent)); + } + + argTo4.msw = argSqrd.msw; + argTo4.midw = argSqrd.midw; + argTo4.lsw = argSqrd.lsw; + mul_Xsig_Xsig(&argTo4, &argTo4); + + polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_h, + N_COEFF_NH - 1); + mul_Xsig_Xsig(&accumulator, &argSqrd); + negate_Xsig(&accumulator); + + polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_h, + N_COEFF_PH - 1); + negate_Xsig(&accumulator); + + mul64_Xsig(&accumulator, &significand(st0_ptr)); + mul64_Xsig(&accumulator, &significand(st0_ptr)); + shr_Xsig(&accumulator, -2 * (1 + exponent)); + + shr_Xsig(&accumulator, 3); + negate_Xsig(&accumulator); + + add_Xsig_Xsig(&accumulator, &argSqrd); + + shr_Xsig(&accumulator, 1); + + /* It doesn't matter if accumulator is all zero here, the + following code will work ok */ + negate_Xsig(&accumulator); + + if (accumulator.lsw & 0x80000000) + XSIG_LL(accumulator)++; + if (accumulator.msw == 0) { + /* The result is 1.0 */ + FPU_copy_to_reg0(&CONST_1, TAG_Valid); + return; + } else { + significand(&result) = XSIG_LL(accumulator); + + /* will be a valid positive nr with expon = -1 */ + setexponentpos(&result, -1); + } + } else { + fixed_arg = significand(st0_ptr); + + if (exponent == 0) { + /* The argument is >= 1.0 */ + + /* Put the binary point at the left. */ + fixed_arg <<= 1; + } + /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */ + fixed_arg = 0x921fb54442d18469LL - fixed_arg; + /* There is a special case which arises due to rounding, to fix here. */ + if (fixed_arg == 0xffffffffffffffffLL) + fixed_arg = 0; + + exponent = -1; + exp2 = -1; + + /* A shift is needed here only for a narrow range of arguments, + i.e. for fixed_arg approx 2^-32, but we pick up more... */ + if (!(LL_MSW(fixed_arg) & 0xffff0000)) { + fixed_arg <<= 16; + exponent -= 16; + exp2 -= 16; + } + + XSIG_LL(argSqrd) = fixed_arg; + argSqrd.lsw = 0; + mul64_Xsig(&argSqrd, &fixed_arg); + + if (exponent < -1) { + /* shift the argument right by the required places */ + shr_Xsig(&argSqrd, 2 * (-1 - exponent)); + } + + argTo4.msw = argSqrd.msw; + argTo4.midw = argSqrd.midw; + argTo4.lsw = argSqrd.lsw; + mul_Xsig_Xsig(&argTo4, &argTo4); + + polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_l, + N_COEFF_N - 1); + mul_Xsig_Xsig(&accumulator, &argSqrd); + negate_Xsig(&accumulator); + + polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_l, + N_COEFF_P - 1); + + shr_Xsig(&accumulator, 2); /* Divide by four */ + accumulator.msw |= 0x80000000; /* Add 1.0 */ + + mul64_Xsig(&accumulator, &fixed_arg); + mul64_Xsig(&accumulator, &fixed_arg); + mul64_Xsig(&accumulator, &fixed_arg); + + /* Divide by four, FPU_REG compatible, etc */ + exponent = 3 * exponent; + + /* The minimum exponent difference is 3 */ + shr_Xsig(&accumulator, exp2 - exponent); + + negate_Xsig(&accumulator); + XSIG_LL(accumulator) += fixed_arg; + + /* The basic computation is complete. Now fix the answer to + compensate for the error due to the approximation used for + pi/2 + */ + + /* This has an exponent of -65 */ + XSIG_LL(fix_up) = 0x898cc51701b839a2ll; + fix_up.lsw = 0; + + /* The fix-up needs to be improved for larger args */ + if (argSqrd.msw & 0xffc00000) { + /* Get about 32 bit precision in these: */ + fix_up.msw -= mul_32_32(0x898cc517, argSqrd.msw) / 2; + fix_up.msw += mul_32_32(0x898cc517, argTo4.msw) / 24; + } + + exp2 += norm_Xsig(&accumulator); + shr_Xsig(&accumulator, 1); /* Prevent overflow */ + exp2++; + shr_Xsig(&fix_up, 65 + exp2); + + add_Xsig_Xsig(&accumulator, &fix_up); + + echange = round_Xsig(&accumulator); + + setexponentpos(&result, exp2 + echange); + significand(&result) = XSIG_LL(accumulator); } - argTo4.msw = argSqrd.msw; argTo4.midw = argSqrd.midw; - argTo4.lsw = argSqrd.lsw; - mul_Xsig_Xsig(&argTo4, &argTo4); - - polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_h, - N_COEFF_NH-1); - mul_Xsig_Xsig(&accumulator, &argSqrd); - negate_Xsig(&accumulator); - - polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_h, - N_COEFF_PH-1); - negate_Xsig(&accumulator); - - mul64_Xsig(&accumulator, &significand(st0_ptr)); - mul64_Xsig(&accumulator, &significand(st0_ptr)); - shr_Xsig(&accumulator, -2*(1+exponent)); - - shr_Xsig(&accumulator, 3); - negate_Xsig(&accumulator); - - add_Xsig_Xsig(&accumulator, &argSqrd); - - shr_Xsig(&accumulator, 1); - - /* It doesn't matter if accumulator is all zero here, the - following code will work ok */ - negate_Xsig(&accumulator); - - if ( accumulator.lsw & 0x80000000 ) - XSIG_LL(accumulator) ++; - if ( accumulator.msw == 0 ) - { - /* The result is 1.0 */ - FPU_copy_to_reg0(&CONST_1, TAG_Valid); - return; - } - else - { - significand(&result) = XSIG_LL(accumulator); - - /* will be a valid positive nr with expon = -1 */ - setexponentpos(&result, -1); - } - } - else - { - fixed_arg = significand(st0_ptr); - - if ( exponent == 0 ) - { - /* The argument is >= 1.0 */ - - /* Put the binary point at the left. */ - fixed_arg <<= 1; - } - /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */ - fixed_arg = 0x921fb54442d18469LL - fixed_arg; - /* There is a special case which arises due to rounding, to fix here. */ - if ( fixed_arg == 0xffffffffffffffffLL ) - fixed_arg = 0; - - exponent = -1; - exp2 = -1; - - /* A shift is needed here only for a narrow range of arguments, - i.e. for fixed_arg approx 2^-32, but we pick up more... */ - if ( !(LL_MSW(fixed_arg) & 0xffff0000) ) - { - fixed_arg <<= 16; - exponent -= 16; - exp2 -= 16; - } - - XSIG_LL(argSqrd) = fixed_arg; argSqrd.lsw = 0; - mul64_Xsig(&argSqrd, &fixed_arg); - - if ( exponent < -1 ) - { - /* shift the argument right by the required places */ - shr_Xsig(&argSqrd, 2*(-1-exponent)); - } - - argTo4.msw = argSqrd.msw; argTo4.midw = argSqrd.midw; - argTo4.lsw = argSqrd.lsw; - mul_Xsig_Xsig(&argTo4, &argTo4); - - polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_l, - N_COEFF_N-1); - mul_Xsig_Xsig(&accumulator, &argSqrd); - negate_Xsig(&accumulator); - - polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_l, - N_COEFF_P-1); - - shr_Xsig(&accumulator, 2); /* Divide by four */ - accumulator.msw |= 0x80000000; /* Add 1.0 */ - - mul64_Xsig(&accumulator, &fixed_arg); - mul64_Xsig(&accumulator, &fixed_arg); - mul64_Xsig(&accumulator, &fixed_arg); - - /* Divide by four, FPU_REG compatible, etc */ - exponent = 3*exponent; - - /* The minimum exponent difference is 3 */ - shr_Xsig(&accumulator, exp2 - exponent); - - negate_Xsig(&accumulator); - XSIG_LL(accumulator) += fixed_arg; - - /* The basic computation is complete. Now fix the answer to - compensate for the error due to the approximation used for - pi/2 - */ - - /* This has an exponent of -65 */ - XSIG_LL(fix_up) = 0x898cc51701b839a2ll; - fix_up.lsw = 0; - - /* The fix-up needs to be improved for larger args */ - if ( argSqrd.msw & 0xffc00000 ) - { - /* Get about 32 bit precision in these: */ - fix_up.msw -= mul_32_32(0x898cc517, argSqrd.msw) / 2; - fix_up.msw += mul_32_32(0x898cc517, argTo4.msw) / 24; - } - - exp2 += norm_Xsig(&accumulator); - shr_Xsig(&accumulator, 1); /* Prevent overflow */ - exp2++; - shr_Xsig(&fix_up, 65 + exp2); - - add_Xsig_Xsig(&accumulator, &fix_up); - - echange = round_Xsig(&accumulator); - - setexponentpos(&result, exp2 + echange); - significand(&result) = XSIG_LL(accumulator); - } - - FPU_copy_to_reg0(&result, TAG_Valid); + FPU_copy_to_reg0(&result, TAG_Valid); #ifdef PARANOID - if ( (exponent(&result) >= 0) - && (significand(&result) > 0x8000000000000000LL) ) - { - EXCEPTION(EX_INTERNAL|0x151); - } + if ((exponent(&result) >= 0) + && (significand(&result) > 0x8000000000000000LL)) { + EXCEPTION(EX_INTERNAL | 0x151); + } #endif /* PARANOID */ } diff --git a/arch/x86/math-emu/poly_tan.c b/arch/x86/math-emu/poly_tan.c index 8df3e03b6e6f..c0d181e39229 100644 --- a/arch/x86/math-emu/poly_tan.c +++ b/arch/x86/math-emu/poly_tan.c @@ -17,206 +17,196 @@ #include "control_w.h" #include "poly.h" - #define HiPOWERop 3 /* odd poly, positive terms */ -static const unsigned long long oddplterm[HiPOWERop] = -{ - 0x0000000000000000LL, - 0x0051a1cf08fca228LL, - 0x0000000071284ff7LL +static const unsigned long long oddplterm[HiPOWERop] = { + 0x0000000000000000LL, + 0x0051a1cf08fca228LL, + 0x0000000071284ff7LL }; #define HiPOWERon 2 /* odd poly, negative terms */ -static const unsigned long long oddnegterm[HiPOWERon] = -{ - 0x1291a9a184244e80LL, - 0x0000583245819c21LL +static const unsigned long long oddnegterm[HiPOWERon] = { + 0x1291a9a184244e80LL, + 0x0000583245819c21LL }; #define HiPOWERep 2 /* even poly, positive terms */ -static const unsigned long long evenplterm[HiPOWERep] = -{ - 0x0e848884b539e888LL, - 0x00003c7f18b887daLL +static const unsigned long long evenplterm[HiPOWERep] = { + 0x0e848884b539e888LL, + 0x00003c7f18b887daLL }; #define HiPOWERen 2 /* even poly, negative terms */ -static const unsigned long long evennegterm[HiPOWERen] = -{ - 0xf1f0200fd51569ccLL, - 0x003afb46105c4432LL +static const unsigned long long evennegterm[HiPOWERen] = { + 0xf1f0200fd51569ccLL, + 0x003afb46105c4432LL }; static const unsigned long long twothirds = 0xaaaaaaaaaaaaaaabLL; - /*--- poly_tan() ------------------------------------------------------------+ | | +---------------------------------------------------------------------------*/ -void poly_tan(FPU_REG *st0_ptr) +void poly_tan(FPU_REG * st0_ptr) { - long int exponent; - int invert; - Xsig argSq, argSqSq, accumulatoro, accumulatore, accum, - argSignif, fix_up; - unsigned long adj; + long int exponent; + int invert; + Xsig argSq, argSqSq, accumulatoro, accumulatore, accum, + argSignif, fix_up; + unsigned long adj; - exponent = exponent(st0_ptr); + exponent = exponent(st0_ptr); #ifdef PARANOID - if ( signnegative(st0_ptr) ) /* Can't hack a number < 0.0 */ - { arith_invalid(0); return; } /* Need a positive number */ + if (signnegative(st0_ptr)) { /* Can't hack a number < 0.0 */ + arith_invalid(0); + return; + } /* Need a positive number */ #endif /* PARANOID */ - /* Split the problem into two domains, smaller and larger than pi/4 */ - if ( (exponent == 0) || ((exponent == -1) && (st0_ptr->sigh > 0xc90fdaa2)) ) - { - /* The argument is greater than (approx) pi/4 */ - invert = 1; - accum.lsw = 0; - XSIG_LL(accum) = significand(st0_ptr); - - if ( exponent == 0 ) - { - /* The argument is >= 1.0 */ - /* Put the binary point at the left. */ - XSIG_LL(accum) <<= 1; - } - /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */ - XSIG_LL(accum) = 0x921fb54442d18469LL - XSIG_LL(accum); - /* This is a special case which arises due to rounding. */ - if ( XSIG_LL(accum) == 0xffffffffffffffffLL ) - { - FPU_settag0(TAG_Valid); - significand(st0_ptr) = 0x8a51e04daabda360LL; - setexponent16(st0_ptr, (0x41 + EXTENDED_Ebias) | SIGN_Negative); - return; + /* Split the problem into two domains, smaller and larger than pi/4 */ + if ((exponent == 0) + || ((exponent == -1) && (st0_ptr->sigh > 0xc90fdaa2))) { + /* The argument is greater than (approx) pi/4 */ + invert = 1; + accum.lsw = 0; + XSIG_LL(accum) = significand(st0_ptr); + + if (exponent == 0) { + /* The argument is >= 1.0 */ + /* Put the binary point at the left. */ + XSIG_LL(accum) <<= 1; + } + /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */ + XSIG_LL(accum) = 0x921fb54442d18469LL - XSIG_LL(accum); + /* This is a special case which arises due to rounding. */ + if (XSIG_LL(accum) == 0xffffffffffffffffLL) { + FPU_settag0(TAG_Valid); + significand(st0_ptr) = 0x8a51e04daabda360LL; + setexponent16(st0_ptr, + (0x41 + EXTENDED_Ebias) | SIGN_Negative); + return; + } + + argSignif.lsw = accum.lsw; + XSIG_LL(argSignif) = XSIG_LL(accum); + exponent = -1 + norm_Xsig(&argSignif); + } else { + invert = 0; + argSignif.lsw = 0; + XSIG_LL(accum) = XSIG_LL(argSignif) = significand(st0_ptr); + + if (exponent < -1) { + /* shift the argument right by the required places */ + if (FPU_shrx(&XSIG_LL(accum), -1 - exponent) >= + 0x80000000U) + XSIG_LL(accum)++; /* round up */ + } } - argSignif.lsw = accum.lsw; - XSIG_LL(argSignif) = XSIG_LL(accum); - exponent = -1 + norm_Xsig(&argSignif); - } - else - { - invert = 0; - argSignif.lsw = 0; - XSIG_LL(accum) = XSIG_LL(argSignif) = significand(st0_ptr); - - if ( exponent < -1 ) - { - /* shift the argument right by the required places */ - if ( FPU_shrx(&XSIG_LL(accum), -1-exponent) >= 0x80000000U ) - XSIG_LL(accum) ++; /* round up */ + XSIG_LL(argSq) = XSIG_LL(accum); + argSq.lsw = accum.lsw; + mul_Xsig_Xsig(&argSq, &argSq); + XSIG_LL(argSqSq) = XSIG_LL(argSq); + argSqSq.lsw = argSq.lsw; + mul_Xsig_Xsig(&argSqSq, &argSqSq); + + /* Compute the negative terms for the numerator polynomial */ + accumulatoro.msw = accumulatoro.midw = accumulatoro.lsw = 0; + polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddnegterm, + HiPOWERon - 1); + mul_Xsig_Xsig(&accumulatoro, &argSq); + negate_Xsig(&accumulatoro); + /* Add the positive terms */ + polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddplterm, + HiPOWERop - 1); + + /* Compute the positive terms for the denominator polynomial */ + accumulatore.msw = accumulatore.midw = accumulatore.lsw = 0; + polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evenplterm, + HiPOWERep - 1); + mul_Xsig_Xsig(&accumulatore, &argSq); + negate_Xsig(&accumulatore); + /* Add the negative terms */ + polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evennegterm, + HiPOWERen - 1); + /* Multiply by arg^2 */ + mul64_Xsig(&accumulatore, &XSIG_LL(argSignif)); + mul64_Xsig(&accumulatore, &XSIG_LL(argSignif)); + /* de-normalize and divide by 2 */ + shr_Xsig(&accumulatore, -2 * (1 + exponent) + 1); + negate_Xsig(&accumulatore); /* This does 1 - accumulator */ + + /* Now find the ratio. */ + if (accumulatore.msw == 0) { + /* accumulatoro must contain 1.0 here, (actually, 0) but it + really doesn't matter what value we use because it will + have negligible effect in later calculations + */ + XSIG_LL(accum) = 0x8000000000000000LL; + accum.lsw = 0; + } else { + div_Xsig(&accumulatoro, &accumulatore, &accum); } - } - XSIG_LL(argSq) = XSIG_LL(accum); argSq.lsw = accum.lsw; - mul_Xsig_Xsig(&argSq, &argSq); - XSIG_LL(argSqSq) = XSIG_LL(argSq); argSqSq.lsw = argSq.lsw; - mul_Xsig_Xsig(&argSqSq, &argSqSq); + /* Multiply by 1/3 * arg^3 */ + mul64_Xsig(&accum, &XSIG_LL(argSignif)); + mul64_Xsig(&accum, &XSIG_LL(argSignif)); + mul64_Xsig(&accum, &XSIG_LL(argSignif)); + mul64_Xsig(&accum, &twothirds); + shr_Xsig(&accum, -2 * (exponent + 1)); - /* Compute the negative terms for the numerator polynomial */ - accumulatoro.msw = accumulatoro.midw = accumulatoro.lsw = 0; - polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddnegterm, HiPOWERon-1); - mul_Xsig_Xsig(&accumulatoro, &argSq); - negate_Xsig(&accumulatoro); - /* Add the positive terms */ - polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddplterm, HiPOWERop-1); + /* tan(arg) = arg + accum */ + add_two_Xsig(&accum, &argSignif, &exponent); - - /* Compute the positive terms for the denominator polynomial */ - accumulatore.msw = accumulatore.midw = accumulatore.lsw = 0; - polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evenplterm, HiPOWERep-1); - mul_Xsig_Xsig(&accumulatore, &argSq); - negate_Xsig(&accumulatore); - /* Add the negative terms */ - polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evennegterm, HiPOWERen-1); - /* Multiply by arg^2 */ - mul64_Xsig(&accumulatore, &XSIG_LL(argSignif)); - mul64_Xsig(&accumulatore, &XSIG_LL(argSignif)); - /* de-normalize and divide by 2 */ - shr_Xsig(&accumulatore, -2*(1+exponent) + 1); - negate_Xsig(&accumulatore); /* This does 1 - accumulator */ + if (invert) { + /* We now have the value of tan(pi_2 - arg) where pi_2 is an + approximation for pi/2 + */ + /* The next step is to fix the answer to compensate for the + error due to the approximation used for pi/2 + */ - /* Now find the ratio. */ - if ( accumulatore.msw == 0 ) - { - /* accumulatoro must contain 1.0 here, (actually, 0) but it - really doesn't matter what value we use because it will - have negligible effect in later calculations - */ - XSIG_LL(accum) = 0x8000000000000000LL; - accum.lsw = 0; - } - else - { - div_Xsig(&accumulatoro, &accumulatore, &accum); - } + /* This is (approx) delta, the error in our approx for pi/2 + (see above). It has an exponent of -65 + */ + XSIG_LL(fix_up) = 0x898cc51701b839a2LL; + fix_up.lsw = 0; - /* Multiply by 1/3 * arg^3 */ - mul64_Xsig(&accum, &XSIG_LL(argSignif)); - mul64_Xsig(&accum, &XSIG_LL(argSignif)); - mul64_Xsig(&accum, &XSIG_LL(argSignif)); - mul64_Xsig(&accum, &twothirds); - shr_Xsig(&accum, -2*(exponent+1)); + if (exponent == 0) + adj = 0xffffffff; /* We want approx 1.0 here, but + this is close enough. */ + else if (exponent > -30) { + adj = accum.msw >> -(exponent + 1); /* tan */ + adj = mul_32_32(adj, adj); /* tan^2 */ + } else + adj = 0; + adj = mul_32_32(0x898cc517, adj); /* delta * tan^2 */ - /* tan(arg) = arg + accum */ - add_two_Xsig(&accum, &argSignif, &exponent); + fix_up.msw += adj; + if (!(fix_up.msw & 0x80000000)) { /* did fix_up overflow ? */ + /* Yes, we need to add an msb */ + shr_Xsig(&fix_up, 1); + fix_up.msw |= 0x80000000; + shr_Xsig(&fix_up, 64 + exponent); + } else + shr_Xsig(&fix_up, 65 + exponent); - if ( invert ) - { - /* We now have the value of tan(pi_2 - arg) where pi_2 is an - approximation for pi/2 - */ - /* The next step is to fix the answer to compensate for the - error due to the approximation used for pi/2 - */ + add_two_Xsig(&accum, &fix_up, &exponent); - /* This is (approx) delta, the error in our approx for pi/2 - (see above). It has an exponent of -65 - */ - XSIG_LL(fix_up) = 0x898cc51701b839a2LL; - fix_up.lsw = 0; - - if ( exponent == 0 ) - adj = 0xffffffff; /* We want approx 1.0 here, but - this is close enough. */ - else if ( exponent > -30 ) - { - adj = accum.msw >> -(exponent+1); /* tan */ - adj = mul_32_32(adj, adj); /* tan^2 */ + /* accum now contains tan(pi/2 - arg). + Use tan(arg) = 1.0 / tan(pi/2 - arg) + */ + accumulatoro.lsw = accumulatoro.midw = 0; + accumulatoro.msw = 0x80000000; + div_Xsig(&accumulatoro, &accum, &accum); + exponent = -exponent - 1; } - else - adj = 0; - adj = mul_32_32(0x898cc517, adj); /* delta * tan^2 */ - fix_up.msw += adj; - if ( !(fix_up.msw & 0x80000000) ) /* did fix_up overflow ? */ - { - /* Yes, we need to add an msb */ - shr_Xsig(&fix_up, 1); - fix_up.msw |= 0x80000000; - shr_Xsig(&fix_up, 64 + exponent); - } - else - shr_Xsig(&fix_up, 65 + exponent); - - add_two_Xsig(&accum, &fix_up, &exponent); - - /* accum now contains tan(pi/2 - arg). - Use tan(arg) = 1.0 / tan(pi/2 - arg) - */ - accumulatoro.lsw = accumulatoro.midw = 0; - accumulatoro.msw = 0x80000000; - div_Xsig(&accumulatoro, &accum, &accum); - exponent = - exponent - 1; - } - - /* Transfer the result */ - round_Xsig(&accum); - FPU_settag0(TAG_Valid); - significand(st0_ptr) = XSIG_LL(accum); - setexponent16(st0_ptr, exponent + EXTENDED_Ebias); /* Result is positive. */ + /* Transfer the result */ + round_Xsig(&accum); + FPU_settag0(TAG_Valid); + significand(st0_ptr) = XSIG_LL(accum); + setexponent16(st0_ptr, exponent + EXTENDED_Ebias); /* Result is positive. */ } diff --git a/arch/x86/math-emu/reg_add_sub.c b/arch/x86/math-emu/reg_add_sub.c index 7cd3b37ac084..deea48b9f13a 100644 --- a/arch/x86/math-emu/reg_add_sub.c +++ b/arch/x86/math-emu/reg_add_sub.c @@ -27,7 +27,7 @@ static int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa, FPU_REG const *b, u_char tagb, u_char signb, - FPU_REG *dest, int deststnr, int control_w); + FPU_REG * dest, int deststnr, int control_w); /* Operates on st(0) and st(n), or on st(0) and temporary data. @@ -35,340 +35,299 @@ int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa, */ int FPU_add(FPU_REG const *b, u_char tagb, int deststnr, int control_w) { - FPU_REG *a = &st(0); - FPU_REG *dest = &st(deststnr); - u_char signb = getsign(b); - u_char taga = FPU_gettag0(); - u_char signa = getsign(a); - u_char saved_sign = getsign(dest); - int diff, tag, expa, expb; - - if ( !(taga | tagb) ) - { - expa = exponent(a); - expb = exponent(b); + FPU_REG *a = &st(0); + FPU_REG *dest = &st(deststnr); + u_char signb = getsign(b); + u_char taga = FPU_gettag0(); + u_char signa = getsign(a); + u_char saved_sign = getsign(dest); + int diff, tag, expa, expb; - valid_add: - /* Both registers are valid */ - if (!(signa ^ signb)) - { - /* signs are the same */ - tag = FPU_u_add(a, b, dest, control_w, signa, expa, expb); - } - else - { - /* The signs are different, so do a subtraction */ - diff = expa - expb; - if (!diff) - { - diff = a->sigh - b->sigh; /* This works only if the ms bits - are identical. */ - if (!diff) - { - diff = a->sigl > b->sigl; - if (!diff) - diff = -(a->sigl < b->sigl); + if (!(taga | tagb)) { + expa = exponent(a); + expb = exponent(b); + + valid_add: + /* Both registers are valid */ + if (!(signa ^ signb)) { + /* signs are the same */ + tag = + FPU_u_add(a, b, dest, control_w, signa, expa, expb); + } else { + /* The signs are different, so do a subtraction */ + diff = expa - expb; + if (!diff) { + diff = a->sigh - b->sigh; /* This works only if the ms bits + are identical. */ + if (!diff) { + diff = a->sigl > b->sigl; + if (!diff) + diff = -(a->sigl < b->sigl); + } + } + + if (diff > 0) { + tag = + FPU_u_sub(a, b, dest, control_w, signa, + expa, expb); + } else if (diff < 0) { + tag = + FPU_u_sub(b, a, dest, control_w, signb, + expb, expa); + } else { + FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); + /* sign depends upon rounding mode */ + setsign(dest, ((control_w & CW_RC) != RC_DOWN) + ? SIGN_POS : SIGN_NEG); + return TAG_Zero; + } } - } - - if (diff > 0) - { - tag = FPU_u_sub(a, b, dest, control_w, signa, expa, expb); - } - else if ( diff < 0 ) - { - tag = FPU_u_sub(b, a, dest, control_w, signb, expb, expa); - } - else - { - FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); - /* sign depends upon rounding mode */ - setsign(dest, ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG); - return TAG_Zero; - } + + if (tag < 0) { + setsign(dest, saved_sign); + return tag; + } + FPU_settagi(deststnr, tag); + return tag; } - if ( tag < 0 ) - { - setsign(dest, saved_sign); - return tag; - } - FPU_settagi(deststnr, tag); - return tag; - } + if (taga == TAG_Special) + taga = FPU_Special(a); + if (tagb == TAG_Special) + tagb = FPU_Special(b); - if ( taga == TAG_Special ) - taga = FPU_Special(a); - if ( tagb == TAG_Special ) - tagb = FPU_Special(b); - - if ( ((taga == TAG_Valid) && (tagb == TW_Denormal)) + if (((taga == TAG_Valid) && (tagb == TW_Denormal)) || ((taga == TW_Denormal) && (tagb == TAG_Valid)) - || ((taga == TW_Denormal) && (tagb == TW_Denormal)) ) - { - FPU_REG x, y; + || ((taga == TW_Denormal) && (tagb == TW_Denormal))) { + FPU_REG x, y; - if ( denormal_operand() < 0 ) - return FPU_Exception; + if (denormal_operand() < 0) + return FPU_Exception; - FPU_to_exp16(a, &x); - FPU_to_exp16(b, &y); - a = &x; - b = &y; - expa = exponent16(a); - expb = exponent16(b); - goto valid_add; - } + FPU_to_exp16(a, &x); + FPU_to_exp16(b, &y); + a = &x; + b = &y; + expa = exponent16(a); + expb = exponent16(b); + goto valid_add; + } - if ( (taga == TW_NaN) || (tagb == TW_NaN) ) - { - if ( deststnr == 0 ) - return real_2op_NaN(b, tagb, deststnr, a); - else - return real_2op_NaN(a, taga, deststnr, a); - } + if ((taga == TW_NaN) || (tagb == TW_NaN)) { + if (deststnr == 0) + return real_2op_NaN(b, tagb, deststnr, a); + else + return real_2op_NaN(a, taga, deststnr, a); + } - return add_sub_specials(a, taga, signa, b, tagb, signb, - dest, deststnr, control_w); + return add_sub_specials(a, taga, signa, b, tagb, signb, + dest, deststnr, control_w); } - /* Subtract b from a. (a-b) -> dest */ int FPU_sub(int flags, int rm, int control_w) { - FPU_REG const *a, *b; - FPU_REG *dest; - u_char taga, tagb, signa, signb, saved_sign, sign; - int diff, tag = 0, expa, expb, deststnr; + FPU_REG const *a, *b; + FPU_REG *dest; + u_char taga, tagb, signa, signb, saved_sign, sign; + int diff, tag = 0, expa, expb, deststnr; - a = &st(0); - taga = FPU_gettag0(); + a = &st(0); + taga = FPU_gettag0(); - deststnr = 0; - if ( flags & LOADED ) - { - b = (FPU_REG *)rm; - tagb = flags & 0x0f; - } - else - { - b = &st(rm); - tagb = FPU_gettagi(rm); + deststnr = 0; + if (flags & LOADED) { + b = (FPU_REG *) rm; + tagb = flags & 0x0f; + } else { + b = &st(rm); + tagb = FPU_gettagi(rm); - if ( flags & DEST_RM ) - deststnr = rm; - } - - signa = getsign(a); - signb = getsign(b); - - if ( flags & REV ) - { - signa ^= SIGN_NEG; - signb ^= SIGN_NEG; - } - - dest = &st(deststnr); - saved_sign = getsign(dest); - - if ( !(taga | tagb) ) - { - expa = exponent(a); - expb = exponent(b); - - valid_subtract: - /* Both registers are valid */ - - diff = expa - expb; - - if (!diff) - { - diff = a->sigh - b->sigh; /* Works only if ms bits are identical */ - if (!diff) - { - diff = a->sigl > b->sigl; - if (!diff) - diff = -(a->sigl < b->sigl); - } + if (flags & DEST_RM) + deststnr = rm; } - switch ( (((int)signa)*2 + signb) / SIGN_NEG ) - { - case 0: /* P - P */ - case 3: /* N - N */ - if (diff > 0) - { - /* |a| > |b| */ - tag = FPU_u_sub(a, b, dest, control_w, signa, expa, expb); - } - else if ( diff == 0 ) - { - FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); + signa = getsign(a); + signb = getsign(b); - /* sign depends upon rounding mode */ - setsign(dest, ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG); - return TAG_Zero; - } - else - { - sign = signa ^ SIGN_NEG; - tag = FPU_u_sub(b, a, dest, control_w, sign, expb, expa); - } - break; - case 1: /* P - N */ - tag = FPU_u_add(a, b, dest, control_w, SIGN_POS, expa, expb); - break; - case 2: /* N - P */ - tag = FPU_u_add(a, b, dest, control_w, SIGN_NEG, expa, expb); - break; + if (flags & REV) { + signa ^= SIGN_NEG; + signb ^= SIGN_NEG; + } + + dest = &st(deststnr); + saved_sign = getsign(dest); + + if (!(taga | tagb)) { + expa = exponent(a); + expb = exponent(b); + + valid_subtract: + /* Both registers are valid */ + + diff = expa - expb; + + if (!diff) { + diff = a->sigh - b->sigh; /* Works only if ms bits are identical */ + if (!diff) { + diff = a->sigl > b->sigl; + if (!diff) + diff = -(a->sigl < b->sigl); + } + } + + switch ((((int)signa) * 2 + signb) / SIGN_NEG) { + case 0: /* P - P */ + case 3: /* N - N */ + if (diff > 0) { + /* |a| > |b| */ + tag = + FPU_u_sub(a, b, dest, control_w, signa, + expa, expb); + } else if (diff == 0) { + FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); + + /* sign depends upon rounding mode */ + setsign(dest, ((control_w & CW_RC) != RC_DOWN) + ? SIGN_POS : SIGN_NEG); + return TAG_Zero; + } else { + sign = signa ^ SIGN_NEG; + tag = + FPU_u_sub(b, a, dest, control_w, sign, expb, + expa); + } + break; + case 1: /* P - N */ + tag = + FPU_u_add(a, b, dest, control_w, SIGN_POS, expa, + expb); + break; + case 2: /* N - P */ + tag = + FPU_u_add(a, b, dest, control_w, SIGN_NEG, expa, + expb); + break; #ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL|0x111); - return -1; + default: + EXCEPTION(EX_INTERNAL | 0x111); + return -1; #endif + } + if (tag < 0) { + setsign(dest, saved_sign); + return tag; + } + FPU_settagi(deststnr, tag); + return tag; } - if ( tag < 0 ) - { - setsign(dest, saved_sign); - return tag; - } - FPU_settagi(deststnr, tag); - return tag; - } - if ( taga == TAG_Special ) - taga = FPU_Special(a); - if ( tagb == TAG_Special ) - tagb = FPU_Special(b); + if (taga == TAG_Special) + taga = FPU_Special(a); + if (tagb == TAG_Special) + tagb = FPU_Special(b); - if ( ((taga == TAG_Valid) && (tagb == TW_Denormal)) + if (((taga == TAG_Valid) && (tagb == TW_Denormal)) || ((taga == TW_Denormal) && (tagb == TAG_Valid)) - || ((taga == TW_Denormal) && (tagb == TW_Denormal)) ) - { - FPU_REG x, y; + || ((taga == TW_Denormal) && (tagb == TW_Denormal))) { + FPU_REG x, y; - if ( denormal_operand() < 0 ) - return FPU_Exception; + if (denormal_operand() < 0) + return FPU_Exception; - FPU_to_exp16(a, &x); - FPU_to_exp16(b, &y); - a = &x; - b = &y; - expa = exponent16(a); - expb = exponent16(b); + FPU_to_exp16(a, &x); + FPU_to_exp16(b, &y); + a = &x; + b = &y; + expa = exponent16(a); + expb = exponent16(b); - goto valid_subtract; - } - - if ( (taga == TW_NaN) || (tagb == TW_NaN) ) - { - FPU_REG const *d1, *d2; - if ( flags & REV ) - { - d1 = b; - d2 = a; + goto valid_subtract; } - else - { - d1 = a; - d2 = b; - } - if ( flags & LOADED ) - return real_2op_NaN(b, tagb, deststnr, d1); - if ( flags & DEST_RM ) - return real_2op_NaN(a, taga, deststnr, d2); - else - return real_2op_NaN(b, tagb, deststnr, d2); - } - return add_sub_specials(a, taga, signa, b, tagb, signb ^ SIGN_NEG, - dest, deststnr, control_w); + if ((taga == TW_NaN) || (tagb == TW_NaN)) { + FPU_REG const *d1, *d2; + if (flags & REV) { + d1 = b; + d2 = a; + } else { + d1 = a; + d2 = b; + } + if (flags & LOADED) + return real_2op_NaN(b, tagb, deststnr, d1); + if (flags & DEST_RM) + return real_2op_NaN(a, taga, deststnr, d2); + else + return real_2op_NaN(b, tagb, deststnr, d2); + } + + return add_sub_specials(a, taga, signa, b, tagb, signb ^ SIGN_NEG, + dest, deststnr, control_w); } - static int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa, FPU_REG const *b, u_char tagb, u_char signb, - FPU_REG *dest, int deststnr, int control_w) + FPU_REG * dest, int deststnr, int control_w) { - if ( ((taga == TW_Denormal) || (tagb == TW_Denormal)) - && (denormal_operand() < 0) ) - return FPU_Exception; + if (((taga == TW_Denormal) || (tagb == TW_Denormal)) + && (denormal_operand() < 0)) + return FPU_Exception; - if (taga == TAG_Zero) - { - if (tagb == TAG_Zero) - { - /* Both are zero, result will be zero. */ - u_char different_signs = signa ^ signb; + if (taga == TAG_Zero) { + if (tagb == TAG_Zero) { + /* Both are zero, result will be zero. */ + u_char different_signs = signa ^ signb; - FPU_copy_to_regi(a, TAG_Zero, deststnr); - if ( different_signs ) - { - /* Signs are different. */ - /* Sign of answer depends upon rounding mode. */ - setsign(dest, ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG); - } - else - setsign(dest, signa); /* signa may differ from the sign of a. */ - return TAG_Zero; + FPU_copy_to_regi(a, TAG_Zero, deststnr); + if (different_signs) { + /* Signs are different. */ + /* Sign of answer depends upon rounding mode. */ + setsign(dest, ((control_w & CW_RC) != RC_DOWN) + ? SIGN_POS : SIGN_NEG); + } else + setsign(dest, signa); /* signa may differ from the sign of a. */ + return TAG_Zero; + } else { + reg_copy(b, dest); + if ((tagb == TW_Denormal) && (b->sigh & 0x80000000)) { + /* A pseudoDenormal, convert it. */ + addexponent(dest, 1); + tagb = TAG_Valid; + } else if (tagb > TAG_Empty) + tagb = TAG_Special; + setsign(dest, signb); /* signb may differ from the sign of b. */ + FPU_settagi(deststnr, tagb); + return tagb; + } + } else if (tagb == TAG_Zero) { + reg_copy(a, dest); + if ((taga == TW_Denormal) && (a->sigh & 0x80000000)) { + /* A pseudoDenormal */ + addexponent(dest, 1); + taga = TAG_Valid; + } else if (taga > TAG_Empty) + taga = TAG_Special; + setsign(dest, signa); /* signa may differ from the sign of a. */ + FPU_settagi(deststnr, taga); + return taga; + } else if (taga == TW_Infinity) { + if ((tagb != TW_Infinity) || (signa == signb)) { + FPU_copy_to_regi(a, TAG_Special, deststnr); + setsign(dest, signa); /* signa may differ from the sign of a. */ + return taga; + } + /* Infinity-Infinity is undefined. */ + return arith_invalid(deststnr); + } else if (tagb == TW_Infinity) { + FPU_copy_to_regi(b, TAG_Special, deststnr); + setsign(dest, signb); /* signb may differ from the sign of b. */ + return tagb; } - else - { - reg_copy(b, dest); - if ( (tagb == TW_Denormal) && (b->sigh & 0x80000000) ) - { - /* A pseudoDenormal, convert it. */ - addexponent(dest, 1); - tagb = TAG_Valid; - } - else if ( tagb > TAG_Empty ) - tagb = TAG_Special; - setsign(dest, signb); /* signb may differ from the sign of b. */ - FPU_settagi(deststnr, tagb); - return tagb; - } - } - else if (tagb == TAG_Zero) - { - reg_copy(a, dest); - if ( (taga == TW_Denormal) && (a->sigh & 0x80000000) ) - { - /* A pseudoDenormal */ - addexponent(dest, 1); - taga = TAG_Valid; - } - else if ( taga > TAG_Empty ) - taga = TAG_Special; - setsign(dest, signa); /* signa may differ from the sign of a. */ - FPU_settagi(deststnr, taga); - return taga; - } - else if (taga == TW_Infinity) - { - if ( (tagb != TW_Infinity) || (signa == signb) ) - { - FPU_copy_to_regi(a, TAG_Special, deststnr); - setsign(dest, signa); /* signa may differ from the sign of a. */ - return taga; - } - /* Infinity-Infinity is undefined. */ - return arith_invalid(deststnr); - } - else if (tagb == TW_Infinity) - { - FPU_copy_to_regi(b, TAG_Special, deststnr); - setsign(dest, signb); /* signb may differ from the sign of b. */ - return tagb; - } - #ifdef PARANOID - EXCEPTION(EX_INTERNAL|0x101); + EXCEPTION(EX_INTERNAL | 0x101); #endif - return FPU_Exception; + return FPU_Exception; } - diff --git a/arch/x86/math-emu/reg_compare.c b/arch/x86/math-emu/reg_compare.c index f37c5b5a35ad..ecce55fc2e2e 100644 --- a/arch/x86/math-emu/reg_compare.c +++ b/arch/x86/math-emu/reg_compare.c @@ -20,362 +20,331 @@ #include "control_w.h" #include "status_w.h" - static int compare(FPU_REG const *b, int tagb) { - int diff, exp0, expb; - u_char st0_tag; - FPU_REG *st0_ptr; - FPU_REG x, y; - u_char st0_sign, signb = getsign(b); + int diff, exp0, expb; + u_char st0_tag; + FPU_REG *st0_ptr; + FPU_REG x, y; + u_char st0_sign, signb = getsign(b); - st0_ptr = &st(0); - st0_tag = FPU_gettag0(); - st0_sign = getsign(st0_ptr); + st0_ptr = &st(0); + st0_tag = FPU_gettag0(); + st0_sign = getsign(st0_ptr); - if ( tagb == TAG_Special ) - tagb = FPU_Special(b); - if ( st0_tag == TAG_Special ) - st0_tag = FPU_Special(st0_ptr); + if (tagb == TAG_Special) + tagb = FPU_Special(b); + if (st0_tag == TAG_Special) + st0_tag = FPU_Special(st0_ptr); - if ( ((st0_tag != TAG_Valid) && (st0_tag != TW_Denormal)) - || ((tagb != TAG_Valid) && (tagb != TW_Denormal)) ) - { - if ( st0_tag == TAG_Zero ) - { - if ( tagb == TAG_Zero ) return COMP_A_eq_B; - if ( tagb == TAG_Valid ) - return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B); - if ( tagb == TW_Denormal ) - return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B) - | COMP_Denormal; - } - else if ( tagb == TAG_Zero ) - { - if ( st0_tag == TAG_Valid ) - return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B); - if ( st0_tag == TW_Denormal ) - return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B) - | COMP_Denormal; + if (((st0_tag != TAG_Valid) && (st0_tag != TW_Denormal)) + || ((tagb != TAG_Valid) && (tagb != TW_Denormal))) { + if (st0_tag == TAG_Zero) { + if (tagb == TAG_Zero) + return COMP_A_eq_B; + if (tagb == TAG_Valid) + return ((signb == + SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B); + if (tagb == TW_Denormal) + return ((signb == + SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B) + | COMP_Denormal; + } else if (tagb == TAG_Zero) { + if (st0_tag == TAG_Valid) + return ((st0_sign == + SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B); + if (st0_tag == TW_Denormal) + return ((st0_sign == + SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B) + | COMP_Denormal; + } + + if (st0_tag == TW_Infinity) { + if ((tagb == TAG_Valid) || (tagb == TAG_Zero)) + return ((st0_sign == + SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B); + else if (tagb == TW_Denormal) + return ((st0_sign == + SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B) + | COMP_Denormal; + else if (tagb == TW_Infinity) { + /* The 80486 book says that infinities can be equal! */ + return (st0_sign == signb) ? COMP_A_eq_B : + ((st0_sign == + SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B); + } + /* Fall through to the NaN code */ + } else if (tagb == TW_Infinity) { + if ((st0_tag == TAG_Valid) || (st0_tag == TAG_Zero)) + return ((signb == + SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B); + if (st0_tag == TW_Denormal) + return ((signb == + SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B) + | COMP_Denormal; + /* Fall through to the NaN code */ + } + + /* The only possibility now should be that one of the arguments + is a NaN */ + if ((st0_tag == TW_NaN) || (tagb == TW_NaN)) { + int signalling = 0, unsupported = 0; + if (st0_tag == TW_NaN) { + signalling = + (st0_ptr->sigh & 0xc0000000) == 0x80000000; + unsupported = !((exponent(st0_ptr) == EXP_OVER) + && (st0_ptr-> + sigh & 0x80000000)); + } + if (tagb == TW_NaN) { + signalling |= + (b->sigh & 0xc0000000) == 0x80000000; + unsupported |= !((exponent(b) == EXP_OVER) + && (b->sigh & 0x80000000)); + } + if (signalling || unsupported) + return COMP_No_Comp | COMP_SNaN | COMP_NaN; + else + /* Neither is a signaling NaN */ + return COMP_No_Comp | COMP_NaN; + } + + EXCEPTION(EX_Invalid); } - if ( st0_tag == TW_Infinity ) - { - if ( (tagb == TAG_Valid) || (tagb == TAG_Zero) ) - return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B); - else if ( tagb == TW_Denormal ) - return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B) - | COMP_Denormal; - else if ( tagb == TW_Infinity ) - { - /* The 80486 book says that infinities can be equal! */ - return (st0_sign == signb) ? COMP_A_eq_B : - ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B); - } - /* Fall through to the NaN code */ - } - else if ( tagb == TW_Infinity ) - { - if ( (st0_tag == TAG_Valid) || (st0_tag == TAG_Zero) ) - return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B); - if ( st0_tag == TW_Denormal ) - return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B) - | COMP_Denormal; - /* Fall through to the NaN code */ + if (st0_sign != signb) { + return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B) + | (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ? + COMP_Denormal : 0); } - /* The only possibility now should be that one of the arguments - is a NaN */ - if ( (st0_tag == TW_NaN) || (tagb == TW_NaN) ) - { - int signalling = 0, unsupported = 0; - if ( st0_tag == TW_NaN ) - { - signalling = (st0_ptr->sigh & 0xc0000000) == 0x80000000; - unsupported = !((exponent(st0_ptr) == EXP_OVER) - && (st0_ptr->sigh & 0x80000000)); - } - if ( tagb == TW_NaN ) - { - signalling |= (b->sigh & 0xc0000000) == 0x80000000; - unsupported |= !((exponent(b) == EXP_OVER) - && (b->sigh & 0x80000000)); - } - if ( signalling || unsupported ) - return COMP_No_Comp | COMP_SNaN | COMP_NaN; - else - /* Neither is a signaling NaN */ - return COMP_No_Comp | COMP_NaN; + if ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) { + FPU_to_exp16(st0_ptr, &x); + FPU_to_exp16(b, &y); + st0_ptr = &x; + b = &y; + exp0 = exponent16(st0_ptr); + expb = exponent16(b); + } else { + exp0 = exponent(st0_ptr); + expb = exponent(b); } - - EXCEPTION(EX_Invalid); - } - - if (st0_sign != signb) - { - return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B) - | ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ? - COMP_Denormal : 0); - } - - if ( (st0_tag == TW_Denormal) || (tagb == TW_Denormal) ) - { - FPU_to_exp16(st0_ptr, &x); - FPU_to_exp16(b, &y); - st0_ptr = &x; - b = &y; - exp0 = exponent16(st0_ptr); - expb = exponent16(b); - } - else - { - exp0 = exponent(st0_ptr); - expb = exponent(b); - } #ifdef PARANOID - if (!(st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid); - if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid); + if (!(st0_ptr->sigh & 0x80000000)) + EXCEPTION(EX_Invalid); + if (!(b->sigh & 0x80000000)) + EXCEPTION(EX_Invalid); #endif /* PARANOID */ - diff = exp0 - expb; - if ( diff == 0 ) - { - diff = st0_ptr->sigh - b->sigh; /* Works only if ms bits are - identical */ - if ( diff == 0 ) - { - diff = st0_ptr->sigl > b->sigl; - if ( diff == 0 ) - diff = -(st0_ptr->sigl < b->sigl); + diff = exp0 - expb; + if (diff == 0) { + diff = st0_ptr->sigh - b->sigh; /* Works only if ms bits are + identical */ + if (diff == 0) { + diff = st0_ptr->sigl > b->sigl; + if (diff == 0) + diff = -(st0_ptr->sigl < b->sigl); + } } - } - if ( diff > 0 ) - { - return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B) - | ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ? - COMP_Denormal : 0); - } - if ( diff < 0 ) - { - return ((st0_sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B) - | ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ? - COMP_Denormal : 0); - } + if (diff > 0) { + return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B) + | (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ? + COMP_Denormal : 0); + } + if (diff < 0) { + return ((st0_sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B) + | (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ? + COMP_Denormal : 0); + } - return COMP_A_eq_B - | ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ? - COMP_Denormal : 0); + return COMP_A_eq_B + | (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ? + COMP_Denormal : 0); } - /* This function requires that st(0) is not empty */ int FPU_compare_st_data(FPU_REG const *loaded_data, u_char loaded_tag) { - int f = 0, c; + int f = 0, c; - c = compare(loaded_data, loaded_tag); + c = compare(loaded_data, loaded_tag); - if (c & COMP_NaN) - { - EXCEPTION(EX_Invalid); - f = SW_C3 | SW_C2 | SW_C0; - } - else - switch (c & 7) - { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; + if (c & COMP_NaN) { + EXCEPTION(EX_Invalid); + f = SW_C3 | SW_C2 | SW_C0; + } else + switch (c & 7) { + case COMP_A_lt_B: + f = SW_C0; + break; + case COMP_A_eq_B: + f = SW_C3; + break; + case COMP_A_gt_B: + f = 0; + break; + case COMP_No_Comp: + f = SW_C3 | SW_C2 | SW_C0; + break; #ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL|0x121); - f = SW_C3 | SW_C2 | SW_C0; - break; + default: + EXCEPTION(EX_INTERNAL | 0x121); + f = SW_C3 | SW_C2 | SW_C0; + break; #endif /* PARANOID */ - } - setcc(f); - if (c & COMP_Denormal) - { - return denormal_operand() < 0; - } - return 0; + } + setcc(f); + if (c & COMP_Denormal) { + return denormal_operand() < 0; + } + return 0; } - static int compare_st_st(int nr) { - int f = 0, c; - FPU_REG *st_ptr; + int f = 0, c; + FPU_REG *st_ptr; - if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) ) - { - setcc(SW_C3 | SW_C2 | SW_C0); - /* Stack fault */ - EXCEPTION(EX_StackUnder); - return !(control_word & CW_Invalid); - } + if (!NOT_EMPTY(0) || !NOT_EMPTY(nr)) { + setcc(SW_C3 | SW_C2 | SW_C0); + /* Stack fault */ + EXCEPTION(EX_StackUnder); + return !(control_word & CW_Invalid); + } - st_ptr = &st(nr); - c = compare(st_ptr, FPU_gettagi(nr)); - if (c & COMP_NaN) - { - setcc(SW_C3 | SW_C2 | SW_C0); - EXCEPTION(EX_Invalid); - return !(control_word & CW_Invalid); - } - else - switch (c & 7) - { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; + st_ptr = &st(nr); + c = compare(st_ptr, FPU_gettagi(nr)); + if (c & COMP_NaN) { + setcc(SW_C3 | SW_C2 | SW_C0); + EXCEPTION(EX_Invalid); + return !(control_word & CW_Invalid); + } else + switch (c & 7) { + case COMP_A_lt_B: + f = SW_C0; + break; + case COMP_A_eq_B: + f = SW_C3; + break; + case COMP_A_gt_B: + f = 0; + break; + case COMP_No_Comp: + f = SW_C3 | SW_C2 | SW_C0; + break; #ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL|0x122); - f = SW_C3 | SW_C2 | SW_C0; - break; + default: + EXCEPTION(EX_INTERNAL | 0x122); + f = SW_C3 | SW_C2 | SW_C0; + break; #endif /* PARANOID */ - } - setcc(f); - if (c & COMP_Denormal) - { - return denormal_operand() < 0; - } - return 0; + } + setcc(f); + if (c & COMP_Denormal) { + return denormal_operand() < 0; + } + return 0; } - static int compare_u_st_st(int nr) { - int f = 0, c; - FPU_REG *st_ptr; + int f = 0, c; + FPU_REG *st_ptr; - if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) ) - { - setcc(SW_C3 | SW_C2 | SW_C0); - /* Stack fault */ - EXCEPTION(EX_StackUnder); - return !(control_word & CW_Invalid); - } - - st_ptr = &st(nr); - c = compare(st_ptr, FPU_gettagi(nr)); - if (c & COMP_NaN) - { - setcc(SW_C3 | SW_C2 | SW_C0); - if (c & COMP_SNaN) /* This is the only difference between - un-ordered and ordinary comparisons */ - { - EXCEPTION(EX_Invalid); - return !(control_word & CW_Invalid); + if (!NOT_EMPTY(0) || !NOT_EMPTY(nr)) { + setcc(SW_C3 | SW_C2 | SW_C0); + /* Stack fault */ + EXCEPTION(EX_StackUnder); + return !(control_word & CW_Invalid); } - return 0; - } - else - switch (c & 7) - { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; + + st_ptr = &st(nr); + c = compare(st_ptr, FPU_gettagi(nr)); + if (c & COMP_NaN) { + setcc(SW_C3 | SW_C2 | SW_C0); + if (c & COMP_SNaN) { /* This is the only difference between + un-ordered and ordinary comparisons */ + EXCEPTION(EX_Invalid); + return !(control_word & CW_Invalid); + } + return 0; + } else + switch (c & 7) { + case COMP_A_lt_B: + f = SW_C0; + break; + case COMP_A_eq_B: + f = SW_C3; + break; + case COMP_A_gt_B: + f = 0; + break; + case COMP_No_Comp: + f = SW_C3 | SW_C2 | SW_C0; + break; #ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL|0x123); - f = SW_C3 | SW_C2 | SW_C0; - break; -#endif /* PARANOID */ - } - setcc(f); - if (c & COMP_Denormal) - { - return denormal_operand() < 0; - } - return 0; + default: + EXCEPTION(EX_INTERNAL | 0x123); + f = SW_C3 | SW_C2 | SW_C0; + break; +#endif /* PARANOID */ + } + setcc(f); + if (c & COMP_Denormal) { + return denormal_operand() < 0; + } + return 0; } /*---------------------------------------------------------------------------*/ void fcom_st(void) { - /* fcom st(i) */ - compare_st_st(FPU_rm); + /* fcom st(i) */ + compare_st_st(FPU_rm); } - void fcompst(void) { - /* fcomp st(i) */ - if ( !compare_st_st(FPU_rm) ) - FPU_pop(); + /* fcomp st(i) */ + if (!compare_st_st(FPU_rm)) + FPU_pop(); } - void fcompp(void) { - /* fcompp */ - if (FPU_rm != 1) - { - FPU_illegal(); - return; - } - if ( !compare_st_st(1) ) - poppop(); + /* fcompp */ + if (FPU_rm != 1) { + FPU_illegal(); + return; + } + if (!compare_st_st(1)) + poppop(); } - void fucom_(void) { - /* fucom st(i) */ - compare_u_st_st(FPU_rm); + /* fucom st(i) */ + compare_u_st_st(FPU_rm); } - void fucomp(void) { - /* fucomp st(i) */ - if ( !compare_u_st_st(FPU_rm) ) - FPU_pop(); + /* fucomp st(i) */ + if (!compare_u_st_st(FPU_rm)) + FPU_pop(); } - void fucompp(void) { - /* fucompp */ - if (FPU_rm == 1) - { - if ( !compare_u_st_st(1) ) - poppop(); - } - else - FPU_illegal(); + /* fucompp */ + if (FPU_rm == 1) { + if (!compare_u_st_st(1)) + poppop(); + } else + FPU_illegal(); } diff --git a/arch/x86/math-emu/reg_constant.c b/arch/x86/math-emu/reg_constant.c index a85015801969..04869e64b18e 100644 --- a/arch/x86/math-emu/reg_constant.c +++ b/arch/x86/math-emu/reg_constant.c @@ -16,29 +16,28 @@ #include "reg_constant.h" #include "control_w.h" - #define MAKE_REG(s,e,l,h) { l, h, \ ((EXTENDED_Ebias+(e)) | ((SIGN_##s != 0)*0x8000)) } -FPU_REG const CONST_1 = MAKE_REG(POS, 0, 0x00000000, 0x80000000); +FPU_REG const CONST_1 = MAKE_REG(POS, 0, 0x00000000, 0x80000000); #if 0 -FPU_REG const CONST_2 = MAKE_REG(POS, 1, 0x00000000, 0x80000000); +FPU_REG const CONST_2 = MAKE_REG(POS, 1, 0x00000000, 0x80000000); FPU_REG const CONST_HALF = MAKE_REG(POS, -1, 0x00000000, 0x80000000); -#endif /* 0 */ -static FPU_REG const CONST_L2T = MAKE_REG(POS, 1, 0xcd1b8afe, 0xd49a784b); -static FPU_REG const CONST_L2E = MAKE_REG(POS, 0, 0x5c17f0bc, 0xb8aa3b29); -FPU_REG const CONST_PI = MAKE_REG(POS, 1, 0x2168c235, 0xc90fdaa2); -FPU_REG const CONST_PI2 = MAKE_REG(POS, 0, 0x2168c235, 0xc90fdaa2); -FPU_REG const CONST_PI4 = MAKE_REG(POS, -1, 0x2168c235, 0xc90fdaa2); -static FPU_REG const CONST_LG2 = MAKE_REG(POS, -2, 0xfbcff799, 0x9a209a84); -static FPU_REG const CONST_LN2 = MAKE_REG(POS, -1, 0xd1cf79ac, 0xb17217f7); +#endif /* 0 */ +static FPU_REG const CONST_L2T = MAKE_REG(POS, 1, 0xcd1b8afe, 0xd49a784b); +static FPU_REG const CONST_L2E = MAKE_REG(POS, 0, 0x5c17f0bc, 0xb8aa3b29); +FPU_REG const CONST_PI = MAKE_REG(POS, 1, 0x2168c235, 0xc90fdaa2); +FPU_REG const CONST_PI2 = MAKE_REG(POS, 0, 0x2168c235, 0xc90fdaa2); +FPU_REG const CONST_PI4 = MAKE_REG(POS, -1, 0x2168c235, 0xc90fdaa2); +static FPU_REG const CONST_LG2 = MAKE_REG(POS, -2, 0xfbcff799, 0x9a209a84); +static FPU_REG const CONST_LN2 = MAKE_REG(POS, -1, 0xd1cf79ac, 0xb17217f7); /* Extra bits to take pi/2 to more than 128 bits precision. */ FPU_REG const CONST_PI2extra = MAKE_REG(NEG, -66, - 0xfc8f8cbb, 0xece675d1); + 0xfc8f8cbb, 0xece675d1); /* Only the sign (and tag) is used in internal zeroes */ -FPU_REG const CONST_Z = MAKE_REG(POS, EXP_UNDER, 0x0, 0x0); +FPU_REG const CONST_Z = MAKE_REG(POS, EXP_UNDER, 0x0, 0x0); /* Only the sign and significand (and tag) are used in internal NaNs */ /* The 80486 never generates one of these @@ -48,24 +47,22 @@ FPU_REG const CONST_SNAN = MAKE_REG(POS, EXP_OVER, 0x00000001, 0x80000000); FPU_REG const CONST_QNaN = MAKE_REG(NEG, EXP_OVER, 0x00000000, 0xC0000000); /* Only the sign (and tag) is used in internal infinities */ -FPU_REG const CONST_INF = MAKE_REG(POS, EXP_OVER, 0x00000000, 0x80000000); - +FPU_REG const CONST_INF = MAKE_REG(POS, EXP_OVER, 0x00000000, 0x80000000); static void fld_const(FPU_REG const *c, int adj, u_char tag) { - FPU_REG *st_new_ptr; + FPU_REG *st_new_ptr; - if ( STACK_OVERFLOW ) - { - FPU_stack_overflow(); - return; - } - push(); - reg_copy(c, st_new_ptr); - st_new_ptr->sigl += adj; /* For all our fldxxx constants, we don't need to - borrow or carry. */ - FPU_settag0(tag); - clear_C1(); + if (STACK_OVERFLOW) { + FPU_stack_overflow(); + return; + } + push(); + reg_copy(c, st_new_ptr); + st_new_ptr->sigl += adj; /* For all our fldxxx constants, we don't need to + borrow or carry. */ + FPU_settag0(tag); + clear_C1(); } /* A fast way to find out whether x is one of RC_DOWN or RC_CHOP @@ -75,46 +72,46 @@ static void fld_const(FPU_REG const *c, int adj, u_char tag) static void fld1(int rc) { - fld_const(&CONST_1, 0, TAG_Valid); + fld_const(&CONST_1, 0, TAG_Valid); } static void fldl2t(int rc) { - fld_const(&CONST_L2T, (rc == RC_UP) ? 1 : 0, TAG_Valid); + fld_const(&CONST_L2T, (rc == RC_UP) ? 1 : 0, TAG_Valid); } static void fldl2e(int rc) { - fld_const(&CONST_L2E, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); + fld_const(&CONST_L2E, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); } static void fldpi(int rc) { - fld_const(&CONST_PI, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); + fld_const(&CONST_PI, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); } static void fldlg2(int rc) { - fld_const(&CONST_LG2, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); + fld_const(&CONST_LG2, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); } static void fldln2(int rc) { - fld_const(&CONST_LN2, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); + fld_const(&CONST_LN2, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid); } static void fldz(int rc) { - fld_const(&CONST_Z, 0, TAG_Zero); + fld_const(&CONST_Z, 0, TAG_Zero); } -typedef void (*FUNC_RC)(int); +typedef void (*FUNC_RC) (int); static FUNC_RC constants_table[] = { - fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, (FUNC_RC)FPU_illegal + fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, (FUNC_RC) FPU_illegal }; void fconst(void) { - (constants_table[FPU_rm])(control_word & CW_RC); + (constants_table[FPU_rm]) (control_word & CW_RC); } diff --git a/arch/x86/math-emu/reg_convert.c b/arch/x86/math-emu/reg_convert.c index 45a258752703..afd31b31000d 100644 --- a/arch/x86/math-emu/reg_convert.c +++ b/arch/x86/math-emu/reg_convert.c @@ -13,41 +13,34 @@ #include "exception.h" #include "fpu_emu.h" - -int FPU_to_exp16(FPU_REG const *a, FPU_REG *x) +int FPU_to_exp16(FPU_REG const *a, FPU_REG * x) { - int sign = getsign(a); + int sign = getsign(a); - *(long long *)&(x->sigl) = *(const long long *)&(a->sigl); + *(long long *)&(x->sigl) = *(const long long *)&(a->sigl); - /* Set up the exponent as a 16 bit quantity. */ - setexponent16(x, exponent(a)); + /* Set up the exponent as a 16 bit quantity. */ + setexponent16(x, exponent(a)); - if ( exponent16(x) == EXP_UNDER ) - { - /* The number is a de-normal or pseudodenormal. */ - /* We only deal with the significand and exponent. */ + if (exponent16(x) == EXP_UNDER) { + /* The number is a de-normal or pseudodenormal. */ + /* We only deal with the significand and exponent. */ - if (x->sigh & 0x80000000) - { - /* Is a pseudodenormal. */ - /* This is non-80486 behaviour because the number - loses its 'denormal' identity. */ - addexponent(x, 1); + if (x->sigh & 0x80000000) { + /* Is a pseudodenormal. */ + /* This is non-80486 behaviour because the number + loses its 'denormal' identity. */ + addexponent(x, 1); + } else { + /* Is a denormal. */ + addexponent(x, 1); + FPU_normalize_nuo(x); + } } - else - { - /* Is a denormal. */ - addexponent(x, 1); - FPU_normalize_nuo(x); + + if (!(x->sigh & 0x80000000)) { + EXCEPTION(EX_INTERNAL | 0x180); } - } - if ( !(x->sigh & 0x80000000) ) - { - EXCEPTION(EX_INTERNAL | 0x180); - } - - return sign; + return sign; } - diff --git a/arch/x86/math-emu/reg_divide.c b/arch/x86/math-emu/reg_divide.c index 5cee7ff920d9..6827012db341 100644 --- a/arch/x86/math-emu/reg_divide.c +++ b/arch/x86/math-emu/reg_divide.c @@ -26,182 +26,157 @@ */ int FPU_div(int flags, int rm, int control_w) { - FPU_REG x, y; - FPU_REG const *a, *b, *st0_ptr, *st_ptr; - FPU_REG *dest; - u_char taga, tagb, signa, signb, sign, saved_sign; - int tag, deststnr; + FPU_REG x, y; + FPU_REG const *a, *b, *st0_ptr, *st_ptr; + FPU_REG *dest; + u_char taga, tagb, signa, signb, sign, saved_sign; + int tag, deststnr; - if ( flags & DEST_RM ) - deststnr = rm; - else - deststnr = 0; + if (flags & DEST_RM) + deststnr = rm; + else + deststnr = 0; - if ( flags & REV ) - { - b = &st(0); - st0_ptr = b; - tagb = FPU_gettag0(); - if ( flags & LOADED ) - { - a = (FPU_REG *)rm; - taga = flags & 0x0f; + if (flags & REV) { + b = &st(0); + st0_ptr = b; + tagb = FPU_gettag0(); + if (flags & LOADED) { + a = (FPU_REG *) rm; + taga = flags & 0x0f; + } else { + a = &st(rm); + st_ptr = a; + taga = FPU_gettagi(rm); + } + } else { + a = &st(0); + st0_ptr = a; + taga = FPU_gettag0(); + if (flags & LOADED) { + b = (FPU_REG *) rm; + tagb = flags & 0x0f; + } else { + b = &st(rm); + st_ptr = b; + tagb = FPU_gettagi(rm); + } } - else - { - a = &st(rm); - st_ptr = a; - taga = FPU_gettagi(rm); + + signa = getsign(a); + signb = getsign(b); + + sign = signa ^ signb; + + dest = &st(deststnr); + saved_sign = getsign(dest); + + if (!(taga | tagb)) { + /* Both regs Valid, this should be the most common case. */ + reg_copy(a, &x); + reg_copy(b, &y); + setpositive(&x); + setpositive(&y); + tag = FPU_u_div(&x, &y, dest, control_w, sign); + + if (tag < 0) + return tag; + + FPU_settagi(deststnr, tag); + return tag; } - } - else - { - a = &st(0); - st0_ptr = a; - taga = FPU_gettag0(); - if ( flags & LOADED ) - { - b = (FPU_REG *)rm; - tagb = flags & 0x0f; - } - else - { - b = &st(rm); - st_ptr = b; - tagb = FPU_gettagi(rm); - } - } - signa = getsign(a); - signb = getsign(b); + if (taga == TAG_Special) + taga = FPU_Special(a); + if (tagb == TAG_Special) + tagb = FPU_Special(b); - sign = signa ^ signb; - - dest = &st(deststnr); - saved_sign = getsign(dest); - - if ( !(taga | tagb) ) - { - /* Both regs Valid, this should be the most common case. */ - reg_copy(a, &x); - reg_copy(b, &y); - setpositive(&x); - setpositive(&y); - tag = FPU_u_div(&x, &y, dest, control_w, sign); - - if ( tag < 0 ) - return tag; - - FPU_settagi(deststnr, tag); - return tag; - } - - if ( taga == TAG_Special ) - taga = FPU_Special(a); - if ( tagb == TAG_Special ) - tagb = FPU_Special(b); - - if ( ((taga == TAG_Valid) && (tagb == TW_Denormal)) + if (((taga == TAG_Valid) && (tagb == TW_Denormal)) || ((taga == TW_Denormal) && (tagb == TAG_Valid)) - || ((taga == TW_Denormal) && (tagb == TW_Denormal)) ) - { - if ( denormal_operand() < 0 ) - return FPU_Exception; + || ((taga == TW_Denormal) && (tagb == TW_Denormal))) { + if (denormal_operand() < 0) + return FPU_Exception; - FPU_to_exp16(a, &x); - FPU_to_exp16(b, &y); - tag = FPU_u_div(&x, &y, dest, control_w, sign); - if ( tag < 0 ) - return tag; + FPU_to_exp16(a, &x); + FPU_to_exp16(b, &y); + tag = FPU_u_div(&x, &y, dest, control_w, sign); + if (tag < 0) + return tag; - FPU_settagi(deststnr, tag); - return tag; - } - else if ( (taga <= TW_Denormal) && (tagb <= TW_Denormal) ) - { - if ( tagb != TAG_Zero ) - { - /* Want to find Zero/Valid */ - if ( tagb == TW_Denormal ) - { - if ( denormal_operand() < 0 ) - return FPU_Exception; - } + FPU_settagi(deststnr, tag); + return tag; + } else if ((taga <= TW_Denormal) && (tagb <= TW_Denormal)) { + if (tagb != TAG_Zero) { + /* Want to find Zero/Valid */ + if (tagb == TW_Denormal) { + if (denormal_operand() < 0) + return FPU_Exception; + } - /* The result is zero. */ - FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); - setsign(dest, sign); - return TAG_Zero; + /* The result is zero. */ + FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); + setsign(dest, sign); + return TAG_Zero; + } + /* We have an exception condition, either 0/0 or Valid/Zero. */ + if (taga == TAG_Zero) { + /* 0/0 */ + return arith_invalid(deststnr); + } + /* Valid/Zero */ + return FPU_divide_by_zero(deststnr, sign); } - /* We have an exception condition, either 0/0 or Valid/Zero. */ - if ( taga == TAG_Zero ) - { - /* 0/0 */ - return arith_invalid(deststnr); - } - /* Valid/Zero */ - return FPU_divide_by_zero(deststnr, sign); - } - /* Must have infinities, NaNs, etc */ - else if ( (taga == TW_NaN) || (tagb == TW_NaN) ) - { - if ( flags & LOADED ) - return real_2op_NaN((FPU_REG *)rm, flags & 0x0f, 0, st0_ptr); + /* Must have infinities, NaNs, etc */ + else if ((taga == TW_NaN) || (tagb == TW_NaN)) { + if (flags & LOADED) + return real_2op_NaN((FPU_REG *) rm, flags & 0x0f, 0, + st0_ptr); - if ( flags & DEST_RM ) - { - int tag; - tag = FPU_gettag0(); - if ( tag == TAG_Special ) - tag = FPU_Special(st0_ptr); - return real_2op_NaN(st0_ptr, tag, rm, (flags & REV) ? st0_ptr : &st(rm)); - } - else - { - int tag; - tag = FPU_gettagi(rm); - if ( tag == TAG_Special ) - tag = FPU_Special(&st(rm)); - return real_2op_NaN(&st(rm), tag, 0, (flags & REV) ? st0_ptr : &st(rm)); - } - } - else if (taga == TW_Infinity) - { - if (tagb == TW_Infinity) - { - /* infinity/infinity */ - return arith_invalid(deststnr); - } - else - { - /* tagb must be Valid or Zero */ - if ( (tagb == TW_Denormal) && (denormal_operand() < 0) ) - return FPU_Exception; - - /* Infinity divided by Zero or Valid does - not raise and exception, but returns Infinity */ - FPU_copy_to_regi(a, TAG_Special, deststnr); - setsign(dest, sign); - return taga; - } - } - else if (tagb == TW_Infinity) - { - if ( (taga == TW_Denormal) && (denormal_operand() < 0) ) - return FPU_Exception; + if (flags & DEST_RM) { + int tag; + tag = FPU_gettag0(); + if (tag == TAG_Special) + tag = FPU_Special(st0_ptr); + return real_2op_NaN(st0_ptr, tag, rm, + (flags & REV) ? st0_ptr : &st(rm)); + } else { + int tag; + tag = FPU_gettagi(rm); + if (tag == TAG_Special) + tag = FPU_Special(&st(rm)); + return real_2op_NaN(&st(rm), tag, 0, + (flags & REV) ? st0_ptr : &st(rm)); + } + } else if (taga == TW_Infinity) { + if (tagb == TW_Infinity) { + /* infinity/infinity */ + return arith_invalid(deststnr); + } else { + /* tagb must be Valid or Zero */ + if ((tagb == TW_Denormal) && (denormal_operand() < 0)) + return FPU_Exception; - /* The result is zero. */ - FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); - setsign(dest, sign); - return TAG_Zero; - } + /* Infinity divided by Zero or Valid does + not raise and exception, but returns Infinity */ + FPU_copy_to_regi(a, TAG_Special, deststnr); + setsign(dest, sign); + return taga; + } + } else if (tagb == TW_Infinity) { + if ((taga == TW_Denormal) && (denormal_operand() < 0)) + return FPU_Exception; + + /* The result is zero. */ + FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); + setsign(dest, sign); + return TAG_Zero; + } #ifdef PARANOID - else - { - EXCEPTION(EX_INTERNAL|0x102); - return FPU_Exception; - } -#endif /* PARANOID */ + else { + EXCEPTION(EX_INTERNAL | 0x102); + return FPU_Exception; + } +#endif /* PARANOID */ return 0; } diff --git a/arch/x86/math-emu/reg_ld_str.c b/arch/x86/math-emu/reg_ld_str.c index e976caef6498..0b2ca8dc2988 100644 --- a/arch/x86/math-emu/reg_ld_str.c +++ b/arch/x86/math-emu/reg_ld_str.c @@ -27,1084 +27,938 @@ #include "control_w.h" #include "status_w.h" - -#define DOUBLE_Emax 1023 /* largest valid exponent */ +#define DOUBLE_Emax 1023 /* largest valid exponent */ #define DOUBLE_Ebias 1023 -#define DOUBLE_Emin (-1022) /* smallest valid exponent */ +#define DOUBLE_Emin (-1022) /* smallest valid exponent */ -#define SINGLE_Emax 127 /* largest valid exponent */ +#define SINGLE_Emax 127 /* largest valid exponent */ #define SINGLE_Ebias 127 -#define SINGLE_Emin (-126) /* smallest valid exponent */ +#define SINGLE_Emin (-126) /* smallest valid exponent */ - -static u_char normalize_no_excep(FPU_REG *r, int exp, int sign) +static u_char normalize_no_excep(FPU_REG * r, int exp, int sign) { - u_char tag; + u_char tag; - setexponent16(r, exp); + setexponent16(r, exp); - tag = FPU_normalize_nuo(r); - stdexp(r); - if ( sign ) - setnegative(r); + tag = FPU_normalize_nuo(r); + stdexp(r); + if (sign) + setnegative(r); - return tag; + return tag; } - -int FPU_tagof(FPU_REG *ptr) +int FPU_tagof(FPU_REG * ptr) { - int exp; + int exp; - exp = exponent16(ptr) & 0x7fff; - if ( exp == 0 ) - { - if ( !(ptr->sigh | ptr->sigl) ) - { - return TAG_Zero; + exp = exponent16(ptr) & 0x7fff; + if (exp == 0) { + if (!(ptr->sigh | ptr->sigl)) { + return TAG_Zero; + } + /* The number is a de-normal or pseudodenormal. */ + return TAG_Special; } - /* The number is a de-normal or pseudodenormal. */ - return TAG_Special; - } - if ( exp == 0x7fff ) - { - /* Is an Infinity, a NaN, or an unsupported data type. */ - return TAG_Special; - } + if (exp == 0x7fff) { + /* Is an Infinity, a NaN, or an unsupported data type. */ + return TAG_Special; + } - if ( !(ptr->sigh & 0x80000000) ) - { - /* Unsupported data type. */ - /* Valid numbers have the ms bit set to 1. */ - /* Unnormal. */ - return TAG_Special; - } + if (!(ptr->sigh & 0x80000000)) { + /* Unsupported data type. */ + /* Valid numbers have the ms bit set to 1. */ + /* Unnormal. */ + return TAG_Special; + } - return TAG_Valid; + return TAG_Valid; } - /* Get a long double from user memory */ -int FPU_load_extended(long double __user *s, int stnr) +int FPU_load_extended(long double __user * s, int stnr) { - FPU_REG *sti_ptr = &st(stnr); + FPU_REG *sti_ptr = &st(stnr); - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ, s, 10); - __copy_from_user(sti_ptr, s, 10); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, s, 10); + __copy_from_user(sti_ptr, s, 10); + RE_ENTRANT_CHECK_ON; - return FPU_tagof(sti_ptr); + return FPU_tagof(sti_ptr); } - /* Get a double from user memory */ -int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data) +int FPU_load_double(double __user * dfloat, FPU_REG * loaded_data) { - int exp, tag, negative; - unsigned m64, l64; + int exp, tag, negative; + unsigned m64, l64; - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ, dfloat, 8); - FPU_get_user(m64, 1 + (unsigned long __user *) dfloat); - FPU_get_user(l64, (unsigned long __user *) dfloat); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, dfloat, 8); + FPU_get_user(m64, 1 + (unsigned long __user *)dfloat); + FPU_get_user(l64, (unsigned long __user *)dfloat); + RE_ENTRANT_CHECK_ON; - negative = (m64 & 0x80000000) ? SIGN_Negative : SIGN_Positive; - exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias + EXTENDED_Ebias; - m64 &= 0xfffff; - if ( exp > DOUBLE_Emax + EXTENDED_Ebias ) - { - /* Infinity or NaN */ - if ((m64 == 0) && (l64 == 0)) - { - /* +- infinity */ - loaded_data->sigh = 0x80000000; - loaded_data->sigl = 0x00000000; - exp = EXP_Infinity + EXTENDED_Ebias; - tag = TAG_Special; + negative = (m64 & 0x80000000) ? SIGN_Negative : SIGN_Positive; + exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias + EXTENDED_Ebias; + m64 &= 0xfffff; + if (exp > DOUBLE_Emax + EXTENDED_Ebias) { + /* Infinity or NaN */ + if ((m64 == 0) && (l64 == 0)) { + /* +- infinity */ + loaded_data->sigh = 0x80000000; + loaded_data->sigl = 0x00000000; + exp = EXP_Infinity + EXTENDED_Ebias; + tag = TAG_Special; + } else { + /* Must be a signaling or quiet NaN */ + exp = EXP_NaN + EXTENDED_Ebias; + loaded_data->sigh = (m64 << 11) | 0x80000000; + loaded_data->sigh |= l64 >> 21; + loaded_data->sigl = l64 << 11; + tag = TAG_Special; /* The calling function must look for NaNs */ + } + } else if (exp < DOUBLE_Emin + EXTENDED_Ebias) { + /* Zero or de-normal */ + if ((m64 == 0) && (l64 == 0)) { + /* Zero */ + reg_copy(&CONST_Z, loaded_data); + exp = 0; + tag = TAG_Zero; + } else { + /* De-normal */ + loaded_data->sigh = m64 << 11; + loaded_data->sigh |= l64 >> 21; + loaded_data->sigl = l64 << 11; + + return normalize_no_excep(loaded_data, DOUBLE_Emin, + negative) + | (denormal_operand() < 0 ? FPU_Exception : 0); + } + } else { + loaded_data->sigh = (m64 << 11) | 0x80000000; + loaded_data->sigh |= l64 >> 21; + loaded_data->sigl = l64 << 11; + + tag = TAG_Valid; } - else - { - /* Must be a signaling or quiet NaN */ - exp = EXP_NaN + EXTENDED_Ebias; - loaded_data->sigh = (m64 << 11) | 0x80000000; - loaded_data->sigh |= l64 >> 21; - loaded_data->sigl = l64 << 11; - tag = TAG_Special; /* The calling function must look for NaNs */ - } - } - else if ( exp < DOUBLE_Emin + EXTENDED_Ebias ) - { - /* Zero or de-normal */ - if ((m64 == 0) && (l64 == 0)) - { - /* Zero */ - reg_copy(&CONST_Z, loaded_data); - exp = 0; - tag = TAG_Zero; - } - else - { - /* De-normal */ - loaded_data->sigh = m64 << 11; - loaded_data->sigh |= l64 >> 21; - loaded_data->sigl = l64 << 11; - return normalize_no_excep(loaded_data, DOUBLE_Emin, negative) - | (denormal_operand() < 0 ? FPU_Exception : 0); - } - } - else - { - loaded_data->sigh = (m64 << 11) | 0x80000000; - loaded_data->sigh |= l64 >> 21; - loaded_data->sigl = l64 << 11; + setexponent16(loaded_data, exp | negative); - tag = TAG_Valid; - } - - setexponent16(loaded_data, exp | negative); - - return tag; + return tag; } - /* Get a float from user memory */ -int FPU_load_single(float __user *single, FPU_REG *loaded_data) +int FPU_load_single(float __user * single, FPU_REG * loaded_data) { - unsigned m32; - int exp, tag, negative; + unsigned m32; + int exp, tag, negative; - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ, single, 4); - FPU_get_user(m32, (unsigned long __user *) single); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, single, 4); + FPU_get_user(m32, (unsigned long __user *)single); + RE_ENTRANT_CHECK_ON; - negative = (m32 & 0x80000000) ? SIGN_Negative : SIGN_Positive; + negative = (m32 & 0x80000000) ? SIGN_Negative : SIGN_Positive; - if (!(m32 & 0x7fffffff)) - { - /* Zero */ - reg_copy(&CONST_Z, loaded_data); - addexponent(loaded_data, negative); - return TAG_Zero; - } - exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias + EXTENDED_Ebias; - m32 = (m32 & 0x7fffff) << 8; - if ( exp < SINGLE_Emin + EXTENDED_Ebias ) - { - /* De-normals */ - loaded_data->sigh = m32; - loaded_data->sigl = 0; - - return normalize_no_excep(loaded_data, SINGLE_Emin, negative) - | (denormal_operand() < 0 ? FPU_Exception : 0); - } - else if ( exp > SINGLE_Emax + EXTENDED_Ebias ) - { - /* Infinity or NaN */ - if ( m32 == 0 ) - { - /* +- infinity */ - loaded_data->sigh = 0x80000000; - loaded_data->sigl = 0x00000000; - exp = EXP_Infinity + EXTENDED_Ebias; - tag = TAG_Special; + if (!(m32 & 0x7fffffff)) { + /* Zero */ + reg_copy(&CONST_Z, loaded_data); + addexponent(loaded_data, negative); + return TAG_Zero; } - else - { - /* Must be a signaling or quiet NaN */ - exp = EXP_NaN + EXTENDED_Ebias; - loaded_data->sigh = m32 | 0x80000000; - loaded_data->sigl = 0; - tag = TAG_Special; /* The calling function must look for NaNs */ + exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias + EXTENDED_Ebias; + m32 = (m32 & 0x7fffff) << 8; + if (exp < SINGLE_Emin + EXTENDED_Ebias) { + /* De-normals */ + loaded_data->sigh = m32; + loaded_data->sigl = 0; + + return normalize_no_excep(loaded_data, SINGLE_Emin, negative) + | (denormal_operand() < 0 ? FPU_Exception : 0); + } else if (exp > SINGLE_Emax + EXTENDED_Ebias) { + /* Infinity or NaN */ + if (m32 == 0) { + /* +- infinity */ + loaded_data->sigh = 0x80000000; + loaded_data->sigl = 0x00000000; + exp = EXP_Infinity + EXTENDED_Ebias; + tag = TAG_Special; + } else { + /* Must be a signaling or quiet NaN */ + exp = EXP_NaN + EXTENDED_Ebias; + loaded_data->sigh = m32 | 0x80000000; + loaded_data->sigl = 0; + tag = TAG_Special; /* The calling function must look for NaNs */ + } + } else { + loaded_data->sigh = m32 | 0x80000000; + loaded_data->sigl = 0; + tag = TAG_Valid; } - } - else - { - loaded_data->sigh = m32 | 0x80000000; - loaded_data->sigl = 0; - tag = TAG_Valid; - } - setexponent16(loaded_data, exp | negative); /* Set the sign. */ + setexponent16(loaded_data, exp | negative); /* Set the sign. */ - return tag; + return tag; } - /* Get a long long from user memory */ -int FPU_load_int64(long long __user *_s) +int FPU_load_int64(long long __user * _s) { - long long s; - int sign; - FPU_REG *st0_ptr = &st(0); + long long s; + int sign; + FPU_REG *st0_ptr = &st(0); - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ, _s, 8); - if (copy_from_user(&s,_s,8)) - FPU_abort; - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, _s, 8); + if (copy_from_user(&s, _s, 8)) + FPU_abort; + RE_ENTRANT_CHECK_ON; - if (s == 0) - { - reg_copy(&CONST_Z, st0_ptr); - return TAG_Zero; - } + if (s == 0) { + reg_copy(&CONST_Z, st0_ptr); + return TAG_Zero; + } - if (s > 0) - sign = SIGN_Positive; - else - { - s = -s; - sign = SIGN_Negative; - } + if (s > 0) + sign = SIGN_Positive; + else { + s = -s; + sign = SIGN_Negative; + } - significand(st0_ptr) = s; + significand(st0_ptr) = s; - return normalize_no_excep(st0_ptr, 63, sign); + return normalize_no_excep(st0_ptr, 63, sign); } - /* Get a long from user memory */ -int FPU_load_int32(long __user *_s, FPU_REG *loaded_data) +int FPU_load_int32(long __user * _s, FPU_REG * loaded_data) { - long s; - int negative; + long s; + int negative; - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ, _s, 4); - FPU_get_user(s, _s); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, _s, 4); + FPU_get_user(s, _s); + RE_ENTRANT_CHECK_ON; - if (s == 0) - { reg_copy(&CONST_Z, loaded_data); return TAG_Zero; } + if (s == 0) { + reg_copy(&CONST_Z, loaded_data); + return TAG_Zero; + } - if (s > 0) - negative = SIGN_Positive; - else - { - s = -s; - negative = SIGN_Negative; - } + if (s > 0) + negative = SIGN_Positive; + else { + s = -s; + negative = SIGN_Negative; + } - loaded_data->sigh = s; - loaded_data->sigl = 0; + loaded_data->sigh = s; + loaded_data->sigl = 0; - return normalize_no_excep(loaded_data, 31, negative); + return normalize_no_excep(loaded_data, 31, negative); } - /* Get a short from user memory */ -int FPU_load_int16(short __user *_s, FPU_REG *loaded_data) +int FPU_load_int16(short __user * _s, FPU_REG * loaded_data) { - int s, negative; + int s, negative; - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ, _s, 2); - /* Cast as short to get the sign extended. */ - FPU_get_user(s, _s); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, _s, 2); + /* Cast as short to get the sign extended. */ + FPU_get_user(s, _s); + RE_ENTRANT_CHECK_ON; - if (s == 0) - { reg_copy(&CONST_Z, loaded_data); return TAG_Zero; } + if (s == 0) { + reg_copy(&CONST_Z, loaded_data); + return TAG_Zero; + } - if (s > 0) - negative = SIGN_Positive; - else - { - s = -s; - negative = SIGN_Negative; - } + if (s > 0) + negative = SIGN_Positive; + else { + s = -s; + negative = SIGN_Negative; + } - loaded_data->sigh = s << 16; - loaded_data->sigl = 0; + loaded_data->sigh = s << 16; + loaded_data->sigl = 0; - return normalize_no_excep(loaded_data, 15, negative); + return normalize_no_excep(loaded_data, 15, negative); } - /* Get a packed bcd array from user memory */ -int FPU_load_bcd(u_char __user *s) +int FPU_load_bcd(u_char __user * s) { - FPU_REG *st0_ptr = &st(0); - int pos; - u_char bcd; - long long l=0; - int sign; + FPU_REG *st0_ptr = &st(0); + int pos; + u_char bcd; + long long l = 0; + int sign; - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ, s, 10); - RE_ENTRANT_CHECK_ON; - for ( pos = 8; pos >= 0; pos--) - { - l *= 10; - RE_ENTRANT_CHECK_OFF; - FPU_get_user(bcd, s+pos); - RE_ENTRANT_CHECK_ON; - l += bcd >> 4; - l *= 10; - l += bcd & 0x0f; - } - - RE_ENTRANT_CHECK_OFF; - FPU_get_user(sign, s+9); - sign = sign & 0x80 ? SIGN_Negative : SIGN_Positive; - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, s, 10); + RE_ENTRANT_CHECK_ON; + for (pos = 8; pos >= 0; pos--) { + l *= 10; + RE_ENTRANT_CHECK_OFF; + FPU_get_user(bcd, s + pos); + RE_ENTRANT_CHECK_ON; + l += bcd >> 4; + l *= 10; + l += bcd & 0x0f; + } - if ( l == 0 ) - { - reg_copy(&CONST_Z, st0_ptr); - addexponent(st0_ptr, sign); /* Set the sign. */ - return TAG_Zero; - } - else - { - significand(st0_ptr) = l; - return normalize_no_excep(st0_ptr, 63, sign); - } + RE_ENTRANT_CHECK_OFF; + FPU_get_user(sign, s + 9); + sign = sign & 0x80 ? SIGN_Negative : SIGN_Positive; + RE_ENTRANT_CHECK_ON; + + if (l == 0) { + reg_copy(&CONST_Z, st0_ptr); + addexponent(st0_ptr, sign); /* Set the sign. */ + return TAG_Zero; + } else { + significand(st0_ptr) = l; + return normalize_no_excep(st0_ptr, 63, sign); + } } /*===========================================================================*/ /* Put a long double into user memory */ -int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double __user *d) +int FPU_store_extended(FPU_REG * st0_ptr, u_char st0_tag, + long double __user * d) { - /* - The only exception raised by an attempt to store to an - extended format is the Invalid Stack exception, i.e. - attempting to store from an empty register. - */ + /* + The only exception raised by an attempt to store to an + extended format is the Invalid Stack exception, i.e. + attempting to store from an empty register. + */ - if ( st0_tag != TAG_Empty ) - { - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE, d, 10); + if (st0_tag != TAG_Empty) { + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, d, 10); - FPU_put_user(st0_ptr->sigl, (unsigned long __user *) d); - FPU_put_user(st0_ptr->sigh, (unsigned long __user *) ((u_char __user *)d + 4)); - FPU_put_user(exponent16(st0_ptr), (unsigned short __user *) ((u_char __user *)d + 8)); - RE_ENTRANT_CHECK_ON; + FPU_put_user(st0_ptr->sigl, (unsigned long __user *)d); + FPU_put_user(st0_ptr->sigh, + (unsigned long __user *)((u_char __user *) d + 4)); + FPU_put_user(exponent16(st0_ptr), + (unsigned short __user *)((u_char __user *) d + + 8)); + RE_ENTRANT_CHECK_ON; - return 1; - } + return 1; + } - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if ( control_word & CW_Invalid ) - { - /* The masked response */ - /* Put out the QNaN indefinite */ - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,d,10); - FPU_put_user(0, (unsigned long __user *) d); - FPU_put_user(0xc0000000, 1 + (unsigned long __user *) d); - FPU_put_user(0xffff, 4 + (short __user *) d); - RE_ENTRANT_CHECK_ON; - return 1; - } - else - return 0; + /* Empty register (stack underflow) */ + EXCEPTION(EX_StackUnder); + if (control_word & CW_Invalid) { + /* The masked response */ + /* Put out the QNaN indefinite */ + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, d, 10); + FPU_put_user(0, (unsigned long __user *)d); + FPU_put_user(0xc0000000, 1 + (unsigned long __user *)d); + FPU_put_user(0xffff, 4 + (short __user *)d); + RE_ENTRANT_CHECK_ON; + return 1; + } else + return 0; } - /* Put a double into user memory */ -int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat) +int FPU_store_double(FPU_REG * st0_ptr, u_char st0_tag, double __user * dfloat) { - unsigned long l[2]; - unsigned long increment = 0; /* avoid gcc warnings */ - int precision_loss; - int exp; - FPU_REG tmp; + unsigned long l[2]; + unsigned long increment = 0; /* avoid gcc warnings */ + int precision_loss; + int exp; + FPU_REG tmp; - if ( st0_tag == TAG_Valid ) - { - reg_copy(st0_ptr, &tmp); - exp = exponent(&tmp); + if (st0_tag == TAG_Valid) { + reg_copy(st0_ptr, &tmp); + exp = exponent(&tmp); - if ( exp < DOUBLE_Emin ) /* It may be a denormal */ - { - addexponent(&tmp, -DOUBLE_Emin + 52); /* largest exp to be 51 */ + if (exp < DOUBLE_Emin) { /* It may be a denormal */ + addexponent(&tmp, -DOUBLE_Emin + 52); /* largest exp to be 51 */ - denormal_arg: + denormal_arg: - if ( (precision_loss = FPU_round_to_int(&tmp, st0_tag)) ) - { + if ((precision_loss = FPU_round_to_int(&tmp, st0_tag))) { #ifdef PECULIAR_486 - /* Did it round to a non-denormal ? */ - /* This behaviour might be regarded as peculiar, it appears - that the 80486 rounds to the dest precision, then - converts to decide underflow. */ - if ( !((tmp.sigh == 0x00100000) && (tmp.sigl == 0) && - (st0_ptr->sigl & 0x000007ff)) ) + /* Did it round to a non-denormal ? */ + /* This behaviour might be regarded as peculiar, it appears + that the 80486 rounds to the dest precision, then + converts to decide underflow. */ + if (! + ((tmp.sigh == 0x00100000) && (tmp.sigl == 0) + && (st0_ptr->sigl & 0x000007ff))) #endif /* PECULIAR_486 */ - { - EXCEPTION(EX_Underflow); - /* This is a special case: see sec 16.2.5.1 of - the 80486 book */ - if ( !(control_word & CW_Underflow) ) - return 0; - } - EXCEPTION(precision_loss); - if ( !(control_word & CW_Precision) ) - return 0; - } - l[0] = tmp.sigl; - l[1] = tmp.sigh; - } - else - { - if ( tmp.sigl & 0x000007ff ) - { - precision_loss = 1; - switch (control_word & CW_RC) - { - case RC_RND: - /* Rounding can get a little messy.. */ - increment = ((tmp.sigl & 0x7ff) > 0x400) | /* nearest */ - ((tmp.sigl & 0xc00) == 0xc00); /* odd -> even */ - break; - case RC_DOWN: /* towards -infinity */ - increment = signpositive(&tmp) ? 0 : tmp.sigl & 0x7ff; - break; - case RC_UP: /* towards +infinity */ - increment = signpositive(&tmp) ? tmp.sigl & 0x7ff : 0; - break; - case RC_CHOP: - increment = 0; - break; - } - - /* Truncate the mantissa */ - tmp.sigl &= 0xfffff800; - - if ( increment ) - { - if ( tmp.sigl >= 0xfffff800 ) - { - /* the sigl part overflows */ - if ( tmp.sigh == 0xffffffff ) - { - /* The sigh part overflows */ - tmp.sigh = 0x80000000; - exp++; - if (exp >= EXP_OVER) - goto overflow; + { + EXCEPTION(EX_Underflow); + /* This is a special case: see sec 16.2.5.1 of + the 80486 book */ + if (!(control_word & CW_Underflow)) + return 0; + } + EXCEPTION(precision_loss); + if (!(control_word & CW_Precision)) + return 0; } - else - { - tmp.sigh ++; + l[0] = tmp.sigl; + l[1] = tmp.sigh; + } else { + if (tmp.sigl & 0x000007ff) { + precision_loss = 1; + switch (control_word & CW_RC) { + case RC_RND: + /* Rounding can get a little messy.. */ + increment = ((tmp.sigl & 0x7ff) > 0x400) | /* nearest */ + ((tmp.sigl & 0xc00) == 0xc00); /* odd -> even */ + break; + case RC_DOWN: /* towards -infinity */ + increment = + signpositive(&tmp) ? 0 : tmp. + sigl & 0x7ff; + break; + case RC_UP: /* towards +infinity */ + increment = + signpositive(&tmp) ? tmp. + sigl & 0x7ff : 0; + break; + case RC_CHOP: + increment = 0; + break; + } + + /* Truncate the mantissa */ + tmp.sigl &= 0xfffff800; + + if (increment) { + if (tmp.sigl >= 0xfffff800) { + /* the sigl part overflows */ + if (tmp.sigh == 0xffffffff) { + /* The sigh part overflows */ + tmp.sigh = 0x80000000; + exp++; + if (exp >= EXP_OVER) + goto overflow; + } else { + tmp.sigh++; + } + tmp.sigl = 0x00000000; + } else { + /* We only need to increment sigl */ + tmp.sigl += 0x00000800; + } + } + } else + precision_loss = 0; + + l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21); + l[1] = ((tmp.sigh >> 11) & 0xfffff); + + if (exp > DOUBLE_Emax) { + overflow: + EXCEPTION(EX_Overflow); + if (!(control_word & CW_Overflow)) + return 0; + set_precision_flag_up(); + if (!(control_word & CW_Precision)) + return 0; + + /* This is a special case: see sec 16.2.5.1 of the 80486 book */ + /* Overflow to infinity */ + l[0] = 0x00000000; /* Set to */ + l[1] = 0x7ff00000; /* + INF */ + } else { + if (precision_loss) { + if (increment) + set_precision_flag_up(); + else + set_precision_flag_down(); + } + /* Add the exponent */ + l[1] |= (((exp + DOUBLE_Ebias) & 0x7ff) << 20); } - tmp.sigl = 0x00000000; - } - else - { - /* We only need to increment sigl */ - tmp.sigl += 0x00000800; - } } - } - else - precision_loss = 0; - - l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21); - l[1] = ((tmp.sigh >> 11) & 0xfffff); - - if ( exp > DOUBLE_Emax ) - { - overflow: - EXCEPTION(EX_Overflow); - if ( !(control_word & CW_Overflow) ) - return 0; - set_precision_flag_up(); - if ( !(control_word & CW_Precision) ) - return 0; - - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - /* Overflow to infinity */ - l[0] = 0x00000000; /* Set to */ - l[1] = 0x7ff00000; /* + INF */ - } - else - { - if ( precision_loss ) - { - if ( increment ) - set_precision_flag_up(); - else - set_precision_flag_down(); - } - /* Add the exponent */ - l[1] |= (((exp+DOUBLE_Ebias) & 0x7ff) << 20); - } - } - } - else if (st0_tag == TAG_Zero) - { - /* Number is zero */ - l[0] = 0; - l[1] = 0; - } - else if ( st0_tag == TAG_Special ) - { - st0_tag = FPU_Special(st0_ptr); - if ( st0_tag == TW_Denormal ) - { - /* A denormal will always underflow. */ + } else if (st0_tag == TAG_Zero) { + /* Number is zero */ + l[0] = 0; + l[1] = 0; + } else if (st0_tag == TAG_Special) { + st0_tag = FPU_Special(st0_ptr); + if (st0_tag == TW_Denormal) { + /* A denormal will always underflow. */ #ifndef PECULIAR_486 - /* An 80486 is supposed to be able to generate - a denormal exception here, but... */ - /* Underflow has priority. */ - if ( control_word & CW_Underflow ) - denormal_operand(); + /* An 80486 is supposed to be able to generate + a denormal exception here, but... */ + /* Underflow has priority. */ + if (control_word & CW_Underflow) + denormal_operand(); #endif /* PECULIAR_486 */ - reg_copy(st0_ptr, &tmp); - goto denormal_arg; - } - else if (st0_tag == TW_Infinity) - { - l[0] = 0; - l[1] = 0x7ff00000; - } - else if (st0_tag == TW_NaN) - { - /* Is it really a NaN ? */ - if ( (exponent(st0_ptr) == EXP_OVER) - && (st0_ptr->sigh & 0x80000000) ) - { - /* See if we can get a valid NaN from the FPU_REG */ - l[0] = (st0_ptr->sigl >> 11) | (st0_ptr->sigh << 21); - l[1] = ((st0_ptr->sigh >> 11) & 0xfffff); - if ( !(st0_ptr->sigh & 0x40000000) ) - { - /* It is a signalling NaN */ - EXCEPTION(EX_Invalid); - if ( !(control_word & CW_Invalid) ) - return 0; - l[1] |= (0x40000000 >> 11); + reg_copy(st0_ptr, &tmp); + goto denormal_arg; + } else if (st0_tag == TW_Infinity) { + l[0] = 0; + l[1] = 0x7ff00000; + } else if (st0_tag == TW_NaN) { + /* Is it really a NaN ? */ + if ((exponent(st0_ptr) == EXP_OVER) + && (st0_ptr->sigh & 0x80000000)) { + /* See if we can get a valid NaN from the FPU_REG */ + l[0] = + (st0_ptr->sigl >> 11) | (st0_ptr-> + sigh << 21); + l[1] = ((st0_ptr->sigh >> 11) & 0xfffff); + if (!(st0_ptr->sigh & 0x40000000)) { + /* It is a signalling NaN */ + EXCEPTION(EX_Invalid); + if (!(control_word & CW_Invalid)) + return 0; + l[1] |= (0x40000000 >> 11); + } + l[1] |= 0x7ff00000; + } else { + /* It is an unsupported data type */ + EXCEPTION(EX_Invalid); + if (!(control_word & CW_Invalid)) + return 0; + l[0] = 0; + l[1] = 0xfff80000; + } } - l[1] |= 0x7ff00000; - } - else - { - /* It is an unsupported data type */ - EXCEPTION(EX_Invalid); - if ( !(control_word & CW_Invalid) ) - return 0; - l[0] = 0; - l[1] = 0xfff80000; - } + } else if (st0_tag == TAG_Empty) { + /* Empty register (stack underflow) */ + EXCEPTION(EX_StackUnder); + if (control_word & CW_Invalid) { + /* The masked response */ + /* Put out the QNaN indefinite */ + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, dfloat, 8); + FPU_put_user(0, (unsigned long __user *)dfloat); + FPU_put_user(0xfff80000, + 1 + (unsigned long __user *)dfloat); + RE_ENTRANT_CHECK_ON; + return 1; + } else + return 0; } - } - else if ( st0_tag == TAG_Empty ) - { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if ( control_word & CW_Invalid ) - { - /* The masked response */ - /* Put out the QNaN indefinite */ - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,dfloat,8); - FPU_put_user(0, (unsigned long __user *) dfloat); - FPU_put_user(0xfff80000, 1 + (unsigned long __user *) dfloat); - RE_ENTRANT_CHECK_ON; - return 1; - } - else - return 0; - } - if ( getsign(st0_ptr) ) - l[1] |= 0x80000000; + if (getsign(st0_ptr)) + l[1] |= 0x80000000; - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,dfloat,8); - FPU_put_user(l[0], (unsigned long __user *)dfloat); - FPU_put_user(l[1], 1 + (unsigned long __user *)dfloat); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, dfloat, 8); + FPU_put_user(l[0], (unsigned long __user *)dfloat); + FPU_put_user(l[1], 1 + (unsigned long __user *)dfloat); + RE_ENTRANT_CHECK_ON; - return 1; + return 1; } - /* Put a float into user memory */ -int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single) +int FPU_store_single(FPU_REG * st0_ptr, u_char st0_tag, float __user * single) { - long templ = 0; - unsigned long increment = 0; /* avoid gcc warnings */ - int precision_loss; - int exp; - FPU_REG tmp; + long templ = 0; + unsigned long increment = 0; /* avoid gcc warnings */ + int precision_loss; + int exp; + FPU_REG tmp; - if ( st0_tag == TAG_Valid ) - { + if (st0_tag == TAG_Valid) { - reg_copy(st0_ptr, &tmp); - exp = exponent(&tmp); + reg_copy(st0_ptr, &tmp); + exp = exponent(&tmp); - if ( exp < SINGLE_Emin ) - { - addexponent(&tmp, -SINGLE_Emin + 23); /* largest exp to be 22 */ + if (exp < SINGLE_Emin) { + addexponent(&tmp, -SINGLE_Emin + 23); /* largest exp to be 22 */ - denormal_arg: + denormal_arg: - if ( (precision_loss = FPU_round_to_int(&tmp, st0_tag)) ) - { + if ((precision_loss = FPU_round_to_int(&tmp, st0_tag))) { #ifdef PECULIAR_486 - /* Did it round to a non-denormal ? */ - /* This behaviour might be regarded as peculiar, it appears - that the 80486 rounds to the dest precision, then - converts to decide underflow. */ - if ( !((tmp.sigl == 0x00800000) && - ((st0_ptr->sigh & 0x000000ff) || st0_ptr->sigl)) ) + /* Did it round to a non-denormal ? */ + /* This behaviour might be regarded as peculiar, it appears + that the 80486 rounds to the dest precision, then + converts to decide underflow. */ + if (!((tmp.sigl == 0x00800000) && + ((st0_ptr->sigh & 0x000000ff) + || st0_ptr->sigl))) #endif /* PECULIAR_486 */ - { - EXCEPTION(EX_Underflow); - /* This is a special case: see sec 16.2.5.1 of - the 80486 book */ - if ( !(control_word & CW_Underflow) ) - return 0; - } - EXCEPTION(precision_loss); - if ( !(control_word & CW_Precision) ) - return 0; - } - templ = tmp.sigl; - } - else - { - if ( tmp.sigl | (tmp.sigh & 0x000000ff) ) - { - unsigned long sigh = tmp.sigh; - unsigned long sigl = tmp.sigl; - - precision_loss = 1; - switch (control_word & CW_RC) - { - case RC_RND: - increment = ((sigh & 0xff) > 0x80) /* more than half */ - || (((sigh & 0xff) == 0x80) && sigl) /* more than half */ - || ((sigh & 0x180) == 0x180); /* round to even */ - break; - case RC_DOWN: /* towards -infinity */ - increment = signpositive(&tmp) - ? 0 : (sigl | (sigh & 0xff)); - break; - case RC_UP: /* towards +infinity */ - increment = signpositive(&tmp) - ? (sigl | (sigh & 0xff)) : 0; - break; - case RC_CHOP: - increment = 0; - break; - } - - /* Truncate part of the mantissa */ - tmp.sigl = 0; - - if (increment) - { - if ( sigh >= 0xffffff00 ) - { - /* The sigh part overflows */ - tmp.sigh = 0x80000000; - exp++; - if ( exp >= EXP_OVER ) - goto overflow; - } - else - { - tmp.sigh &= 0xffffff00; - tmp.sigh += 0x100; - } - } - else - { - tmp.sigh &= 0xffffff00; /* Finish the truncation */ - } - } - else - precision_loss = 0; - - templ = (tmp.sigh >> 8) & 0x007fffff; + { + EXCEPTION(EX_Underflow); + /* This is a special case: see sec 16.2.5.1 of + the 80486 book */ + if (!(control_word & CW_Underflow)) + return 0; + } + EXCEPTION(precision_loss); + if (!(control_word & CW_Precision)) + return 0; + } + templ = tmp.sigl; + } else { + if (tmp.sigl | (tmp.sigh & 0x000000ff)) { + unsigned long sigh = tmp.sigh; + unsigned long sigl = tmp.sigl; - if ( exp > SINGLE_Emax ) - { - overflow: - EXCEPTION(EX_Overflow); - if ( !(control_word & CW_Overflow) ) - return 0; - set_precision_flag_up(); - if ( !(control_word & CW_Precision) ) - return 0; + precision_loss = 1; + switch (control_word & CW_RC) { + case RC_RND: + increment = ((sigh & 0xff) > 0x80) /* more than half */ + ||(((sigh & 0xff) == 0x80) && sigl) /* more than half */ + ||((sigh & 0x180) == 0x180); /* round to even */ + break; + case RC_DOWN: /* towards -infinity */ + increment = signpositive(&tmp) + ? 0 : (sigl | (sigh & 0xff)); + break; + case RC_UP: /* towards +infinity */ + increment = signpositive(&tmp) + ? (sigl | (sigh & 0xff)) : 0; + break; + case RC_CHOP: + increment = 0; + break; + } - /* This is a special case: see sec 16.2.5.1 of the 80486 book. */ - /* Masked response is overflow to infinity. */ - templ = 0x7f800000; - } - else - { - if ( precision_loss ) - { - if ( increment ) - set_precision_flag_up(); - else - set_precision_flag_down(); + /* Truncate part of the mantissa */ + tmp.sigl = 0; + + if (increment) { + if (sigh >= 0xffffff00) { + /* The sigh part overflows */ + tmp.sigh = 0x80000000; + exp++; + if (exp >= EXP_OVER) + goto overflow; + } else { + tmp.sigh &= 0xffffff00; + tmp.sigh += 0x100; + } + } else { + tmp.sigh &= 0xffffff00; /* Finish the truncation */ + } + } else + precision_loss = 0; + + templ = (tmp.sigh >> 8) & 0x007fffff; + + if (exp > SINGLE_Emax) { + overflow: + EXCEPTION(EX_Overflow); + if (!(control_word & CW_Overflow)) + return 0; + set_precision_flag_up(); + if (!(control_word & CW_Precision)) + return 0; + + /* This is a special case: see sec 16.2.5.1 of the 80486 book. */ + /* Masked response is overflow to infinity. */ + templ = 0x7f800000; + } else { + if (precision_loss) { + if (increment) + set_precision_flag_up(); + else + set_precision_flag_down(); + } + /* Add the exponent */ + templ |= ((exp + SINGLE_Ebias) & 0xff) << 23; + } } - /* Add the exponent */ - templ |= ((exp+SINGLE_Ebias) & 0xff) << 23; - } - } - } - else if (st0_tag == TAG_Zero) - { - templ = 0; - } - else if ( st0_tag == TAG_Special ) - { - st0_tag = FPU_Special(st0_ptr); - if (st0_tag == TW_Denormal) - { - reg_copy(st0_ptr, &tmp); + } else if (st0_tag == TAG_Zero) { + templ = 0; + } else if (st0_tag == TAG_Special) { + st0_tag = FPU_Special(st0_ptr); + if (st0_tag == TW_Denormal) { + reg_copy(st0_ptr, &tmp); - /* A denormal will always underflow. */ + /* A denormal will always underflow. */ #ifndef PECULIAR_486 - /* An 80486 is supposed to be able to generate - a denormal exception here, but... */ - /* Underflow has priority. */ - if ( control_word & CW_Underflow ) - denormal_operand(); -#endif /* PECULIAR_486 */ - goto denormal_arg; - } - else if (st0_tag == TW_Infinity) - { - templ = 0x7f800000; - } - else if (st0_tag == TW_NaN) - { - /* Is it really a NaN ? */ - if ( (exponent(st0_ptr) == EXP_OVER) && (st0_ptr->sigh & 0x80000000) ) - { - /* See if we can get a valid NaN from the FPU_REG */ - templ = st0_ptr->sigh >> 8; - if ( !(st0_ptr->sigh & 0x40000000) ) - { - /* It is a signalling NaN */ - EXCEPTION(EX_Invalid); - if ( !(control_word & CW_Invalid) ) - return 0; - templ |= (0x40000000 >> 8); + /* An 80486 is supposed to be able to generate + a denormal exception here, but... */ + /* Underflow has priority. */ + if (control_word & CW_Underflow) + denormal_operand(); +#endif /* PECULIAR_486 */ + goto denormal_arg; + } else if (st0_tag == TW_Infinity) { + templ = 0x7f800000; + } else if (st0_tag == TW_NaN) { + /* Is it really a NaN ? */ + if ((exponent(st0_ptr) == EXP_OVER) + && (st0_ptr->sigh & 0x80000000)) { + /* See if we can get a valid NaN from the FPU_REG */ + templ = st0_ptr->sigh >> 8; + if (!(st0_ptr->sigh & 0x40000000)) { + /* It is a signalling NaN */ + EXCEPTION(EX_Invalid); + if (!(control_word & CW_Invalid)) + return 0; + templ |= (0x40000000 >> 8); + } + templ |= 0x7f800000; + } else { + /* It is an unsupported data type */ + EXCEPTION(EX_Invalid); + if (!(control_word & CW_Invalid)) + return 0; + templ = 0xffc00000; + } } - templ |= 0x7f800000; - } - else - { - /* It is an unsupported data type */ - EXCEPTION(EX_Invalid); - if ( !(control_word & CW_Invalid) ) +#ifdef PARANOID + else { + EXCEPTION(EX_INTERNAL | 0x164); + return 0; + } +#endif + } else if (st0_tag == TAG_Empty) { + /* Empty register (stack underflow) */ + EXCEPTION(EX_StackUnder); + if (control_word & EX_Invalid) { + /* The masked response */ + /* Put out the QNaN indefinite */ + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, single, 4); + FPU_put_user(0xffc00000, + (unsigned long __user *)single); + RE_ENTRANT_CHECK_ON; + return 1; + } else + return 0; + } +#ifdef PARANOID + else { + EXCEPTION(EX_INTERNAL | 0x163); return 0; - templ = 0xffc00000; - } - } -#ifdef PARANOID - else - { - EXCEPTION(EX_INTERNAL|0x164); - return 0; } #endif - } - else if ( st0_tag == TAG_Empty ) - { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if ( control_word & EX_Invalid ) - { - /* The masked response */ - /* Put out the QNaN indefinite */ - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,single,4); - FPU_put_user(0xffc00000, (unsigned long __user *) single); - RE_ENTRANT_CHECK_ON; - return 1; - } - else - return 0; - } -#ifdef PARANOID - else - { - EXCEPTION(EX_INTERNAL|0x163); - return 0; - } -#endif - if ( getsign(st0_ptr) ) - templ |= 0x80000000; + if (getsign(st0_ptr)) + templ |= 0x80000000; - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,single,4); - FPU_put_user(templ,(unsigned long __user *) single); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, single, 4); + FPU_put_user(templ, (unsigned long __user *)single); + RE_ENTRANT_CHECK_ON; - return 1; + return 1; } - /* Put a long long into user memory */ -int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d) +int FPU_store_int64(FPU_REG * st0_ptr, u_char st0_tag, long long __user * d) { - FPU_REG t; - long long tll; - int precision_loss; + FPU_REG t; + long long tll; + int precision_loss; - if ( st0_tag == TAG_Empty ) - { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - goto invalid_operand; - } - else if ( st0_tag == TAG_Special ) - { - st0_tag = FPU_Special(st0_ptr); - if ( (st0_tag == TW_Infinity) || - (st0_tag == TW_NaN) ) - { - EXCEPTION(EX_Invalid); - goto invalid_operand; + if (st0_tag == TAG_Empty) { + /* Empty register (stack underflow) */ + EXCEPTION(EX_StackUnder); + goto invalid_operand; + } else if (st0_tag == TAG_Special) { + st0_tag = FPU_Special(st0_ptr); + if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) { + EXCEPTION(EX_Invalid); + goto invalid_operand; + } } - } - reg_copy(st0_ptr, &t); - precision_loss = FPU_round_to_int(&t, st0_tag); - ((long *)&tll)[0] = t.sigl; - ((long *)&tll)[1] = t.sigh; - if ( (precision_loss == 1) || - ((t.sigh & 0x80000000) && - !((t.sigh == 0x80000000) && (t.sigl == 0) && - signnegative(&t))) ) - { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - invalid_operand: - if ( control_word & EX_Invalid ) - { - /* Produce something like QNaN "indefinite" */ - tll = 0x8000000000000000LL; + reg_copy(st0_ptr, &t); + precision_loss = FPU_round_to_int(&t, st0_tag); + ((long *)&tll)[0] = t.sigl; + ((long *)&tll)[1] = t.sigh; + if ((precision_loss == 1) || + ((t.sigh & 0x80000000) && + !((t.sigh == 0x80000000) && (t.sigl == 0) && signnegative(&t)))) { + EXCEPTION(EX_Invalid); + /* This is a special case: see sec 16.2.5.1 of the 80486 book */ + invalid_operand: + if (control_word & EX_Invalid) { + /* Produce something like QNaN "indefinite" */ + tll = 0x8000000000000000LL; + } else + return 0; + } else { + if (precision_loss) + set_precision_flag(precision_loss); + if (signnegative(&t)) + tll = -tll; } - else - return 0; - } - else - { - if ( precision_loss ) - set_precision_flag(precision_loss); - if ( signnegative(&t) ) - tll = - tll; - } - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,d,8); - if (copy_to_user(d, &tll, 8)) - FPU_abort; - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, d, 8); + if (copy_to_user(d, &tll, 8)) + FPU_abort; + RE_ENTRANT_CHECK_ON; - return 1; + return 1; } - /* Put a long into user memory */ -int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d) +int FPU_store_int32(FPU_REG * st0_ptr, u_char st0_tag, long __user * d) { - FPU_REG t; - int precision_loss; + FPU_REG t; + int precision_loss; - if ( st0_tag == TAG_Empty ) - { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - goto invalid_operand; - } - else if ( st0_tag == TAG_Special ) - { - st0_tag = FPU_Special(st0_ptr); - if ( (st0_tag == TW_Infinity) || - (st0_tag == TW_NaN) ) - { - EXCEPTION(EX_Invalid); - goto invalid_operand; + if (st0_tag == TAG_Empty) { + /* Empty register (stack underflow) */ + EXCEPTION(EX_StackUnder); + goto invalid_operand; + } else if (st0_tag == TAG_Special) { + st0_tag = FPU_Special(st0_ptr); + if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) { + EXCEPTION(EX_Invalid); + goto invalid_operand; + } } - } - reg_copy(st0_ptr, &t); - precision_loss = FPU_round_to_int(&t, st0_tag); - if (t.sigh || - ((t.sigl & 0x80000000) && - !((t.sigl == 0x80000000) && signnegative(&t))) ) - { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - invalid_operand: - if ( control_word & EX_Invalid ) - { - /* Produce something like QNaN "indefinite" */ - t.sigl = 0x80000000; + reg_copy(st0_ptr, &t); + precision_loss = FPU_round_to_int(&t, st0_tag); + if (t.sigh || + ((t.sigl & 0x80000000) && + !((t.sigl == 0x80000000) && signnegative(&t)))) { + EXCEPTION(EX_Invalid); + /* This is a special case: see sec 16.2.5.1 of the 80486 book */ + invalid_operand: + if (control_word & EX_Invalid) { + /* Produce something like QNaN "indefinite" */ + t.sigl = 0x80000000; + } else + return 0; + } else { + if (precision_loss) + set_precision_flag(precision_loss); + if (signnegative(&t)) + t.sigl = -(long)t.sigl; } - else - return 0; - } - else - { - if ( precision_loss ) - set_precision_flag(precision_loss); - if ( signnegative(&t) ) - t.sigl = -(long)t.sigl; - } - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,d,4); - FPU_put_user(t.sigl, (unsigned long __user *) d); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, d, 4); + FPU_put_user(t.sigl, (unsigned long __user *)d); + RE_ENTRANT_CHECK_ON; - return 1; + return 1; } - /* Put a short into user memory */ -int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d) +int FPU_store_int16(FPU_REG * st0_ptr, u_char st0_tag, short __user * d) { - FPU_REG t; - int precision_loss; + FPU_REG t; + int precision_loss; - if ( st0_tag == TAG_Empty ) - { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - goto invalid_operand; - } - else if ( st0_tag == TAG_Special ) - { - st0_tag = FPU_Special(st0_ptr); - if ( (st0_tag == TW_Infinity) || - (st0_tag == TW_NaN) ) - { - EXCEPTION(EX_Invalid); - goto invalid_operand; + if (st0_tag == TAG_Empty) { + /* Empty register (stack underflow) */ + EXCEPTION(EX_StackUnder); + goto invalid_operand; + } else if (st0_tag == TAG_Special) { + st0_tag = FPU_Special(st0_ptr); + if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) { + EXCEPTION(EX_Invalid); + goto invalid_operand; + } } - } - reg_copy(st0_ptr, &t); - precision_loss = FPU_round_to_int(&t, st0_tag); - if (t.sigh || - ((t.sigl & 0xffff8000) && - !((t.sigl == 0x8000) && signnegative(&t))) ) - { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - invalid_operand: - if ( control_word & EX_Invalid ) - { - /* Produce something like QNaN "indefinite" */ - t.sigl = 0x8000; + reg_copy(st0_ptr, &t); + precision_loss = FPU_round_to_int(&t, st0_tag); + if (t.sigh || + ((t.sigl & 0xffff8000) && + !((t.sigl == 0x8000) && signnegative(&t)))) { + EXCEPTION(EX_Invalid); + /* This is a special case: see sec 16.2.5.1 of the 80486 book */ + invalid_operand: + if (control_word & EX_Invalid) { + /* Produce something like QNaN "indefinite" */ + t.sigl = 0x8000; + } else + return 0; + } else { + if (precision_loss) + set_precision_flag(precision_loss); + if (signnegative(&t)) + t.sigl = -t.sigl; } - else - return 0; - } - else - { - if ( precision_loss ) - set_precision_flag(precision_loss); - if ( signnegative(&t) ) - t.sigl = -t.sigl; - } - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,d,2); - FPU_put_user((short)t.sigl, d); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, d, 2); + FPU_put_user((short)t.sigl, d); + RE_ENTRANT_CHECK_ON; - return 1; + return 1; } - /* Put a packed bcd array into user memory */ -int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d) +int FPU_store_bcd(FPU_REG * st0_ptr, u_char st0_tag, u_char __user * d) { - FPU_REG t; - unsigned long long ll; - u_char b; - int i, precision_loss; - u_char sign = (getsign(st0_ptr) == SIGN_NEG) ? 0x80 : 0; + FPU_REG t; + unsigned long long ll; + u_char b; + int i, precision_loss; + u_char sign = (getsign(st0_ptr) == SIGN_NEG) ? 0x80 : 0; - if ( st0_tag == TAG_Empty ) - { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - goto invalid_operand; - } - else if ( st0_tag == TAG_Special ) - { - st0_tag = FPU_Special(st0_ptr); - if ( (st0_tag == TW_Infinity) || - (st0_tag == TW_NaN) ) - { - EXCEPTION(EX_Invalid); - goto invalid_operand; + if (st0_tag == TAG_Empty) { + /* Empty register (stack underflow) */ + EXCEPTION(EX_StackUnder); + goto invalid_operand; + } else if (st0_tag == TAG_Special) { + st0_tag = FPU_Special(st0_ptr); + if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) { + EXCEPTION(EX_Invalid); + goto invalid_operand; + } } - } - reg_copy(st0_ptr, &t); - precision_loss = FPU_round_to_int(&t, st0_tag); - ll = significand(&t); + reg_copy(st0_ptr, &t); + precision_loss = FPU_round_to_int(&t, st0_tag); + ll = significand(&t); - /* Check for overflow, by comparing with 999999999999999999 decimal. */ - if ( (t.sigh > 0x0de0b6b3) || - ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff)) ) - { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - invalid_operand: - if ( control_word & CW_Invalid ) - { - /* Produce the QNaN "indefinite" */ - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,d,10); - for ( i = 0; i < 7; i++) - FPU_put_user(0, d+i); /* These bytes "undefined" */ - FPU_put_user(0xc0, d+7); /* This byte "undefined" */ - FPU_put_user(0xff, d+8); - FPU_put_user(0xff, d+9); - RE_ENTRANT_CHECK_ON; - return 1; + /* Check for overflow, by comparing with 999999999999999999 decimal. */ + if ((t.sigh > 0x0de0b6b3) || + ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff))) { + EXCEPTION(EX_Invalid); + /* This is a special case: see sec 16.2.5.1 of the 80486 book */ + invalid_operand: + if (control_word & CW_Invalid) { + /* Produce the QNaN "indefinite" */ + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, d, 10); + for (i = 0; i < 7; i++) + FPU_put_user(0, d + i); /* These bytes "undefined" */ + FPU_put_user(0xc0, d + 7); /* This byte "undefined" */ + FPU_put_user(0xff, d + 8); + FPU_put_user(0xff, d + 9); + RE_ENTRANT_CHECK_ON; + return 1; + } else + return 0; + } else if (precision_loss) { + /* Precision loss doesn't stop the data transfer */ + set_precision_flag(precision_loss); } - else - return 0; - } - else if ( precision_loss ) - { - /* Precision loss doesn't stop the data transfer */ - set_precision_flag(precision_loss); - } - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,d,10); - RE_ENTRANT_CHECK_ON; - for ( i = 0; i < 9; i++) - { - b = FPU_div_small(&ll, 10); - b |= (FPU_div_small(&ll, 10)) << 4; - RE_ENTRANT_CHECK_OFF; - FPU_put_user(b, d+i); - RE_ENTRANT_CHECK_ON; - } - RE_ENTRANT_CHECK_OFF; - FPU_put_user(sign, d+9); - RE_ENTRANT_CHECK_ON; + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, d, 10); + RE_ENTRANT_CHECK_ON; + for (i = 0; i < 9; i++) { + b = FPU_div_small(&ll, 10); + b |= (FPU_div_small(&ll, 10)) << 4; + RE_ENTRANT_CHECK_OFF; + FPU_put_user(b, d + i); + RE_ENTRANT_CHECK_ON; + } + RE_ENTRANT_CHECK_OFF; + FPU_put_user(sign, d + 9); + RE_ENTRANT_CHECK_ON; - return 1; + return 1; } /*===========================================================================*/ @@ -1117,259 +971,254 @@ int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d) /* Overflow is signalled by a non-zero return value (in eax). In the case of overflow, the returned significand always has the largest possible value */ -int FPU_round_to_int(FPU_REG *r, u_char tag) +int FPU_round_to_int(FPU_REG * r, u_char tag) { - u_char very_big; - unsigned eax; + u_char very_big; + unsigned eax; - if (tag == TAG_Zero) - { - /* Make sure that zero is returned */ - significand(r) = 0; - return 0; /* o.k. */ - } + if (tag == TAG_Zero) { + /* Make sure that zero is returned */ + significand(r) = 0; + return 0; /* o.k. */ + } - if (exponent(r) > 63) - { - r->sigl = r->sigh = ~0; /* The largest representable number */ - return 1; /* overflow */ - } + if (exponent(r) > 63) { + r->sigl = r->sigh = ~0; /* The largest representable number */ + return 1; /* overflow */ + } - eax = FPU_shrxs(&r->sigl, 63 - exponent(r)); - very_big = !(~(r->sigh) | ~(r->sigl)); /* test for 0xfff...fff */ + eax = FPU_shrxs(&r->sigl, 63 - exponent(r)); + very_big = !(~(r->sigh) | ~(r->sigl)); /* test for 0xfff...fff */ #define half_or_more (eax & 0x80000000) #define frac_part (eax) #define more_than_half ((eax & 0x80000001) == 0x80000001) - switch (control_word & CW_RC) - { - case RC_RND: - if ( more_than_half /* nearest */ - || (half_or_more && (r->sigl & 1)) ) /* odd -> even */ - { - if ( very_big ) return 1; /* overflow */ - significand(r) ++; - return PRECISION_LOST_UP; + switch (control_word & CW_RC) { + case RC_RND: + if (more_than_half /* nearest */ + || (half_or_more && (r->sigl & 1))) { /* odd -> even */ + if (very_big) + return 1; /* overflow */ + significand(r)++; + return PRECISION_LOST_UP; + } + break; + case RC_DOWN: + if (frac_part && getsign(r)) { + if (very_big) + return 1; /* overflow */ + significand(r)++; + return PRECISION_LOST_UP; + } + break; + case RC_UP: + if (frac_part && !getsign(r)) { + if (very_big) + return 1; /* overflow */ + significand(r)++; + return PRECISION_LOST_UP; + } + break; + case RC_CHOP: + break; } - break; - case RC_DOWN: - if (frac_part && getsign(r)) - { - if ( very_big ) return 1; /* overflow */ - significand(r) ++; - return PRECISION_LOST_UP; - } - break; - case RC_UP: - if (frac_part && !getsign(r)) - { - if ( very_big ) return 1; /* overflow */ - significand(r) ++; - return PRECISION_LOST_UP; - } - break; - case RC_CHOP: - break; - } - return eax ? PRECISION_LOST_DOWN : 0; + return eax ? PRECISION_LOST_DOWN : 0; } /*===========================================================================*/ -u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s) +u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user * s) { - unsigned short tag_word = 0; - u_char tag; - int i; + unsigned short tag_word = 0; + u_char tag; + int i; - if ( (addr_modes.default_mode == VM86) || - ((addr_modes.default_mode == PM16) - ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX)) ) - { - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ, s, 0x0e); - FPU_get_user(control_word, (unsigned short __user *) s); - FPU_get_user(partial_status, (unsigned short __user *) (s+2)); - FPU_get_user(tag_word, (unsigned short __user *) (s+4)); - FPU_get_user(instruction_address.offset, (unsigned short __user *) (s+6)); - FPU_get_user(instruction_address.selector, (unsigned short __user *) (s+8)); - FPU_get_user(operand_address.offset, (unsigned short __user *) (s+0x0a)); - FPU_get_user(operand_address.selector, (unsigned short __user *) (s+0x0c)); - RE_ENTRANT_CHECK_ON; - s += 0x0e; - if ( addr_modes.default_mode == VM86 ) - { - instruction_address.offset - += (instruction_address.selector & 0xf000) << 4; - operand_address.offset += (operand_address.selector & 0xf000) << 4; + if ((addr_modes.default_mode == VM86) || + ((addr_modes.default_mode == PM16) + ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX))) { + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, s, 0x0e); + FPU_get_user(control_word, (unsigned short __user *)s); + FPU_get_user(partial_status, (unsigned short __user *)(s + 2)); + FPU_get_user(tag_word, (unsigned short __user *)(s + 4)); + FPU_get_user(instruction_address.offset, + (unsigned short __user *)(s + 6)); + FPU_get_user(instruction_address.selector, + (unsigned short __user *)(s + 8)); + FPU_get_user(operand_address.offset, + (unsigned short __user *)(s + 0x0a)); + FPU_get_user(operand_address.selector, + (unsigned short __user *)(s + 0x0c)); + RE_ENTRANT_CHECK_ON; + s += 0x0e; + if (addr_modes.default_mode == VM86) { + instruction_address.offset + += (instruction_address.selector & 0xf000) << 4; + operand_address.offset += + (operand_address.selector & 0xf000) << 4; + } + } else { + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, s, 0x1c); + FPU_get_user(control_word, (unsigned short __user *)s); + FPU_get_user(partial_status, (unsigned short __user *)(s + 4)); + FPU_get_user(tag_word, (unsigned short __user *)(s + 8)); + FPU_get_user(instruction_address.offset, + (unsigned long __user *)(s + 0x0c)); + FPU_get_user(instruction_address.selector, + (unsigned short __user *)(s + 0x10)); + FPU_get_user(instruction_address.opcode, + (unsigned short __user *)(s + 0x12)); + FPU_get_user(operand_address.offset, + (unsigned long __user *)(s + 0x14)); + FPU_get_user(operand_address.selector, + (unsigned long __user *)(s + 0x18)); + RE_ENTRANT_CHECK_ON; + s += 0x1c; } - } - else - { - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ, s, 0x1c); - FPU_get_user(control_word, (unsigned short __user *) s); - FPU_get_user(partial_status, (unsigned short __user *) (s+4)); - FPU_get_user(tag_word, (unsigned short __user *) (s+8)); - FPU_get_user(instruction_address.offset, (unsigned long __user *) (s+0x0c)); - FPU_get_user(instruction_address.selector, (unsigned short __user *) (s+0x10)); - FPU_get_user(instruction_address.opcode, (unsigned short __user *) (s+0x12)); - FPU_get_user(operand_address.offset, (unsigned long __user *) (s+0x14)); - FPU_get_user(operand_address.selector, (unsigned long __user *) (s+0x18)); - RE_ENTRANT_CHECK_ON; - s += 0x1c; - } #ifdef PECULIAR_486 - control_word &= ~0xe080; -#endif /* PECULIAR_486 */ + control_word &= ~0xe080; +#endif /* PECULIAR_486 */ - top = (partial_status >> SW_Top_Shift) & 7; + top = (partial_status >> SW_Top_Shift) & 7; - if ( partial_status & ~control_word & CW_Exceptions ) - partial_status |= (SW_Summary | SW_Backward); - else - partial_status &= ~(SW_Summary | SW_Backward); + if (partial_status & ~control_word & CW_Exceptions) + partial_status |= (SW_Summary | SW_Backward); + else + partial_status &= ~(SW_Summary | SW_Backward); - for ( i = 0; i < 8; i++ ) - { - tag = tag_word & 3; - tag_word >>= 2; + for (i = 0; i < 8; i++) { + tag = tag_word & 3; + tag_word >>= 2; - if ( tag == TAG_Empty ) - /* New tag is empty. Accept it */ - FPU_settag(i, TAG_Empty); - else if ( FPU_gettag(i) == TAG_Empty ) - { - /* Old tag is empty and new tag is not empty. New tag is determined - by old reg contents */ - if ( exponent(&fpu_register(i)) == - EXTENDED_Ebias ) - { - if ( !(fpu_register(i).sigl | fpu_register(i).sigh) ) - FPU_settag(i, TAG_Zero); - else - FPU_settag(i, TAG_Special); - } - else if ( exponent(&fpu_register(i)) == 0x7fff - EXTENDED_Ebias ) - { - FPU_settag(i, TAG_Special); - } - else if ( fpu_register(i).sigh & 0x80000000 ) - FPU_settag(i, TAG_Valid); - else - FPU_settag(i, TAG_Special); /* An Un-normal */ - } - /* Else old tag is not empty and new tag is not empty. Old tag - remains correct */ - } + if (tag == TAG_Empty) + /* New tag is empty. Accept it */ + FPU_settag(i, TAG_Empty); + else if (FPU_gettag(i) == TAG_Empty) { + /* Old tag is empty and new tag is not empty. New tag is determined + by old reg contents */ + if (exponent(&fpu_register(i)) == -EXTENDED_Ebias) { + if (! + (fpu_register(i).sigl | fpu_register(i). + sigh)) + FPU_settag(i, TAG_Zero); + else + FPU_settag(i, TAG_Special); + } else if (exponent(&fpu_register(i)) == + 0x7fff - EXTENDED_Ebias) { + FPU_settag(i, TAG_Special); + } else if (fpu_register(i).sigh & 0x80000000) + FPU_settag(i, TAG_Valid); + else + FPU_settag(i, TAG_Special); /* An Un-normal */ + } + /* Else old tag is not empty and new tag is not empty. Old tag + remains correct */ + } - return s; + return s; } - -void frstor(fpu_addr_modes addr_modes, u_char __user *data_address) +void frstor(fpu_addr_modes addr_modes, u_char __user * data_address) { - int i, regnr; - u_char __user *s = fldenv(addr_modes, data_address); - int offset = (top & 7) * 10, other = 80 - offset; + int i, regnr; + u_char __user *s = fldenv(addr_modes, data_address); + int offset = (top & 7) * 10, other = 80 - offset; - /* Copy all registers in stack order. */ - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_READ,s,80); - __copy_from_user(register_base+offset, s, other); - if ( offset ) - __copy_from_user(register_base, s+other, offset); - RE_ENTRANT_CHECK_ON; + /* Copy all registers in stack order. */ + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_READ, s, 80); + __copy_from_user(register_base + offset, s, other); + if (offset) + __copy_from_user(register_base, s + other, offset); + RE_ENTRANT_CHECK_ON; - for ( i = 0; i < 8; i++ ) - { - regnr = (i+top) & 7; - if ( FPU_gettag(regnr) != TAG_Empty ) - /* The loaded data over-rides all other cases. */ - FPU_settag(regnr, FPU_tagof(&st(i))); - } + for (i = 0; i < 8; i++) { + regnr = (i + top) & 7; + if (FPU_gettag(regnr) != TAG_Empty) + /* The loaded data over-rides all other cases. */ + FPU_settag(regnr, FPU_tagof(&st(i))); + } } - -u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d) +u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user * d) { - if ( (addr_modes.default_mode == VM86) || - ((addr_modes.default_mode == PM16) - ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX)) ) - { - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,d,14); + if ((addr_modes.default_mode == VM86) || + ((addr_modes.default_mode == PM16) + ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX))) { + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, d, 14); #ifdef PECULIAR_486 - FPU_put_user(control_word & ~0xe080, (unsigned long __user *) d); + FPU_put_user(control_word & ~0xe080, (unsigned long __user *)d); #else - FPU_put_user(control_word, (unsigned short __user *) d); + FPU_put_user(control_word, (unsigned short __user *)d); #endif /* PECULIAR_486 */ - FPU_put_user(status_word(), (unsigned short __user *) (d+2)); - FPU_put_user(fpu_tag_word, (unsigned short __user *) (d+4)); - FPU_put_user(instruction_address.offset, (unsigned short __user *) (d+6)); - FPU_put_user(operand_address.offset, (unsigned short __user *) (d+0x0a)); - if ( addr_modes.default_mode == VM86 ) - { - FPU_put_user((instruction_address.offset & 0xf0000) >> 4, - (unsigned short __user *) (d+8)); - FPU_put_user((operand_address.offset & 0xf0000) >> 4, - (unsigned short __user *) (d+0x0c)); - } - else - { - FPU_put_user(instruction_address.selector, (unsigned short __user *) (d+8)); - FPU_put_user(operand_address.selector, (unsigned short __user *) (d+0x0c)); - } - RE_ENTRANT_CHECK_ON; - d += 0x0e; - } - else - { - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE, d, 7*4); + FPU_put_user(status_word(), (unsigned short __user *)(d + 2)); + FPU_put_user(fpu_tag_word, (unsigned short __user *)(d + 4)); + FPU_put_user(instruction_address.offset, + (unsigned short __user *)(d + 6)); + FPU_put_user(operand_address.offset, + (unsigned short __user *)(d + 0x0a)); + if (addr_modes.default_mode == VM86) { + FPU_put_user((instruction_address. + offset & 0xf0000) >> 4, + (unsigned short __user *)(d + 8)); + FPU_put_user((operand_address.offset & 0xf0000) >> 4, + (unsigned short __user *)(d + 0x0c)); + } else { + FPU_put_user(instruction_address.selector, + (unsigned short __user *)(d + 8)); + FPU_put_user(operand_address.selector, + (unsigned short __user *)(d + 0x0c)); + } + RE_ENTRANT_CHECK_ON; + d += 0x0e; + } else { + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, d, 7 * 4); #ifdef PECULIAR_486 - control_word &= ~0xe080; - /* An 80486 sets nearly all of the reserved bits to 1. */ - control_word |= 0xffff0040; - partial_status = status_word() | 0xffff0000; - fpu_tag_word |= 0xffff0000; - I387.soft.fcs &= ~0xf8000000; - I387.soft.fos |= 0xffff0000; + control_word &= ~0xe080; + /* An 80486 sets nearly all of the reserved bits to 1. */ + control_word |= 0xffff0040; + partial_status = status_word() | 0xffff0000; + fpu_tag_word |= 0xffff0000; + I387.soft.fcs &= ~0xf8000000; + I387.soft.fos |= 0xffff0000; #endif /* PECULIAR_486 */ - if (__copy_to_user(d, &control_word, 7*4)) - FPU_abort; - RE_ENTRANT_CHECK_ON; - d += 0x1c; - } - - control_word |= CW_Exceptions; - partial_status &= ~(SW_Summary | SW_Backward); + if (__copy_to_user(d, &control_word, 7 * 4)) + FPU_abort; + RE_ENTRANT_CHECK_ON; + d += 0x1c; + } - return d; + control_word |= CW_Exceptions; + partial_status &= ~(SW_Summary | SW_Backward); + + return d; } - -void fsave(fpu_addr_modes addr_modes, u_char __user *data_address) +void fsave(fpu_addr_modes addr_modes, u_char __user * data_address) { - u_char __user *d; - int offset = (top & 7) * 10, other = 80 - offset; + u_char __user *d; + int offset = (top & 7) * 10, other = 80 - offset; - d = fstenv(addr_modes, data_address); + d = fstenv(addr_modes, data_address); - RE_ENTRANT_CHECK_OFF; - FPU_access_ok(VERIFY_WRITE,d,80); + RE_ENTRANT_CHECK_OFF; + FPU_access_ok(VERIFY_WRITE, d, 80); - /* Copy all registers in stack order. */ - if (__copy_to_user(d, register_base+offset, other)) - FPU_abort; - if ( offset ) - if (__copy_to_user(d+other, register_base, offset)) - FPU_abort; - RE_ENTRANT_CHECK_ON; + /* Copy all registers in stack order. */ + if (__copy_to_user(d, register_base + offset, other)) + FPU_abort; + if (offset) + if (__copy_to_user(d + other, register_base, offset)) + FPU_abort; + RE_ENTRANT_CHECK_ON; - finit(); + finit(); } /*===========================================================================*/ diff --git a/arch/x86/math-emu/reg_mul.c b/arch/x86/math-emu/reg_mul.c index 40f50b61bc67..36c37f71f713 100644 --- a/arch/x86/math-emu/reg_mul.c +++ b/arch/x86/math-emu/reg_mul.c @@ -20,7 +20,6 @@ #include "reg_constant.h" #include "fpu_system.h" - /* Multiply two registers to give a register result. The sources are st(deststnr) and (b,tagb,signb). @@ -29,104 +28,88 @@ /* This routine must be called with non-empty source registers */ int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w) { - FPU_REG *a = &st(deststnr); - FPU_REG *dest = a; - u_char taga = FPU_gettagi(deststnr); - u_char saved_sign = getsign(dest); - u_char sign = (getsign(a) ^ getsign(b)); - int tag; + FPU_REG *a = &st(deststnr); + FPU_REG *dest = a; + u_char taga = FPU_gettagi(deststnr); + u_char saved_sign = getsign(dest); + u_char sign = (getsign(a) ^ getsign(b)); + int tag; + if (!(taga | tagb)) { + /* Both regs Valid, this should be the most common case. */ - if ( !(taga | tagb) ) - { - /* Both regs Valid, this should be the most common case. */ - - tag = FPU_u_mul(a, b, dest, control_w, sign, exponent(a) + exponent(b)); - if ( tag < 0 ) - { - setsign(dest, saved_sign); - return tag; + tag = + FPU_u_mul(a, b, dest, control_w, sign, + exponent(a) + exponent(b)); + if (tag < 0) { + setsign(dest, saved_sign); + return tag; + } + FPU_settagi(deststnr, tag); + return tag; } - FPU_settagi(deststnr, tag); - return tag; - } - if ( taga == TAG_Special ) - taga = FPU_Special(a); - if ( tagb == TAG_Special ) - tagb = FPU_Special(b); + if (taga == TAG_Special) + taga = FPU_Special(a); + if (tagb == TAG_Special) + tagb = FPU_Special(b); - if ( ((taga == TAG_Valid) && (tagb == TW_Denormal)) + if (((taga == TAG_Valid) && (tagb == TW_Denormal)) || ((taga == TW_Denormal) && (tagb == TAG_Valid)) - || ((taga == TW_Denormal) && (tagb == TW_Denormal)) ) - { - FPU_REG x, y; - if ( denormal_operand() < 0 ) - return FPU_Exception; + || ((taga == TW_Denormal) && (tagb == TW_Denormal))) { + FPU_REG x, y; + if (denormal_operand() < 0) + return FPU_Exception; - FPU_to_exp16(a, &x); - FPU_to_exp16(b, &y); - tag = FPU_u_mul(&x, &y, dest, control_w, sign, - exponent16(&x) + exponent16(&y)); - if ( tag < 0 ) - { - setsign(dest, saved_sign); - return tag; + FPU_to_exp16(a, &x); + FPU_to_exp16(b, &y); + tag = FPU_u_mul(&x, &y, dest, control_w, sign, + exponent16(&x) + exponent16(&y)); + if (tag < 0) { + setsign(dest, saved_sign); + return tag; + } + FPU_settagi(deststnr, tag); + return tag; + } else if ((taga <= TW_Denormal) && (tagb <= TW_Denormal)) { + if (((tagb == TW_Denormal) || (taga == TW_Denormal)) + && (denormal_operand() < 0)) + return FPU_Exception; + + /* Must have either both arguments == zero, or + one valid and the other zero. + The result is therefore zero. */ + FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); + /* The 80486 book says that the answer is +0, but a real + 80486 behaves this way. + IEEE-754 apparently says it should be this way. */ + setsign(dest, sign); + return TAG_Zero; + } + /* Must have infinities, NaNs, etc */ + else if ((taga == TW_NaN) || (tagb == TW_NaN)) { + return real_2op_NaN(b, tagb, deststnr, &st(0)); + } else if (((taga == TW_Infinity) && (tagb == TAG_Zero)) + || ((tagb == TW_Infinity) && (taga == TAG_Zero))) { + return arith_invalid(deststnr); /* Zero*Infinity is invalid */ + } else if (((taga == TW_Denormal) || (tagb == TW_Denormal)) + && (denormal_operand() < 0)) { + return FPU_Exception; + } else if (taga == TW_Infinity) { + FPU_copy_to_regi(a, TAG_Special, deststnr); + setsign(dest, sign); + return TAG_Special; + } else if (tagb == TW_Infinity) { + FPU_copy_to_regi(b, TAG_Special, deststnr); + setsign(dest, sign); + return TAG_Special; } - FPU_settagi(deststnr, tag); - return tag; - } - else if ( (taga <= TW_Denormal) && (tagb <= TW_Denormal) ) - { - if ( ((tagb == TW_Denormal) || (taga == TW_Denormal)) - && (denormal_operand() < 0) ) - return FPU_Exception; - - /* Must have either both arguments == zero, or - one valid and the other zero. - The result is therefore zero. */ - FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr); - /* The 80486 book says that the answer is +0, but a real - 80486 behaves this way. - IEEE-754 apparently says it should be this way. */ - setsign(dest, sign); - return TAG_Zero; - } - /* Must have infinities, NaNs, etc */ - else if ( (taga == TW_NaN) || (tagb == TW_NaN) ) - { - return real_2op_NaN(b, tagb, deststnr, &st(0)); - } - else if ( ((taga == TW_Infinity) && (tagb == TAG_Zero)) - || ((tagb == TW_Infinity) && (taga == TAG_Zero)) ) - { - return arith_invalid(deststnr); /* Zero*Infinity is invalid */ - } - else if ( ((taga == TW_Denormal) || (tagb == TW_Denormal)) - && (denormal_operand() < 0) ) - { - return FPU_Exception; - } - else if (taga == TW_Infinity) - { - FPU_copy_to_regi(a, TAG_Special, deststnr); - setsign(dest, sign); - return TAG_Special; - } - else if (tagb == TW_Infinity) - { - FPU_copy_to_regi(b, TAG_Special, deststnr); - setsign(dest, sign); - return TAG_Special; - } - #ifdef PARANOID - else - { - EXCEPTION(EX_INTERNAL|0x102); - return FPU_Exception; - } -#endif /* PARANOID */ + else { + EXCEPTION(EX_INTERNAL | 0x102); + return FPU_Exception; + } +#endif /* PARANOID */ return 0; } diff --git a/arch/x86/math-emu/status_w.h b/arch/x86/math-emu/status_w.h index 59e73302aa60..54a3f226982d 100644 --- a/arch/x86/math-emu/status_w.h +++ b/arch/x86/math-emu/status_w.h @@ -10,7 +10,7 @@ #ifndef _STATUS_H_ #define _STATUS_H_ -#include "fpu_emu.h" /* for definition of PECULIAR_486 */ +#include "fpu_emu.h" /* for definition of PECULIAR_486 */ #ifdef __ASSEMBLY__ #define Const__(x) $##x @@ -34,7 +34,7 @@ #define SW_Denorm_Op Const__(0x0002) /* denormalized operand */ #define SW_Invalid Const__(0x0001) /* invalid operation */ -#define SW_Exc_Mask Const__(0x27f) /* Status word exception bit mask */ +#define SW_Exc_Mask Const__(0x27f) /* Status word exception bit mask */ #ifndef __ASSEMBLY__ @@ -50,8 +50,8 @@ ((partial_status & ~SW_Top & 0xffff) | ((top << SW_Top_Shift) & SW_Top)) static inline void setcc(int cc) { - partial_status &= ~(SW_C0|SW_C1|SW_C2|SW_C3); - partial_status |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3); + partial_status &= ~(SW_C0 | SW_C1 | SW_C2 | SW_C3); + partial_status |= (cc) & (SW_C0 | SW_C1 | SW_C2 | SW_C3); } #ifdef PECULIAR_486 From e8d591dc710158bae6b53c8b7a0172351025c6e2 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:12 +0100 Subject: [PATCH 044/890] x86: lindent arch/i386/math-emu, cleanup manually clean up some of the damage that lindent caused. (this is a separate commit so that in the unlikely case of a typo we can bisect it down to the manual edits.) Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/math-emu/errors.c | 6 ++-- arch/x86/math-emu/fpu_emu.h | 12 +++---- arch/x86/math-emu/fpu_entry.c | 6 ++-- arch/x86/math-emu/fpu_etc.c | 8 ++--- arch/x86/math-emu/fpu_proto.h | 62 ++++++++++++++++----------------- arch/x86/math-emu/fpu_trig.c | 38 ++++++++++---------- arch/x86/math-emu/poly.h | 10 +++--- arch/x86/math-emu/poly_2xm1.c | 2 +- arch/x86/math-emu/poly_atan.c | 4 +-- arch/x86/math-emu/poly_l2.c | 4 +-- arch/x86/math-emu/poly_sin.c | 4 +-- arch/x86/math-emu/poly_tan.c | 2 +- arch/x86/math-emu/reg_convert.c | 2 +- arch/x86/math-emu/reg_ld_str.c | 42 +++++++++++----------- 14 files changed, 101 insertions(+), 101 deletions(-) diff --git a/arch/x86/math-emu/errors.c b/arch/x86/math-emu/errors.c index 7cb5bf3495b2..145b68a99516 100644 --- a/arch/x86/math-emu/errors.c +++ b/arch/x86/math-emu/errors.c @@ -374,7 +374,7 @@ asmlinkage void FPU_exception(int n) /* Real operation attempted on a NaN. */ /* Returns < 0 if the exception is unmasked */ -int real_1op_NaN(FPU_REG * a) +int real_1op_NaN(FPU_REG *a) { int signalling, isNaN; @@ -573,7 +573,7 @@ asmlinkage int denormal_operand(void) } } -asmlinkage int arith_overflow(FPU_REG * dest) +asmlinkage int arith_overflow(FPU_REG *dest) { int tag = TAG_Valid; @@ -601,7 +601,7 @@ asmlinkage int arith_overflow(FPU_REG * dest) } -asmlinkage int arith_underflow(FPU_REG * dest) +asmlinkage int arith_underflow(FPU_REG *dest) { int tag = TAG_Valid; diff --git a/arch/x86/math-emu/fpu_emu.h b/arch/x86/math-emu/fpu_emu.h index 656dd4c04b1b..4dae511c85ad 100644 --- a/arch/x86/math-emu/fpu_emu.h +++ b/arch/x86/math-emu/fpu_emu.h @@ -122,7 +122,7 @@ struct fpu__reg { typedef void (*FUNC) (void); typedef struct fpu__reg FPU_REG; -typedef void (*FUNC_ST0) (FPU_REG * st0_ptr, u_char st0_tag); +typedef void (*FUNC_ST0) (FPU_REG *st0_ptr, u_char st0_tag); typedef struct { u_char address_size, operand_size, segment; } overrides; @@ -166,7 +166,7 @@ extern u_char const data_sizes_16[32]; #define signpositive(a) ( (signbyte(a) & 0x80) == 0 ) #define signnegative(a) (signbyte(a) & 0x80) -static inline void reg_copy(FPU_REG const *x, FPU_REG * y) +static inline void reg_copy(FPU_REG const *x, FPU_REG *y) { *(short *)&(y->exp) = *(const short *)&(x->exp); *(long long *)&(y->sigl) = *(const long long *)&(x->sigl); @@ -187,8 +187,8 @@ static inline void reg_copy(FPU_REG const *x, FPU_REG * y) /*----- Prototypes for functions written in assembler -----*/ /* extern void reg_move(FPU_REG *a, FPU_REG *b); */ -asmlinkage int FPU_normalize(FPU_REG * x); -asmlinkage int FPU_normalize_nuo(FPU_REG * x); +asmlinkage int FPU_normalize(FPU_REG *x); +asmlinkage int FPU_normalize_nuo(FPU_REG *x); asmlinkage int FPU_u_sub(FPU_REG const *arg1, FPU_REG const *arg2, FPU_REG * answ, unsigned int control_w, u_char sign, int expa, int expb); @@ -200,12 +200,12 @@ asmlinkage int FPU_u_div(FPU_REG const *arg1, FPU_REG const *arg2, asmlinkage int FPU_u_add(FPU_REG const *arg1, FPU_REG const *arg2, FPU_REG * answ, unsigned int control_w, u_char sign, int expa, int expb); -asmlinkage int wm_sqrt(FPU_REG * n, int dummy1, int dummy2, +asmlinkage int wm_sqrt(FPU_REG *n, int dummy1, int dummy2, unsigned int control_w, u_char sign); asmlinkage unsigned FPU_shrx(void *l, unsigned x); asmlinkage unsigned FPU_shrxs(void *v, unsigned x); asmlinkage unsigned long FPU_div_small(unsigned long long *x, unsigned long y); -asmlinkage int FPU_round(FPU_REG * arg, unsigned int extent, int dummy, +asmlinkage int FPU_round(FPU_REG *arg, unsigned int extent, int dummy, unsigned int control_w, u_char sign); #ifndef MAKING_PROTO diff --git a/arch/x86/math-emu/fpu_entry.c b/arch/x86/math-emu/fpu_entry.c index cbb8717f09fd..377c60dfa2f0 100644 --- a/arch/x86/math-emu/fpu_entry.c +++ b/arch/x86/math-emu/fpu_entry.c @@ -126,7 +126,7 @@ static u_char const type_table[64] = { u_char emulating = 0; #endif /* RE_ENTRANT_CHECKING */ -static int valid_prefix(u_char * Byte, u_char __user ** fpu_eip, +static int valid_prefix(u_char *Byte, u_char __user ** fpu_eip, overrides * override); asmlinkage void math_emulate(long arg) @@ -580,7 +580,7 @@ asmlinkage void math_emulate(long arg) all prefix bytes, further changes are needed in the emulator code which accesses user address space. Access to separate segments is important for msdos emulation. */ -static int valid_prefix(u_char * Byte, u_char __user ** fpu_eip, +static int valid_prefix(u_char *Byte, u_char __user **fpu_eip, overrides * override) { u_char byte; @@ -673,7 +673,7 @@ void math_abort(struct info *info, unsigned int signal) #define sstatus_word() \ ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top)) -int restore_i387_soft(void *s387, struct _fpstate __user * buf) +int restore_i387_soft(void *s387, struct _fpstate __user *buf) { u_char __user *d = (u_char __user *) buf; int offset, other, i, tags, regnr, tag, newtop; diff --git a/arch/x86/math-emu/fpu_etc.c b/arch/x86/math-emu/fpu_etc.c index e73631e0cde9..233e5af566f5 100644 --- a/arch/x86/math-emu/fpu_etc.c +++ b/arch/x86/math-emu/fpu_etc.c @@ -16,7 +16,7 @@ #include "status_w.h" #include "reg_constant.h" -static void fchs(FPU_REG * st0_ptr, u_char st0tag) +static void fchs(FPU_REG *st0_ptr, u_char st0tag) { if (st0tag ^ TAG_Empty) { signbyte(st0_ptr) ^= SIGN_NEG; @@ -25,7 +25,7 @@ static void fchs(FPU_REG * st0_ptr, u_char st0tag) FPU_stack_underflow(); } -static void fabs(FPU_REG * st0_ptr, u_char st0tag) +static void fabs(FPU_REG *st0_ptr, u_char st0tag) { if (st0tag ^ TAG_Empty) { setpositive(st0_ptr); @@ -34,7 +34,7 @@ static void fabs(FPU_REG * st0_ptr, u_char st0tag) FPU_stack_underflow(); } -static void ftst_(FPU_REG * st0_ptr, u_char st0tag) +static void ftst_(FPU_REG *st0_ptr, u_char st0tag) { switch (st0tag) { case TAG_Zero: @@ -85,7 +85,7 @@ static void ftst_(FPU_REG * st0_ptr, u_char st0tag) } } -static void fxam(FPU_REG * st0_ptr, u_char st0tag) +static void fxam(FPU_REG *st0_ptr, u_char st0tag) { int c = 0; switch (st0tag) { diff --git a/arch/x86/math-emu/fpu_proto.h b/arch/x86/math-emu/fpu_proto.h index 0f6384102afd..aa49b6a0d850 100644 --- a/arch/x86/math-emu/fpu_proto.h +++ b/arch/x86/math-emu/fpu_proto.h @@ -5,7 +5,7 @@ extern void FPU_illegal(void); extern void FPU_printall(void); asmlinkage void FPU_exception(int n); -extern int real_1op_NaN(FPU_REG * a); +extern int real_1op_NaN(FPU_REG *a); extern int real_2op_NaN(FPU_REG const *b, u_char tagb, int deststnr, FPU_REG const *defaultNaN); asmlinkage int arith_invalid(int deststnr); @@ -14,8 +14,8 @@ extern int set_precision_flag(int flags); asmlinkage void set_precision_flag_up(void); asmlinkage void set_precision_flag_down(void); asmlinkage int denormal_operand(void); -asmlinkage int arith_overflow(FPU_REG * dest); -asmlinkage int arith_underflow(FPU_REG * dest); +asmlinkage int arith_overflow(FPU_REG *dest); +asmlinkage int arith_underflow(FPU_REG *dest); extern void FPU_stack_overflow(void); extern void FPU_stack_underflow(void); extern void FPU_stack_underflow_i(int i); @@ -84,19 +84,19 @@ extern void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip, extern int FPU_load_store(u_char type, fpu_addr_modes addr_modes, void __user * data_address); /* poly_2xm1.c */ -extern int poly_2xm1(u_char sign, FPU_REG * arg, FPU_REG * result); +extern int poly_2xm1(u_char sign, FPU_REG * arg, FPU_REG *result); /* poly_atan.c */ -extern void poly_atan(FPU_REG * st0_ptr, u_char st0_tag, FPU_REG * st1_ptr, +extern void poly_atan(FPU_REG * st0_ptr, u_char st0_tag, FPU_REG *st1_ptr, u_char st1_tag); /* poly_l2.c */ -extern void poly_l2(FPU_REG * st0_ptr, FPU_REG * st1_ptr, u_char st1_sign); -extern int poly_l2p1(u_char s0, u_char s1, FPU_REG * r0, FPU_REG * r1, +extern void poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign); +extern int poly_l2p1(u_char s0, u_char s1, FPU_REG *r0, FPU_REG *r1, FPU_REG * d); /* poly_sin.c */ -extern void poly_sine(FPU_REG * st0_ptr); -extern void poly_cos(FPU_REG * st0_ptr); +extern void poly_sine(FPU_REG *st0_ptr); +extern void poly_cos(FPU_REG *st0_ptr); /* poly_tan.c */ -extern void poly_tan(FPU_REG * st0_ptr); +extern void poly_tan(FPU_REG *st0_ptr); /* reg_add_sub.c */ extern int FPU_add(FPU_REG const *b, u_char tagb, int destrnr, int control_w); extern int FPU_sub(int flags, int rm, int control_w); @@ -111,34 +111,34 @@ extern void fucompp(void); /* reg_constant.c */ extern void fconst(void); /* reg_ld_str.c */ -extern int FPU_load_extended(long double __user * s, int stnr); -extern int FPU_load_double(double __user * dfloat, FPU_REG * loaded_data); -extern int FPU_load_single(float __user * single, FPU_REG * loaded_data); -extern int FPU_load_int64(long long __user * _s); -extern int FPU_load_int32(long __user * _s, FPU_REG * loaded_data); -extern int FPU_load_int16(short __user * _s, FPU_REG * loaded_data); -extern int FPU_load_bcd(u_char __user * s); -extern int FPU_store_extended(FPU_REG * st0_ptr, u_char st0_tag, +extern int FPU_load_extended(long double __user *s, int stnr); +extern int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data); +extern int FPU_load_single(float __user *single, FPU_REG *loaded_data); +extern int FPU_load_int64(long long __user *_s); +extern int FPU_load_int32(long __user *_s, FPU_REG *loaded_data); +extern int FPU_load_int16(short __user *_s, FPU_REG *loaded_data); +extern int FPU_load_bcd(u_char __user *s); +extern int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double __user * d); -extern int FPU_store_double(FPU_REG * st0_ptr, u_char st0_tag, +extern int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user * dfloat); -extern int FPU_store_single(FPU_REG * st0_ptr, u_char st0_tag, +extern int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user * single); -extern int FPU_store_int64(FPU_REG * st0_ptr, u_char st0_tag, +extern int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user * d); -extern int FPU_store_int32(FPU_REG * st0_ptr, u_char st0_tag, long __user * d); -extern int FPU_store_int16(FPU_REG * st0_ptr, u_char st0_tag, short __user * d); -extern int FPU_store_bcd(FPU_REG * st0_ptr, u_char st0_tag, u_char __user * d); -extern int FPU_round_to_int(FPU_REG * r, u_char tag); -extern u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user * s); -extern void frstor(fpu_addr_modes addr_modes, u_char __user * data_address); -extern u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user * d); -extern void fsave(fpu_addr_modes addr_modes, u_char __user * data_address); -extern int FPU_tagof(FPU_REG * ptr); +extern int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d); +extern int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d); +extern int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d); +extern int FPU_round_to_int(FPU_REG *r, u_char tag); +extern u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s); +extern void frstor(fpu_addr_modes addr_modes, u_char __user *data_address); +extern u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d); +extern void fsave(fpu_addr_modes addr_modes, u_char __user *data_address); +extern int FPU_tagof(FPU_REG *ptr); /* reg_mul.c */ extern int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w); extern int FPU_div(int flags, int regrm, int control_w); /* reg_convert.c */ -extern int FPU_to_exp16(FPU_REG const *a, FPU_REG * x); +extern int FPU_to_exp16(FPU_REG const *a, FPU_REG *x); #endif /* _FPU_PROTO_H */ diff --git a/arch/x86/math-emu/fpu_trig.c b/arch/x86/math-emu/fpu_trig.c index e5316a288a6e..ecd06680581c 100644 --- a/arch/x86/math-emu/fpu_trig.c +++ b/arch/x86/math-emu/fpu_trig.c @@ -30,7 +30,7 @@ static void rem_kernel(unsigned long long st0, unsigned long long *y, /* Limited measurements show no results worse than 64 bit precision except for the results for arguments close to 2^63, where the precision of the result sometimes degrades to about 63.9 bits */ -static int trig_arg(FPU_REG * st0_ptr, int even) +static int trig_arg(FPU_REG *st0_ptr, int even) { FPU_REG tmp; u_char tmptag; @@ -176,7 +176,7 @@ static void convert_l2reg(long const *arg, int deststnr) return; } -static void single_arg_error(FPU_REG * st0_ptr, u_char st0_tag) +static void single_arg_error(FPU_REG *st0_ptr, u_char st0_tag) { if (st0_tag == TAG_Empty) FPU_stack_underflow(); /* Puts a QNaN in st(0) */ @@ -188,7 +188,7 @@ static void single_arg_error(FPU_REG * st0_ptr, u_char st0_tag) #endif /* PARANOID */ } -static void single_arg_2_error(FPU_REG * st0_ptr, u_char st0_tag) +static void single_arg_2_error(FPU_REG *st0_ptr, u_char st0_tag) { int isNaN; @@ -229,7 +229,7 @@ static void single_arg_2_error(FPU_REG * st0_ptr, u_char st0_tag) /*---------------------------------------------------------------------------*/ -static void f2xm1(FPU_REG * st0_ptr, u_char tag) +static void f2xm1(FPU_REG *st0_ptr, u_char tag) { FPU_REG a; @@ -272,7 +272,7 @@ static void f2xm1(FPU_REG * st0_ptr, u_char tag) } } -static void fptan(FPU_REG * st0_ptr, u_char st0_tag) +static void fptan(FPU_REG *st0_ptr, u_char st0_tag) { FPU_REG *st_new_ptr; int q; @@ -351,7 +351,7 @@ static void fptan(FPU_REG * st0_ptr, u_char st0_tag) single_arg_2_error(st0_ptr, st0_tag); } -static void fxtract(FPU_REG * st0_ptr, u_char st0_tag) +static void fxtract(FPU_REG *st0_ptr, u_char st0_tag) { FPU_REG *st_new_ptr; u_char sign; @@ -444,7 +444,7 @@ static void fincstp(void) top++; } -static void fsqrt_(FPU_REG * st0_ptr, u_char st0_tag) +static void fsqrt_(FPU_REG *st0_ptr, u_char st0_tag) { int expon; @@ -502,7 +502,7 @@ static void fsqrt_(FPU_REG * st0_ptr, u_char st0_tag) } -static void frndint_(FPU_REG * st0_ptr, u_char st0_tag) +static void frndint_(FPU_REG *st0_ptr, u_char st0_tag) { int flags, tag; @@ -546,7 +546,7 @@ static void frndint_(FPU_REG * st0_ptr, u_char st0_tag) single_arg_error(st0_ptr, st0_tag); } -static int fsin(FPU_REG * st0_ptr, u_char tag) +static int fsin(FPU_REG *st0_ptr, u_char tag) { u_char arg_sign = getsign(st0_ptr); @@ -607,7 +607,7 @@ static int fsin(FPU_REG * st0_ptr, u_char tag) } } -static int f_cos(FPU_REG * st0_ptr, u_char tag) +static int f_cos(FPU_REG *st0_ptr, u_char tag) { u_char st0_sign; @@ -677,12 +677,12 @@ static int f_cos(FPU_REG * st0_ptr, u_char tag) } } -static void fcos(FPU_REG * st0_ptr, u_char st0_tag) +static void fcos(FPU_REG *st0_ptr, u_char st0_tag) { f_cos(st0_ptr, st0_tag); } -static void fsincos(FPU_REG * st0_ptr, u_char st0_tag) +static void fsincos(FPU_REG *st0_ptr, u_char st0_tag) { FPU_REG *st_new_ptr; FPU_REG arg; @@ -775,7 +775,7 @@ static void rem_kernel(unsigned long long st0, unsigned long long *y, /* Remainder of st(0) / st(1) */ /* This routine produces exact results, i.e. there is never any rounding or truncation, etc of the result. */ -static void do_fprem(FPU_REG * st0_ptr, u_char st0_tag, int round) +static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round) { FPU_REG *st1_ptr = &st(1); u_char st1_tag = FPU_gettagi(1); @@ -1017,7 +1017,7 @@ static void do_fprem(FPU_REG * st0_ptr, u_char st0_tag, int round) } /* ST(1) <- ST(1) * log ST; pop ST */ -static void fyl2x(FPU_REG * st0_ptr, u_char st0_tag) +static void fyl2x(FPU_REG *st0_ptr, u_char st0_tag) { FPU_REG *st1_ptr = &st(1), exponent; u_char st1_tag = FPU_gettagi(1); @@ -1188,7 +1188,7 @@ static void fyl2x(FPU_REG * st0_ptr, u_char st0_tag) FPU_pop(); } -static void fpatan(FPU_REG * st0_ptr, u_char st0_tag) +static void fpatan(FPU_REG *st0_ptr, u_char st0_tag) { FPU_REG *st1_ptr = &st(1); u_char st1_tag = FPU_gettagi(1); @@ -1298,17 +1298,17 @@ static void fpatan(FPU_REG * st0_ptr, u_char st0_tag) set_precision_flag_up(); /* We do not really know if up or down */ } -static void fprem(FPU_REG * st0_ptr, u_char st0_tag) +static void fprem(FPU_REG *st0_ptr, u_char st0_tag) { do_fprem(st0_ptr, st0_tag, RC_CHOP); } -static void fprem1(FPU_REG * st0_ptr, u_char st0_tag) +static void fprem1(FPU_REG *st0_ptr, u_char st0_tag) { do_fprem(st0_ptr, st0_tag, RC_RND); } -static void fyl2xp1(FPU_REG * st0_ptr, u_char st0_tag) +static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag) { u_char sign, sign1; FPU_REG *st1_ptr = &st(1), a, b; @@ -1477,7 +1477,7 @@ static void fyl2xp1(FPU_REG * st0_ptr, u_char st0_tag) } -static void fscale(FPU_REG * st0_ptr, u_char st0_tag) +static void fscale(FPU_REG *st0_ptr, u_char st0_tag) { FPU_REG *st1_ptr = &st(1); u_char st1_tag = FPU_gettagi(1); diff --git a/arch/x86/math-emu/poly.h b/arch/x86/math-emu/poly.h index f317de7d8864..168eb44c93c8 100644 --- a/arch/x86/math-emu/poly.h +++ b/arch/x86/math-emu/poly.h @@ -33,12 +33,12 @@ asmlinkage void polynomial_Xsig(Xsig *, const unsigned long long *x, asmlinkage void mul32_Xsig(Xsig *, const unsigned long mult); asmlinkage void mul64_Xsig(Xsig *, const unsigned long long *mult); -asmlinkage void mul_Xsig_Xsig(Xsig * dest, const Xsig * mult); +asmlinkage void mul_Xsig_Xsig(Xsig *dest, const Xsig *mult); asmlinkage void shr_Xsig(Xsig *, const int n); asmlinkage int round_Xsig(Xsig *); asmlinkage int norm_Xsig(Xsig *); -asmlinkage void div_Xsig(Xsig * x1, const Xsig * x2, const Xsig * dest); +asmlinkage void div_Xsig(Xsig *x1, const Xsig *x2, const Xsig *dest); /* Macro to extract the most significant 32 bits from a long long */ #define LL_MSW(x) (((unsigned long *)&x)[1]) @@ -70,7 +70,7 @@ static inline unsigned long mul_32_32(const unsigned long arg1, } /* Add the 12 byte Xsig x2 to Xsig dest, with no checks for overflow. */ -static inline void add_Xsig_Xsig(Xsig * dest, const Xsig * x2) +static inline void add_Xsig_Xsig(Xsig *dest, const Xsig *x2) { asm volatile ("movl %1,%%edi; movl %2,%%esi;\n" "movl (%%esi),%%eax; addl %%eax,(%%edi);\n" @@ -84,7 +84,7 @@ static inline void add_Xsig_Xsig(Xsig * dest, const Xsig * x2) /* Note: the constraints in the asm statement didn't always work properly with gcc 2.5.8. Changing from using edi to using ecx got around the problem, but keep fingers crossed! */ -static inline void add_two_Xsig(Xsig * dest, const Xsig * x2, long int *exp) +static inline void add_two_Xsig(Xsig *dest, const Xsig *x2, long int *exp) { asm volatile ("movl %2,%%ecx; movl %3,%%esi;\n" "movl (%%esi),%%eax; addl %%eax,(%%ecx);\n" @@ -101,7 +101,7 @@ static inline void add_two_Xsig(Xsig * dest, const Xsig * x2, long int *exp) /* Negate (subtract from 1.0) the 12 byte Xsig */ /* This is faster in a loop on my 386 than using the "neg" instruction. */ -static inline void negate_Xsig(Xsig * x) +static inline void negate_Xsig(Xsig *x) { asm volatile ("movl %1,%%esi;\n" "xorl %%ecx,%%ecx;\n" diff --git a/arch/x86/math-emu/poly_2xm1.c b/arch/x86/math-emu/poly_2xm1.c index d8f2be3c8383..b00e9e10cdce 100644 --- a/arch/x86/math-emu/poly_2xm1.c +++ b/arch/x86/math-emu/poly_2xm1.c @@ -49,7 +49,7 @@ static const Xsig *shiftterm[] = { &shiftterm0, &shiftterm1, /*--- poly_2xm1() -----------------------------------------------------------+ | Requires st(0) which is TAG_Valid and < 1. | +---------------------------------------------------------------------------*/ -int poly_2xm1(u_char sign, FPU_REG * arg, FPU_REG * result) +int poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result) { long int exponent, shift; unsigned long long Xll; diff --git a/arch/x86/math-emu/poly_atan.c b/arch/x86/math-emu/poly_atan.c index 2f4ac8143fc3..20c28e58e2d4 100644 --- a/arch/x86/math-emu/poly_atan.c +++ b/arch/x86/math-emu/poly_atan.c @@ -48,8 +48,8 @@ static const Xsig pi_signif = MK_XSIG(0xc90fdaa2, 0x2168c234, 0xc4c6628b); /*--- poly_atan() -----------------------------------------------------------+ | | +---------------------------------------------------------------------------*/ -void poly_atan(FPU_REG * st0_ptr, u_char st0_tag, - FPU_REG * st1_ptr, u_char st1_tag) +void poly_atan(FPU_REG *st0_ptr, u_char st0_tag, + FPU_REG *st1_ptr, u_char st1_tag) { u_char transformed, inverted, sign1, sign2; int exponent; diff --git a/arch/x86/math-emu/poly_l2.c b/arch/x86/math-emu/poly_l2.c index c0102ae87511..8e2ff4b28a0a 100644 --- a/arch/x86/math-emu/poly_l2.c +++ b/arch/x86/math-emu/poly_l2.c @@ -23,7 +23,7 @@ static void log2_kernel(FPU_REG const *arg, u_char argsign, /*--- poly_l2() -------------------------------------------------------------+ | Base 2 logarithm by a polynomial approximation. | +---------------------------------------------------------------------------*/ -void poly_l2(FPU_REG * st0_ptr, FPU_REG * st1_ptr, u_char st1_sign) +void poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign) { long int exponent, expon, expon_expon; Xsig accumulator, expon_accum, yaccum; @@ -178,7 +178,7 @@ static const unsigned long leadterm = 0xb8000000; | Base 2 logarithm by a polynomial approximation. | | log2(x+1) | +---------------------------------------------------------------------------*/ -static void log2_kernel(FPU_REG const *arg, u_char argsign, Xsig * accum_result, +static void log2_kernel(FPU_REG const *arg, u_char argsign, Xsig *accum_result, long int *expon) { long int exponent, adj; diff --git a/arch/x86/math-emu/poly_sin.c b/arch/x86/math-emu/poly_sin.c index 7273ae0c7692..b862039c728e 100644 --- a/arch/x86/math-emu/poly_sin.c +++ b/arch/x86/math-emu/poly_sin.c @@ -54,7 +54,7 @@ static const unsigned long long neg_terms_h[N_COEFF_NH] = { /*--- poly_sine() -----------------------------------------------------------+ | | +---------------------------------------------------------------------------*/ -void poly_sine(FPU_REG * st0_ptr) +void poly_sine(FPU_REG *st0_ptr) { int exponent, echange; Xsig accumulator, argSqrd, argTo4; @@ -197,7 +197,7 @@ void poly_sine(FPU_REG * st0_ptr) /*--- poly_cos() ------------------------------------------------------------+ | | +---------------------------------------------------------------------------*/ -void poly_cos(FPU_REG * st0_ptr) +void poly_cos(FPU_REG *st0_ptr) { FPU_REG result; long int exponent, exp2, echange; diff --git a/arch/x86/math-emu/poly_tan.c b/arch/x86/math-emu/poly_tan.c index c0d181e39229..1875763e0c02 100644 --- a/arch/x86/math-emu/poly_tan.c +++ b/arch/x86/math-emu/poly_tan.c @@ -47,7 +47,7 @@ static const unsigned long long twothirds = 0xaaaaaaaaaaaaaaabLL; /*--- poly_tan() ------------------------------------------------------------+ | | +---------------------------------------------------------------------------*/ -void poly_tan(FPU_REG * st0_ptr) +void poly_tan(FPU_REG *st0_ptr) { long int exponent; int invert; diff --git a/arch/x86/math-emu/reg_convert.c b/arch/x86/math-emu/reg_convert.c index afd31b31000d..108060779977 100644 --- a/arch/x86/math-emu/reg_convert.c +++ b/arch/x86/math-emu/reg_convert.c @@ -13,7 +13,7 @@ #include "exception.h" #include "fpu_emu.h" -int FPU_to_exp16(FPU_REG const *a, FPU_REG * x) +int FPU_to_exp16(FPU_REG const *a, FPU_REG *x) { int sign = getsign(a); diff --git a/arch/x86/math-emu/reg_ld_str.c b/arch/x86/math-emu/reg_ld_str.c index 0b2ca8dc2988..799d4af5be66 100644 --- a/arch/x86/math-emu/reg_ld_str.c +++ b/arch/x86/math-emu/reg_ld_str.c @@ -35,7 +35,7 @@ #define SINGLE_Ebias 127 #define SINGLE_Emin (-126) /* smallest valid exponent */ -static u_char normalize_no_excep(FPU_REG * r, int exp, int sign) +static u_char normalize_no_excep(FPU_REG *r, int exp, int sign) { u_char tag; @@ -49,7 +49,7 @@ static u_char normalize_no_excep(FPU_REG * r, int exp, int sign) return tag; } -int FPU_tagof(FPU_REG * ptr) +int FPU_tagof(FPU_REG *ptr) { int exp; @@ -78,7 +78,7 @@ int FPU_tagof(FPU_REG * ptr) } /* Get a long double from user memory */ -int FPU_load_extended(long double __user * s, int stnr) +int FPU_load_extended(long double __user *s, int stnr) { FPU_REG *sti_ptr = &st(stnr); @@ -91,7 +91,7 @@ int FPU_load_extended(long double __user * s, int stnr) } /* Get a double from user memory */ -int FPU_load_double(double __user * dfloat, FPU_REG * loaded_data) +int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data) { int exp, tag, negative; unsigned m64, l64; @@ -152,7 +152,7 @@ int FPU_load_double(double __user * dfloat, FPU_REG * loaded_data) } /* Get a float from user memory */ -int FPU_load_single(float __user * single, FPU_REG * loaded_data) +int FPU_load_single(float __user *single, FPU_REG *loaded_data) { unsigned m32; int exp, tag, negative; @@ -206,7 +206,7 @@ int FPU_load_single(float __user * single, FPU_REG * loaded_data) } /* Get a long long from user memory */ -int FPU_load_int64(long long __user * _s) +int FPU_load_int64(long long __user *_s) { long long s; int sign; @@ -236,7 +236,7 @@ int FPU_load_int64(long long __user * _s) } /* Get a long from user memory */ -int FPU_load_int32(long __user * _s, FPU_REG * loaded_data) +int FPU_load_int32(long __user *_s, FPU_REG *loaded_data) { long s; int negative; @@ -265,7 +265,7 @@ int FPU_load_int32(long __user * _s, FPU_REG * loaded_data) } /* Get a short from user memory */ -int FPU_load_int16(short __user * _s, FPU_REG * loaded_data) +int FPU_load_int16(short __user *_s, FPU_REG *loaded_data) { int s, negative; @@ -294,7 +294,7 @@ int FPU_load_int16(short __user * _s, FPU_REG * loaded_data) } /* Get a packed bcd array from user memory */ -int FPU_load_bcd(u_char __user * s) +int FPU_load_bcd(u_char __user *s) { FPU_REG *st0_ptr = &st(0); int pos; @@ -333,7 +333,7 @@ int FPU_load_bcd(u_char __user * s) /*===========================================================================*/ /* Put a long double into user memory */ -int FPU_store_extended(FPU_REG * st0_ptr, u_char st0_tag, +int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double __user * d) { /* @@ -375,7 +375,7 @@ int FPU_store_extended(FPU_REG * st0_ptr, u_char st0_tag, } /* Put a double into user memory */ -int FPU_store_double(FPU_REG * st0_ptr, u_char st0_tag, double __user * dfloat) +int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat) { unsigned long l[2]; unsigned long increment = 0; /* avoid gcc warnings */ @@ -565,7 +565,7 @@ int FPU_store_double(FPU_REG * st0_ptr, u_char st0_tag, double __user * dfloat) } /* Put a float into user memory */ -int FPU_store_single(FPU_REG * st0_ptr, u_char st0_tag, float __user * single) +int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single) { long templ = 0; unsigned long increment = 0; /* avoid gcc warnings */ @@ -754,7 +754,7 @@ int FPU_store_single(FPU_REG * st0_ptr, u_char st0_tag, float __user * single) } /* Put a long long into user memory */ -int FPU_store_int64(FPU_REG * st0_ptr, u_char st0_tag, long long __user * d) +int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d) { FPU_REG t; long long tll; @@ -804,7 +804,7 @@ int FPU_store_int64(FPU_REG * st0_ptr, u_char st0_tag, long long __user * d) } /* Put a long into user memory */ -int FPU_store_int32(FPU_REG * st0_ptr, u_char st0_tag, long __user * d) +int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d) { FPU_REG t; int precision_loss; @@ -850,7 +850,7 @@ int FPU_store_int32(FPU_REG * st0_ptr, u_char st0_tag, long __user * d) } /* Put a short into user memory */ -int FPU_store_int16(FPU_REG * st0_ptr, u_char st0_tag, short __user * d) +int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d) { FPU_REG t; int precision_loss; @@ -896,7 +896,7 @@ int FPU_store_int16(FPU_REG * st0_ptr, u_char st0_tag, short __user * d) } /* Put a packed bcd array into user memory */ -int FPU_store_bcd(FPU_REG * st0_ptr, u_char st0_tag, u_char __user * d) +int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d) { FPU_REG t; unsigned long long ll; @@ -971,7 +971,7 @@ int FPU_store_bcd(FPU_REG * st0_ptr, u_char st0_tag, u_char __user * d) /* Overflow is signalled by a non-zero return value (in eax). In the case of overflow, the returned significand always has the largest possible value */ -int FPU_round_to_int(FPU_REG * r, u_char tag) +int FPU_round_to_int(FPU_REG *r, u_char tag) { u_char very_big; unsigned eax; @@ -1028,7 +1028,7 @@ int FPU_round_to_int(FPU_REG * r, u_char tag) /*===========================================================================*/ -u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user * s) +u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s) { unsigned short tag_word = 0; u_char tag; @@ -1121,7 +1121,7 @@ u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user * s) return s; } -void frstor(fpu_addr_modes addr_modes, u_char __user * data_address) +void frstor(fpu_addr_modes addr_modes, u_char __user *data_address) { int i, regnr; u_char __user *s = fldenv(addr_modes, data_address); @@ -1144,7 +1144,7 @@ void frstor(fpu_addr_modes addr_modes, u_char __user * data_address) } -u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user * d) +u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d) { if ((addr_modes.default_mode == VM86) || ((addr_modes.default_mode == PM16) @@ -1200,7 +1200,7 @@ u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user * d) return d; } -void fsave(fpu_addr_modes addr_modes, u_char __user * data_address) +void fsave(fpu_addr_modes addr_modes, u_char __user *data_address) { u_char __user *d; int offset = (top & 7) * 10, other = 80 - offset; From 05fccb0e3840248324a96b320562210410be73dc Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:30:12 +0100 Subject: [PATCH 045/890] x86: code cleanups in arch/x86/kernel/pci-gart_64.c code cleanups: errors lines of code errors/KLOC arch/x86/kernel/pci-gart_64.c 183 748 244.6 arch/x86/kernel/pci-gart_64.c 0 790 0 Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/pci-gart_64.c | 514 ++++++++++++++++++---------------- 1 file changed, 279 insertions(+), 235 deletions(-) diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 06bcba536045..d2b46b489412 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -1,12 +1,12 @@ /* * Dynamic DMA mapping support for AMD Hammer. - * + * * Use the integrated AGP GART in the Hammer northbridge as an IOMMU for PCI. * This allows to use PCI devices that only support 32bit addresses on systems - * with more than 4GB. + * with more than 4GB. * * See Documentation/DMA-mapping.txt for the interface specification. - * + * * Copyright 2002 Andi Kleen, SuSE Labs. * Subject to the GNU General Public License v2 only. */ @@ -37,23 +37,26 @@ #include static unsigned long iommu_bus_base; /* GART remapping area (physical) */ -static unsigned long iommu_size; /* size of remapping area bytes */ +static unsigned long iommu_size; /* size of remapping area bytes */ static unsigned long iommu_pages; /* .. and in pages */ -static u32 *iommu_gatt_base; /* Remapping table */ +static u32 *iommu_gatt_base; /* Remapping table */ -/* If this is disabled the IOMMU will use an optimized flushing strategy - of only flushing when an mapping is reused. With it true the GART is flushed - for every mapping. Problem is that doing the lazy flush seems to trigger - bugs with some popular PCI cards, in particular 3ware (but has been also - also seen with Qlogic at least). */ +/* + * If this is disabled the IOMMU will use an optimized flushing strategy + * of only flushing when an mapping is reused. With it true the GART is + * flushed for every mapping. Problem is that doing the lazy flush seems + * to trigger bugs with some popular PCI cards, in particular 3ware (but + * has been also also seen with Qlogic at least). + */ int iommu_fullflush = 1; -/* Allocation bitmap for the remapping area */ +/* Allocation bitmap for the remapping area: */ static DEFINE_SPINLOCK(iommu_bitmap_lock); -static unsigned long *iommu_gart_bitmap; /* guarded by iommu_bitmap_lock */ +/* Guarded by iommu_bitmap_lock: */ +static unsigned long *iommu_gart_bitmap; -static u32 gart_unmapped_entry; +static u32 gart_unmapped_entry; #define GPTE_VALID 1 #define GPTE_COHERENT 2 @@ -61,10 +64,10 @@ static u32 gart_unmapped_entry; (((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT) #define GPTE_DECODE(x) (((x) & 0xfffff000) | (((u64)(x) & 0xff0) << 28)) -#define to_pages(addr,size) \ +#define to_pages(addr, size) \ (round_up(((addr) & ~PAGE_MASK) + (size), PAGE_SIZE) >> PAGE_SHIFT) -#define EMERGENCY_PAGES 32 /* = 128KB */ +#define EMERGENCY_PAGES 32 /* = 128KB */ #ifdef CONFIG_AGP #define AGPEXTERN extern @@ -77,130 +80,152 @@ AGPEXTERN int agp_memory_reserved; AGPEXTERN __u32 *agp_gatt_table; static unsigned long next_bit; /* protected by iommu_bitmap_lock */ -static int need_flush; /* global flush state. set for each gart wrap */ +static int need_flush; /* global flush state. set for each gart wrap */ -static unsigned long alloc_iommu(int size) -{ +static unsigned long alloc_iommu(int size) +{ unsigned long offset, flags; - spin_lock_irqsave(&iommu_bitmap_lock, flags); - offset = find_next_zero_string(iommu_gart_bitmap,next_bit,iommu_pages,size); + spin_lock_irqsave(&iommu_bitmap_lock, flags); + offset = find_next_zero_string(iommu_gart_bitmap, next_bit, + iommu_pages, size); if (offset == -1) { need_flush = 1; - offset = find_next_zero_string(iommu_gart_bitmap,0,iommu_pages,size); + offset = find_next_zero_string(iommu_gart_bitmap, 0, + iommu_pages, size); } - if (offset != -1) { - set_bit_string(iommu_gart_bitmap, offset, size); - next_bit = offset+size; - if (next_bit >= iommu_pages) { + if (offset != -1) { + set_bit_string(iommu_gart_bitmap, offset, size); + next_bit = offset+size; + if (next_bit >= iommu_pages) { next_bit = 0; need_flush = 1; - } - } + } + } if (iommu_fullflush) need_flush = 1; - spin_unlock_irqrestore(&iommu_bitmap_lock, flags); + spin_unlock_irqrestore(&iommu_bitmap_lock, flags); + return offset; -} +} static void free_iommu(unsigned long offset, int size) -{ +{ unsigned long flags; + spin_lock_irqsave(&iommu_bitmap_lock, flags); __clear_bit_string(iommu_gart_bitmap, offset, size); spin_unlock_irqrestore(&iommu_bitmap_lock, flags); -} +} -/* +/* * Use global flush state to avoid races with multiple flushers. */ static void flush_gart(void) -{ +{ unsigned long flags; + spin_lock_irqsave(&iommu_bitmap_lock, flags); if (need_flush) { k8_flush_garts(); need_flush = 0; - } + } spin_unlock_irqrestore(&iommu_bitmap_lock, flags); -} +} #ifdef CONFIG_IOMMU_LEAK -#define SET_LEAK(x) if (iommu_leak_tab) \ - iommu_leak_tab[x] = __builtin_return_address(0); -#define CLEAR_LEAK(x) if (iommu_leak_tab) \ - iommu_leak_tab[x] = NULL; +#define SET_LEAK(x) \ + do { \ + if (iommu_leak_tab) \ + iommu_leak_tab[x] = __builtin_return_address(0);\ + } while (0) + +#define CLEAR_LEAK(x) \ + do { \ + if (iommu_leak_tab) \ + iommu_leak_tab[x] = NULL; \ + } while (0) /* Debugging aid for drivers that don't free their IOMMU tables */ -static void **iommu_leak_tab; +static void **iommu_leak_tab; static int leak_trace; static int iommu_leak_pages = 20; + static void dump_leak(void) { int i; - static int dump; - if (dump || !iommu_leak_tab) return; + static int dump; + + if (dump || !iommu_leak_tab) + return; dump = 1; - show_stack(NULL,NULL); - /* Very crude. dump some from the end of the table too */ - printk("Dumping %d pages from end of IOMMU:\n", iommu_leak_pages); - for (i = 0; i < iommu_leak_pages; i+=2) { - printk("%lu: ", iommu_pages-i); + show_stack(NULL, NULL); + + /* Very crude. dump some from the end of the table too */ + printk(KERN_DEBUG "Dumping %d pages from end of IOMMU:\n", + iommu_leak_pages); + for (i = 0; i < iommu_leak_pages; i += 2) { + printk(KERN_DEBUG "%lu: ", iommu_pages-i); printk_address((unsigned long) iommu_leak_tab[iommu_pages-i]); - printk("%c", (i+1)%2 == 0 ? '\n' : ' '); - } - printk("\n"); + printk(KERN_CONT "%c", (i+1)%2 == 0 ? '\n' : ' '); + } + printk(KERN_DEBUG "\n"); } #else -#define SET_LEAK(x) -#define CLEAR_LEAK(x) +# define SET_LEAK(x) +# define CLEAR_LEAK(x) #endif static void iommu_full(struct device *dev, size_t size, int dir) { - /* + /* * Ran out of IOMMU space for this operation. This is very bad. * Unfortunately the drivers cannot handle this operation properly. - * Return some non mapped prereserved space in the aperture and + * Return some non mapped prereserved space in the aperture and * let the Northbridge deal with it. This will result in garbage * in the IO operation. When the size exceeds the prereserved space - * memory corruption will occur or random memory will be DMAed + * memory corruption will occur or random memory will be DMAed * out. Hopefully no network devices use single mappings that big. - */ - - printk(KERN_ERR - "PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n", - size, dev->bus_id); + */ + + printk(KERN_ERR + "PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n", + size, dev->bus_id); if (size > PAGE_SIZE*EMERGENCY_PAGES) { if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL) panic("PCI-DMA: Memory would be corrupted\n"); - if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) - panic(KERN_ERR "PCI-DMA: Random memory would be DMAed\n"); - } - + if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) + panic(KERN_ERR + "PCI-DMA: Random memory would be DMAed\n"); + } #ifdef CONFIG_IOMMU_LEAK - dump_leak(); + dump_leak(); #endif -} - -static inline int need_iommu(struct device *dev, unsigned long addr, size_t size) -{ - u64 mask = *dev->dma_mask; - int high = addr + size > mask; - int mmu = high; - if (force_iommu) - mmu = 1; - return mmu; } -static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t size) -{ +static inline int +need_iommu(struct device *dev, unsigned long addr, size_t size) +{ u64 mask = *dev->dma_mask; int high = addr + size > mask; int mmu = high; - return mmu; + + if (force_iommu) + mmu = 1; + + return mmu; +} + +static inline int +nonforced_iommu(struct device *dev, unsigned long addr, size_t size) +{ + u64 mask = *dev->dma_mask; + int high = addr + size > mask; + int mmu = high; + + return mmu; } /* Map a single continuous physical area into the IOMMU. @@ -208,13 +233,14 @@ static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t */ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, size_t size, int dir) -{ +{ unsigned long npages = to_pages(phys_mem, size); unsigned long iommu_page = alloc_iommu(npages); int i; + if (iommu_page == -1) { if (!nonforced_iommu(dev, phys_mem, size)) - return phys_mem; + return phys_mem; if (panic_on_overflow) panic("dma_map_area overflow %lu bytes\n", size); iommu_full(dev, size, dir); @@ -229,35 +255,39 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, return iommu_bus_base + iommu_page*PAGE_SIZE + (phys_mem & ~PAGE_MASK); } -static dma_addr_t gart_map_simple(struct device *dev, char *buf, - size_t size, int dir) +static dma_addr_t +gart_map_simple(struct device *dev, char *buf, size_t size, int dir) { dma_addr_t map = dma_map_area(dev, virt_to_bus(buf), size, dir); + flush_gart(); + return map; } /* Map a single area into the IOMMU */ -static dma_addr_t gart_map_single(struct device *dev, void *addr, size_t size, int dir) +static dma_addr_t +gart_map_single(struct device *dev, void *addr, size_t size, int dir) { unsigned long phys_mem, bus; if (!dev) dev = &fallback_dev; - phys_mem = virt_to_phys(addr); + phys_mem = virt_to_phys(addr); if (!need_iommu(dev, phys_mem, size)) - return phys_mem; + return phys_mem; bus = gart_map_simple(dev, addr, size, dir); - return bus; + + return bus; } /* * Free a DMA mapping. */ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr, - size_t size, int direction) + size_t size, int direction) { unsigned long iommu_page; int npages; @@ -266,6 +296,7 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr, if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || dma_addr >= iommu_bus_base + iommu_size) return; + iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT; npages = to_pages(dma_addr, size); for (i = 0; i < npages; i++) { @@ -278,7 +309,8 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr, /* * Wrapper for pci_unmap_single working with scatterlists. */ -static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) +static void +gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) { struct scatterlist *s; int i; @@ -303,12 +335,13 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, for_each_sg(sg, s, nents, i) { unsigned long addr = sg_phys(s); - if (nonforced_iommu(dev, addr, s->length)) { + + if (nonforced_iommu(dev, addr, s->length)) { addr = dma_map_area(dev, addr, s->length, dir); - if (addr == bad_dma_address) { - if (i > 0) + if (addr == bad_dma_address) { + if (i > 0) gart_unmap_sg(dev, sg, i, dir); - nents = 0; + nents = 0; sg[0].dma_length = 0; break; } @@ -317,15 +350,16 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, s->dma_length = s->length; } flush_gart(); + return nents; } /* Map multiple scatterlist entries continuous into the first. */ static int __dma_map_cont(struct scatterlist *start, int nelems, - struct scatterlist *sout, unsigned long pages) + struct scatterlist *sout, unsigned long pages) { unsigned long iommu_start = alloc_iommu(pages); - unsigned long iommu_page = iommu_start; + unsigned long iommu_page = iommu_start; struct scatterlist *s; int i; @@ -335,32 +369,33 @@ static int __dma_map_cont(struct scatterlist *start, int nelems, for_each_sg(start, s, nelems, i) { unsigned long pages, addr; unsigned long phys_addr = s->dma_address; - + BUG_ON(s != start && s->offset); if (s == start) { sout->dma_address = iommu_bus_base; sout->dma_address += iommu_page*PAGE_SIZE + s->offset; sout->dma_length = s->length; - } else { - sout->dma_length += s->length; + } else { + sout->dma_length += s->length; } addr = phys_addr; - pages = to_pages(s->offset, s->length); - while (pages--) { - iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr); + pages = to_pages(s->offset, s->length); + while (pages--) { + iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr); SET_LEAK(iommu_page); addr += PAGE_SIZE; iommu_page++; } - } - BUG_ON(iommu_page - iommu_start != pages); + } + BUG_ON(iommu_page - iommu_start != pages); + return 0; } -static inline int dma_map_cont(struct scatterlist *start, int nelems, - struct scatterlist *sout, - unsigned long pages, int need) +static inline int +dma_map_cont(struct scatterlist *start, int nelems, struct scatterlist *sout, + unsigned long pages, int need) { if (!need) { BUG_ON(nelems != 1); @@ -370,22 +405,19 @@ static inline int dma_map_cont(struct scatterlist *start, int nelems, } return __dma_map_cont(start, nelems, sout, pages); } - + /* * DMA map all entries in a scatterlist. - * Merge chunks that have page aligned sizes into a continuous mapping. + * Merge chunks that have page aligned sizes into a continuous mapping. */ -static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, - int dir) +static int +gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) { - int i; - int out; - int start; - unsigned long pages = 0; - int need = 0, nextneed; struct scatterlist *s, *ps, *start_sg, *sgmap; + int need = 0, nextneed, i, out, start; + unsigned long pages = 0; - if (nents == 0) + if (nents == 0) return 0; if (!dev) @@ -397,15 +429,19 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, ps = NULL; /* shut up gcc */ for_each_sg(sg, s, nents, i) { dma_addr_t addr = sg_phys(s); - s->dma_address = addr; - BUG_ON(s->length == 0); - nextneed = need_iommu(dev, addr, s->length); + s->dma_address = addr; + BUG_ON(s->length == 0); + + nextneed = need_iommu(dev, addr, s->length); /* Handle the previous not yet processed entries */ if (i > start) { - /* Can only merge when the last chunk ends on a page - boundary and the new one doesn't have an offset. */ + /* + * Can only merge when the last chunk ends on a + * page boundary and the new one doesn't have an + * offset. + */ if (!iommu_merge || !nextneed || !need || s->offset || (ps->offset + ps->length) % PAGE_SIZE) { if (dma_map_cont(start_sg, i - start, sgmap, @@ -436,6 +472,7 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, error: flush_gart(); gart_unmap_sg(dev, sg, out, dir); + /* When it was forced or merged try again in a dumb way */ if (force_iommu || iommu_merge) { out = dma_map_sg_nonforce(dev, sg, nents, dir); @@ -444,64 +481,68 @@ error: } if (panic_on_overflow) panic("dma_map_sg: overflow on %lu pages\n", pages); + iommu_full(dev, pages << PAGE_SHIFT, dir); for_each_sg(sg, s, nents, i) s->dma_address = bad_dma_address; return 0; -} +} static int no_agp; static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) -{ - unsigned long a; - if (!iommu_size) { - iommu_size = aper_size; - if (!no_agp) - iommu_size /= 2; - } +{ + unsigned long a; - a = aper + iommu_size; + if (!iommu_size) { + iommu_size = aper_size; + if (!no_agp) + iommu_size /= 2; + } + + a = aper + iommu_size; iommu_size -= round_up(a, LARGE_PAGE_SIZE) - a; - if (iommu_size < 64*1024*1024) + if (iommu_size < 64*1024*1024) { printk(KERN_WARNING - "PCI-DMA: Warning: Small IOMMU %luMB. Consider increasing the AGP aperture in BIOS\n",iommu_size>>20); - + "PCI-DMA: Warning: Small IOMMU %luMB." + " Consider increasing the AGP aperture in BIOS\n", + iommu_size >> 20); + } + return iommu_size; -} +} -static __init unsigned read_aperture(struct pci_dev *dev, u32 *size) -{ - unsigned aper_size = 0, aper_base_32; +static __init unsigned read_aperture(struct pci_dev *dev, u32 *size) +{ + unsigned aper_size = 0, aper_base_32, aper_order; u64 aper_base; - unsigned aper_order; - pci_read_config_dword(dev, 0x94, &aper_base_32); + pci_read_config_dword(dev, 0x94, &aper_base_32); pci_read_config_dword(dev, 0x90, &aper_order); - aper_order = (aper_order >> 1) & 7; + aper_order = (aper_order >> 1) & 7; - aper_base = aper_base_32 & 0x7fff; + aper_base = aper_base_32 & 0x7fff; aper_base <<= 25; - aper_size = (32 * 1024 * 1024) << aper_order; - if (aper_base + aper_size > 0x100000000UL || !aper_size) + aper_size = (32 * 1024 * 1024) << aper_order; + if (aper_base + aper_size > 0x100000000UL || !aper_size) aper_base = 0; *size = aper_size; return aper_base; -} +} -/* +/* * Private Northbridge GATT initialization in case we cannot use the - * AGP driver for some reason. + * AGP driver for some reason. */ static __init int init_k8_gatt(struct agp_kern_info *info) -{ +{ + unsigned aper_size, gatt_size, new_aper_size; + unsigned aper_base, new_aper_base; struct pci_dev *dev; void *gatt; - unsigned aper_base, new_aper_base; - unsigned aper_size, gatt_size, new_aper_size; int i; printk(KERN_INFO "PCI-DMA: Disabling AGP.\n"); @@ -509,75 +550,77 @@ static __init int init_k8_gatt(struct agp_kern_info *info) dev = NULL; for (i = 0; i < num_k8_northbridges; i++) { dev = k8_northbridges[i]; - new_aper_base = read_aperture(dev, &new_aper_size); - if (!new_aper_base) - goto nommu; - - if (!aper_base) { + new_aper_base = read_aperture(dev, &new_aper_size); + if (!new_aper_base) + goto nommu; + + if (!aper_base) { aper_size = new_aper_size; aper_base = new_aper_base; - } - if (aper_size != new_aper_size || aper_base != new_aper_base) + } + if (aper_size != new_aper_size || aper_base != new_aper_base) goto nommu; } if (!aper_base) - goto nommu; + goto nommu; info->aper_base = aper_base; - info->aper_size = aper_size>>20; + info->aper_size = aper_size >> 20; - gatt_size = (aper_size >> PAGE_SHIFT) * sizeof(u32); - gatt = (void *)__get_free_pages(GFP_KERNEL, get_order(gatt_size)); - if (!gatt) + gatt_size = (aper_size >> PAGE_SHIFT) * sizeof(u32); + gatt = (void *)__get_free_pages(GFP_KERNEL, get_order(gatt_size)); + if (!gatt) panic("Cannot allocate GATT table"); - if (change_page_attr_addr((unsigned long)gatt, gatt_size >> PAGE_SHIFT, PAGE_KERNEL_NOCACHE)) + if (change_page_attr_addr((unsigned long)gatt, gatt_size >> PAGE_SHIFT, + PAGE_KERNEL_NOCACHE)) panic("Could not set GART PTEs to uncacheable pages"); global_flush_tlb(); - memset(gatt, 0, gatt_size); + memset(gatt, 0, gatt_size); agp_gatt_table = gatt; for (i = 0; i < num_k8_northbridges; i++) { - u32 ctl; - u32 gatt_reg; + u32 gatt_reg; + u32 ctl; dev = k8_northbridges[i]; - gatt_reg = __pa(gatt) >> 12; - gatt_reg <<= 4; + gatt_reg = __pa(gatt) >> 12; + gatt_reg <<= 4; pci_write_config_dword(dev, 0x98, gatt_reg); - pci_read_config_dword(dev, 0x90, &ctl); + pci_read_config_dword(dev, 0x90, &ctl); ctl |= 1; ctl &= ~((1<<4) | (1<<5)); - pci_write_config_dword(dev, 0x90, ctl); + pci_write_config_dword(dev, 0x90, ctl); } flush_gart(); - - printk("PCI-DMA: aperture base @ %x size %u KB\n",aper_base, aper_size>>10); + + printk(KERN_INFO "PCI-DMA: aperture base @ %x size %u KB\n", + aper_base, aper_size>>10); return 0; nommu: - /* Should not happen anymore */ + /* Should not happen anymore */ printk(KERN_ERR "PCI-DMA: More than 4GB of RAM and no IOMMU\n" KERN_ERR "PCI-DMA: 32bit PCI IO may malfunction.\n"); - return -1; -} + return -1; +} extern int agp_amd64_init(void); static const struct dma_mapping_ops gart_dma_ops = { - .mapping_error = NULL, - .map_single = gart_map_single, - .map_simple = gart_map_simple, - .unmap_single = gart_unmap_single, - .sync_single_for_cpu = NULL, - .sync_single_for_device = NULL, - .sync_single_range_for_cpu = NULL, - .sync_single_range_for_device = NULL, - .sync_sg_for_cpu = NULL, - .sync_sg_for_device = NULL, - .map_sg = gart_map_sg, - .unmap_sg = gart_unmap_sg, + .mapping_error = NULL, + .map_single = gart_map_single, + .map_simple = gart_map_simple, + .unmap_single = gart_unmap_single, + .sync_single_for_cpu = NULL, + .sync_single_for_device = NULL, + .sync_single_range_for_cpu = NULL, + .sync_single_range_for_device = NULL, + .sync_sg_for_cpu = NULL, + .sync_sg_for_device = NULL, + .map_sg = gart_map_sg, + .unmap_sg = gart_unmap_sg, }; void gart_iommu_shutdown(void) @@ -588,23 +631,23 @@ void gart_iommu_shutdown(void) if (no_agp && (dma_ops != &gart_dma_ops)) return; - for (i = 0; i < num_k8_northbridges; i++) { - u32 ctl; + for (i = 0; i < num_k8_northbridges; i++) { + u32 ctl; - dev = k8_northbridges[i]; - pci_read_config_dword(dev, 0x90, &ctl); + dev = k8_northbridges[i]; + pci_read_config_dword(dev, 0x90, &ctl); - ctl &= ~1; + ctl &= ~1; - pci_write_config_dword(dev, 0x90, ctl); - } + pci_write_config_dword(dev, 0x90, ctl); + } } void __init gart_iommu_init(void) -{ +{ struct agp_kern_info info; - unsigned long aper_size; unsigned long iommu_start; + unsigned long aper_size; unsigned long scratch; long i; @@ -614,14 +657,14 @@ void __init gart_iommu_init(void) } #ifndef CONFIG_AGP_AMD64 - no_agp = 1; + no_agp = 1; #else /* Makefile puts PCI initialization via subsys_initcall first. */ /* Add other K8 AGP bridge drivers here */ - no_agp = no_agp || - (agp_amd64_init() < 0) || + no_agp = no_agp || + (agp_amd64_init() < 0) || (agp_copy_info(agp_bridge, &info) < 0); -#endif +#endif if (swiotlb) return; @@ -643,77 +686,78 @@ void __init gart_iommu_init(void) } printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n"); - aper_size = info.aper_size * 1024 * 1024; - iommu_size = check_iommu_size(info.aper_base, aper_size); - iommu_pages = iommu_size >> PAGE_SHIFT; + aper_size = info.aper_size * 1024 * 1024; + iommu_size = check_iommu_size(info.aper_base, aper_size); + iommu_pages = iommu_size >> PAGE_SHIFT; - iommu_gart_bitmap = (void*)__get_free_pages(GFP_KERNEL, - get_order(iommu_pages/8)); - if (!iommu_gart_bitmap) - panic("Cannot allocate iommu bitmap\n"); + iommu_gart_bitmap = (void *) __get_free_pages(GFP_KERNEL, + get_order(iommu_pages/8)); + if (!iommu_gart_bitmap) + panic("Cannot allocate iommu bitmap\n"); memset(iommu_gart_bitmap, 0, iommu_pages/8); #ifdef CONFIG_IOMMU_LEAK - if (leak_trace) { - iommu_leak_tab = (void *)__get_free_pages(GFP_KERNEL, + if (leak_trace) { + iommu_leak_tab = (void *)__get_free_pages(GFP_KERNEL, get_order(iommu_pages*sizeof(void *))); - if (iommu_leak_tab) - memset(iommu_leak_tab, 0, iommu_pages * 8); + if (iommu_leak_tab) + memset(iommu_leak_tab, 0, iommu_pages * 8); else - printk("PCI-DMA: Cannot allocate leak trace area\n"); - } + printk(KERN_DEBUG + "PCI-DMA: Cannot allocate leak trace area\n"); + } #endif - /* + /* * Out of IOMMU space handling. - * Reserve some invalid pages at the beginning of the GART. - */ - set_bit_string(iommu_gart_bitmap, 0, EMERGENCY_PAGES); + * Reserve some invalid pages at the beginning of the GART. + */ + set_bit_string(iommu_gart_bitmap, 0, EMERGENCY_PAGES); - agp_memory_reserved = iommu_size; + agp_memory_reserved = iommu_size; printk(KERN_INFO "PCI-DMA: Reserving %luMB of IOMMU area in the AGP aperture\n", - iommu_size>>20); + iommu_size >> 20); - iommu_start = aper_size - iommu_size; - iommu_bus_base = info.aper_base + iommu_start; + iommu_start = aper_size - iommu_size; + iommu_bus_base = info.aper_base + iommu_start; bad_dma_address = iommu_bus_base; iommu_gatt_base = agp_gatt_table + (iommu_start>>PAGE_SHIFT); - /* + /* * Unmap the IOMMU part of the GART. The alias of the page is * always mapped with cache enabled and there is no full cache * coherency across the GART remapping. The unmapping avoids * automatic prefetches from the CPU allocating cache lines in * there. All CPU accesses are done via the direct mapping to * the backing memory. The GART address is only used by PCI - * devices. + * devices. */ clear_kernel_mapping((unsigned long)__va(iommu_bus_base), iommu_size); - /* - * Try to workaround a bug (thanks to BenH) - * Set unmapped entries to a scratch page instead of 0. + /* + * Try to workaround a bug (thanks to BenH) + * Set unmapped entries to a scratch page instead of 0. * Any prefetches that hit unmapped entries won't get an bus abort * then. */ - scratch = get_zeroed_page(GFP_KERNEL); - if (!scratch) + scratch = get_zeroed_page(GFP_KERNEL); + if (!scratch) panic("Cannot allocate iommu scratch page"); gart_unmapped_entry = GPTE_ENCODE(__pa(scratch)); - for (i = EMERGENCY_PAGES; i < iommu_pages; i++) + for (i = EMERGENCY_PAGES; i < iommu_pages; i++) iommu_gatt_base[i] = gart_unmapped_entry; flush_gart(); dma_ops = &gart_dma_ops; -} +} void __init gart_parse_options(char *p) { int arg; #ifdef CONFIG_IOMMU_LEAK - if (!strncmp(p,"leak",4)) { + if (!strncmp(p, "leak", 4)) { leak_trace = 1; p += 4; if (*p == '=') ++p; @@ -723,18 +767,18 @@ void __init gart_parse_options(char *p) #endif if (isdigit(*p) && get_option(&p, &arg)) iommu_size = arg; - if (!strncmp(p, "fullflush",8)) + if (!strncmp(p, "fullflush", 8)) iommu_fullflush = 1; - if (!strncmp(p, "nofullflush",11)) + if (!strncmp(p, "nofullflush", 11)) iommu_fullflush = 0; - if (!strncmp(p,"noagp",5)) + if (!strncmp(p, "noagp", 5)) no_agp = 1; - if (!strncmp(p, "noaperture",10)) + if (!strncmp(p, "noaperture", 10)) fix_aperture = 0; /* duplicated from pci-dma.c */ - if (!strncmp(p,"force",5)) + if (!strncmp(p, "force", 5)) gart_iommu_aperture_allowed = 1; - if (!strncmp(p,"allowed",7)) + if (!strncmp(p, "allowed", 7)) gart_iommu_aperture_allowed = 1; if (!strncmp(p, "memaper", 7)) { fallback_aper_force = 1; From 2f36fa13ce49ffd000249feaedfcbefbcc83a72f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:12 +0100 Subject: [PATCH 046/890] x86: clean up arch/x86/kernel/e820_64.c White space and coding style cleanup. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/e820_64.c | 305 ++++++++++++++++++++++---------------- 1 file changed, 177 insertions(+), 128 deletions(-) diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c index 04698e0b056c..d41cd2f01733 100644 --- a/arch/x86/kernel/e820_64.c +++ b/arch/x86/kernel/e820_64.c @@ -1,4 +1,4 @@ -/* +/* * Handle the memory map. * The functions here do the job until bootmem takes over. * @@ -29,44 +29,44 @@ struct e820map e820; -/* +/* * PFN of last memory page. */ -unsigned long end_pfn; +unsigned long end_pfn; EXPORT_SYMBOL(end_pfn); -/* +/* * end_pfn only includes RAM, while end_pfn_map includes all e820 entries. * The direct mapping extends to end_pfn_map, so that we can directly access * apertures, ACPI and other tables without having to play with fixmaps. - */ -unsigned long end_pfn_map; + */ +unsigned long end_pfn_map; -/* +/* * Last pfn which the user wants to use. */ static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT; extern struct resource code_resource, data_resource, bss_resource; -/* Check for some hardcoded bad areas that early boot is not allowed to touch */ +/* Check for some hardcoded bad areas that early boot is not allowed to touch */ static inline int bad_addr(unsigned long *addrp, unsigned long size) -{ - unsigned long addr = *addrp, last = addr + size; +{ + unsigned long addr = *addrp, last = addr + size; /* various gunk below that needed for SMP startup */ - if (addr < 0x8000) { + if (addr < 0x8000) { *addrp = PAGE_ALIGN(0x8000); - return 1; + return 1; } /* direct mapping tables of the kernel */ - if (last >= table_start<= table_start<= __pa_symbol(&_text) && addr < __pa_symbol(&_end)) { @@ -97,9 +97,9 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size) return 1; } #endif - /* XXX ramdisk image here? */ + /* XXX ramdisk image here? */ return 0; -} +} /* * This function checks if any part of the range is mapped @@ -107,16 +107,18 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size) */ int e820_any_mapped(unsigned long start, unsigned long end, unsigned type) -{ +{ int i; - for (i = 0; i < e820.nr_map; i++) { - struct e820entry *ei = &e820.map[i]; - if (type && ei->type != type) + + for (i = 0; i < e820.nr_map; i++) { + struct e820entry *ei = &e820.map[i]; + + if (type && ei->type != type) continue; if (ei->addr >= end || ei->addr + ei->size <= start) - continue; - return 1; - } + continue; + return 1; + } return 0; } EXPORT_SYMBOL_GPL(e820_any_mapped); @@ -127,11 +129,14 @@ EXPORT_SYMBOL_GPL(e820_any_mapped); * Note: this function only works correct if the e820 table is sorted and * not-overlapping, which is the case */ -int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type) +int __init e820_all_mapped(unsigned long start, unsigned long end, + unsigned type) { int i; + for (i = 0; i < e820.nr_map; i++) { struct e820entry *ei = &e820.map[i]; + if (type && ei->type != type) continue; /* is the region (part) in overlap with the current region ?*/ @@ -143,59 +148,66 @@ int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type */ if (ei->addr <= start) start = ei->addr + ei->size; - /* if start is now at or beyond end, we're done, full coverage */ + /* + * if start is now at or beyond end, we're done, full + * coverage + */ if (start >= end) - return 1; /* we're done */ + return 1; } return 0; } -/* - * Find a free area in a specific range. - */ -unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsigned size) -{ - int i; - for (i = 0; i < e820.nr_map; i++) { - struct e820entry *ei = &e820.map[i]; - unsigned long addr = ei->addr, last; - if (ei->type != E820_RAM) - continue; - if (addr < start) +/* + * Find a free area in a specific range. + */ +unsigned long __init find_e820_area(unsigned long start, unsigned long end, + unsigned size) +{ + int i; + + for (i = 0; i < e820.nr_map; i++) { + struct e820entry *ei = &e820.map[i]; + unsigned long addr = ei->addr, last; + + if (ei->type != E820_RAM) + continue; + if (addr < start) addr = start; - if (addr > ei->addr + ei->size) - continue; + if (addr > ei->addr + ei->size) + continue; while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size) ; last = PAGE_ALIGN(addr) + size; if (last > ei->addr + ei->size) continue; - if (last > end) + if (last > end) continue; - return addr; - } - return -1UL; -} + return addr; + } + return -1UL; +} /* * Find the highest page frame number we have available */ unsigned long __init e820_end_of_ram(void) { - unsigned long end_pfn = 0; + unsigned long end_pfn; + end_pfn = find_max_pfn_with_active_regions(); - - if (end_pfn > end_pfn_map) + + if (end_pfn > end_pfn_map) end_pfn_map = end_pfn; if (end_pfn_map > MAXMEM>>PAGE_SHIFT) end_pfn_map = MAXMEM>>PAGE_SHIFT; if (end_pfn > end_user_pfn) end_pfn = end_user_pfn; - if (end_pfn > end_pfn_map) - end_pfn = end_pfn_map; + if (end_pfn > end_pfn_map) + end_pfn = end_pfn_map; - printk("end_pfn_map = %lu\n", end_pfn_map); - return end_pfn; + printk(KERN_INFO "end_pfn_map = %lu\n", end_pfn_map); + return end_pfn; } /* @@ -219,9 +231,9 @@ void __init e820_reserve_resources(void) request_resource(&iomem_resource, res); if (e820.map[i].type == E820_RAM) { /* - * We don't know which RAM region contains kernel data, - * so we try it repeatedly and let the resource manager - * test it. + * We don't know which RAM region contains kernel data, + * so we try it repeatedly and let the resource manager + * test it. */ request_resource(res, &code_resource); request_resource(res, &data_resource); @@ -322,9 +334,9 @@ e820_register_active_regions(int nid, unsigned long start_pfn, add_active_range(nid, ei_startpfn, ei_endpfn); } -/* +/* * Add a memory region to the kernel e820 map. - */ + */ void __init add_memory_region(unsigned long start, unsigned long size, int type) { int x = e820.nr_map; @@ -349,9 +361,7 @@ unsigned long __init e820_hole_size(unsigned long start, unsigned long end) { unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long end_pfn = end >> PAGE_SHIFT; - unsigned long ei_startpfn; - unsigned long ei_endpfn; - unsigned long ram = 0; + unsigned long ei_startpfn, ei_endpfn, ram = 0; int i; for (i = 0; i < e820.nr_map; i++) { @@ -369,22 +379,25 @@ void __init e820_print_map(char *who) for (i = 0; i < e820.nr_map; i++) { printk(KERN_INFO " %s: %016Lx - %016Lx ", who, - (unsigned long long) e820.map[i].addr, - (unsigned long long) (e820.map[i].addr + e820.map[i].size)); + (unsigned long long) e820.map[i].addr, + (unsigned long long) + (e820.map[i].addr + e820.map[i].size)); switch (e820.map[i].type) { - case E820_RAM: printk("(usable)\n"); - break; + case E820_RAM: + printk(KERN_CONT "(usable)\n"); + break; case E820_RESERVED: - printk("(reserved)\n"); - break; + printk(KERN_CONT "(reserved)\n"); + break; case E820_ACPI: - printk("(ACPI data)\n"); - break; + printk(KERN_CONT "(ACPI data)\n"); + break; case E820_NVS: - printk("(ACPI NVS)\n"); - break; - default: printk("type %u\n", e820.map[i].type); - break; + printk(KERN_CONT "(ACPI NVS)\n"); + break; + default: + printk(KERN_CONT "type %u\n", e820.map[i].type); + break; } } } @@ -392,11 +405,11 @@ void __init e820_print_map(char *who) /* * Sanitize the BIOS e820 map. * - * Some e820 responses include overlapping entries. The following + * Some e820 responses include overlapping entries. The following * replaces the original e820 map with a new one, removing overlaps. * */ -static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map) +static int __init sanitize_e820_map(struct e820entry *biosmap, char *pnr_map) { struct change_member { struct e820entry *pbios; /* pointer to original bios entry */ @@ -416,7 +429,8 @@ static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map) int i; /* - Visually we're performing the following (1,2,3,4 = memory types)... + Visually we're performing the following + (1,2,3,4 = memory types)... Sample memory map (w/overlaps): ____22__________________ @@ -458,22 +472,23 @@ static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map) old_nr = *pnr_map; /* bail out if we find any unreasonable addresses in bios map */ - for (i=0; iaddr = biosmap[i].addr; change_point[chgidx++]->pbios = &biosmap[i]; - change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size; + change_point[chgidx]->addr = biosmap[i].addr + + biosmap[i].size; change_point[chgidx++]->pbios = &biosmap[i]; } } @@ -483,75 +498,106 @@ static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map) still_changing = 1; while (still_changing) { still_changing = 0; - for (i=1; i < chg_nr; i++) { - /* if > , swap */ - /* or, if current= & last=, swap */ - if ((change_point[i]->addr < change_point[i-1]->addr) || - ((change_point[i]->addr == change_point[i-1]->addr) && - (change_point[i]->addr == change_point[i]->pbios->addr) && - (change_point[i-1]->addr != change_point[i-1]->pbios->addr)) - ) - { + for (i = 1; i < chg_nr; i++) { + unsigned long long curaddr, lastaddr; + unsigned long long curpbaddr, lastpbaddr; + + curaddr = change_point[i]->addr; + lastaddr = change_point[i - 1]->addr; + curpbaddr = change_point[i]->pbios->addr; + lastpbaddr = change_point[i - 1]->pbios->addr; + + /* + * swap entries, when: + * + * curaddr > lastaddr or + * curaddr == lastaddr and curaddr == curpbaddr and + * lastaddr != lastpbaddr + */ + if (curaddr < lastaddr || + (curaddr == lastaddr && curaddr == curpbaddr && + lastaddr != lastpbaddr)) { change_tmp = change_point[i]; change_point[i] = change_point[i-1]; change_point[i-1] = change_tmp; - still_changing=1; + still_changing = 1; } } } /* create a new bios memory map, removing overlaps */ - overlap_entries=0; /* number of entries in the overlap table */ - new_bios_entry=0; /* index for creating new bios map entries */ + overlap_entries = 0; /* number of entries in the overlap table */ + new_bios_entry = 0; /* index for creating new bios map entries */ last_type = 0; /* start with undefined memory type */ last_addr = 0; /* start with 0 as last starting address */ + /* loop through change-points, determining affect on the new bios map */ - for (chgidx=0; chgidx < chg_nr; chgidx++) - { + for (chgidx = 0; chgidx < chg_nr; chgidx++) { /* keep track of all overlapping bios entries */ - if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr) - { - /* add map entry to overlap list (> 1 entry implies an overlap) */ - overlap_list[overlap_entries++]=change_point[chgidx]->pbios; - } - else - { - /* remove entry from list (order independent, so swap with last) */ - for (i=0; ipbios) - overlap_list[i] = overlap_list[overlap_entries-1]; + if (change_point[chgidx]->addr == + change_point[chgidx]->pbios->addr) { + /* + * add map entry to overlap list (> 1 entry + * implies an overlap) + */ + overlap_list[overlap_entries++] = + change_point[chgidx]->pbios; + } else { + /* + * remove entry from list (order independent, + * so swap with last) + */ + for (i = 0; i < overlap_entries; i++) { + if (overlap_list[i] == + change_point[chgidx]->pbios) + overlap_list[i] = + overlap_list[overlap_entries-1]; } overlap_entries--; } - /* if there are overlapping entries, decide which "type" to use */ - /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */ + /* + * if there are overlapping entries, decide which + * "type" to use (larger value takes precedence -- + * 1=usable, 2,3,4,4+=unusable) + */ current_type = 0; - for (i=0; itype > current_type) current_type = overlap_list[i]->type; - /* continue building up new bios map based on this information */ + /* + * continue building up new bios map based on this + * information + */ if (current_type != last_type) { if (last_type != 0) { new_bios[new_bios_entry].size = change_point[chgidx]->addr - last_addr; - /* move forward only if the new size was non-zero */ + /* + * move forward only if the new size + * was non-zero + */ if (new_bios[new_bios_entry].size != 0) + /* + * no more space left for new + * bios entries ? + */ if (++new_bios_entry >= E820MAX) - break; /* no more space left for new bios entries */ + break; } if (current_type != 0) { - new_bios[new_bios_entry].addr = change_point[chgidx]->addr; + new_bios[new_bios_entry].addr = + change_point[chgidx]->addr; new_bios[new_bios_entry].type = current_type; - last_addr=change_point[chgidx]->addr; + last_addr = change_point[chgidx]->addr; } last_type = current_type; } } - new_nr = new_bios_entry; /* retain count for new bios entries */ + /* retain count for new bios entries */ + new_nr = new_bios_entry; /* copy new bios mapping into original location */ - memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry)); + memcpy(biosmap, new_bios, new_nr * sizeof(struct e820entry)); *pnr_map = new_nr; return 0; @@ -566,7 +612,7 @@ static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map) * will have given us a memory map that we can use to properly * set up memory. If we aren't, we'll fake a memory map. */ -static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) +static int __init copy_e820_map(struct e820entry *biosmap, int nr_map) { /* Only one memory region (or negative)? Ignore it */ if (nr_map < 2) @@ -583,7 +629,7 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) return -1; add_memory_region(start, size, type); - } while (biosmap++,--nr_map); + } while (biosmap++, --nr_map); return 0; } @@ -613,9 +659,9 @@ static int __init parse_memopt(char *p) if (!p) return -EINVAL; end_user_pfn = memparse(p, &p); - end_user_pfn >>= PAGE_SHIFT; + end_user_pfn >>= PAGE_SHIFT; return 0; -} +} early_param("mem", parse_memopt); static int userdef __initdata; @@ -627,9 +673,9 @@ static int __init parse_memmap_opt(char *p) if (!strcmp(p, "exactmap")) { #ifdef CONFIG_CRASH_DUMP - /* If we are doing a crash dump, we - * still need to know the real mem - * size before original memory map is + /* + * If we are doing a crash dump, we still need to know + * the real mem size before original memory map is * reset. */ e820_register_active_regions(0, 0, -1UL); @@ -713,8 +759,10 @@ __init void e820_setup_gap(void) if (!found) { gapstart = (end_pfn << PAGE_SHIFT) + 1024*1024; - printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit address range\n" - KERN_ERR "PCI: Unassigned devices with 32bit resource registers may break!\n"); + printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit " + "address range\n" + KERN_ERR "PCI: Unassigned devices with 32bit resource " + "registers may break!\n"); } /* @@ -727,8 +775,9 @@ __init void e820_setup_gap(void) /* Fun with two's complement */ pci_mem_start = (gapstart + round) & -round; - printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n", - pci_mem_start, gapstart, gapsize); + printk(KERN_INFO + "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n", + pci_mem_start, gapstart, gapsize); } int __init arch_get_ram_range(int slot, u64 *addr, u64 *size) From 78aa1f66f77da078357bd263fcac95fbf6bca15b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:13 +0100 Subject: [PATCH 047/890] x86: clean up arch/x86/kernel/ldt_32/64.c White space and coding style clenaup. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/ldt_32.c | 60 ++++++++++++++++++---------------- arch/x86/kernel/ldt_64.c | 69 +++++++++++++++++++++------------------- 2 files changed, 69 insertions(+), 60 deletions(-) diff --git a/arch/x86/kernel/ldt_32.c b/arch/x86/kernel/ldt_32.c index 9ff90a27c45f..e366c5fd0d19 100644 --- a/arch/x86/kernel/ldt_32.c +++ b/arch/x86/kernel/ldt_32.c @@ -17,7 +17,7 @@ #include #include -#ifdef CONFIG_SMP /* avoids "defined but not used" warnig */ +#ifdef CONFIG_SMP static void flush_ldt(void *null) { if (current->active_mm) @@ -34,19 +34,20 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) if (mincount <= pc->size) return 0; oldsize = pc->size; - mincount = (mincount+511)&(~511); - if (mincount*LDT_ENTRY_SIZE > PAGE_SIZE) - newldt = vmalloc(mincount*LDT_ENTRY_SIZE); + mincount = (mincount + 511) & (~511); + if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE) + newldt = vmalloc(mincount * LDT_ENTRY_SIZE); else - newldt = kmalloc(mincount*LDT_ENTRY_SIZE, GFP_KERNEL); + newldt = kmalloc(mincount * LDT_ENTRY_SIZE, GFP_KERNEL); if (!newldt) return -ENOMEM; if (oldsize) - memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE); + memcpy(newldt, pc->ldt, oldsize * LDT_ENTRY_SIZE); oldldt = pc->ldt; - memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE); + memset(newldt + oldsize * LDT_ENTRY_SIZE, 0, + (mincount - oldsize) * LDT_ENTRY_SIZE); pc->ldt = newldt; wmb(); pc->size = mincount; @@ -55,6 +56,7 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) if (reload) { #ifdef CONFIG_SMP cpumask_t mask; + preempt_disable(); load_LDT(pc); mask = cpumask_of_cpu(smp_processor_id()); @@ -66,7 +68,7 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) #endif } if (oldsize) { - if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE) + if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE) vfree(oldldt); else kfree(oldldt); @@ -77,9 +79,10 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) static inline int copy_ldt(mm_context_t *new, mm_context_t *old) { int err = alloc_ldt(new, old->size, 0); + if (err < 0) return err; - memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE); + memcpy(new->ldt, old->ldt, old->size * LDT_ENTRY_SIZE); return 0; } @@ -89,7 +92,7 @@ static inline int copy_ldt(mm_context_t *new, mm_context_t *old) */ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { - struct mm_struct * old_mm; + struct mm_struct *old_mm; int retval = 0; mutex_init(&mm->context.lock); @@ -111,7 +114,7 @@ void destroy_context(struct mm_struct *mm) if (mm->context.size) { if (mm == current->active_mm) clear_LDT(); - if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE) + if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE) vfree(mm->context.ldt); else kfree(mm->context.ldt); @@ -119,19 +122,19 @@ void destroy_context(struct mm_struct *mm) } } -static int read_ldt(void __user * ptr, unsigned long bytecount) +static int read_ldt(void __user *ptr, unsigned long bytecount) { int err; unsigned long size; - struct mm_struct * mm = current->mm; + struct mm_struct *mm = current->mm; if (!mm->context.size) return 0; - if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) - bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; + if (bytecount > LDT_ENTRY_SIZE * LDT_ENTRIES) + bytecount = LDT_ENTRY_SIZE * LDT_ENTRIES; mutex_lock(&mm->context.lock); - size = mm->context.size*LDT_ENTRY_SIZE; + size = mm->context.size * LDT_ENTRY_SIZE; if (size > bytecount) size = bytecount; @@ -143,7 +146,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) goto error_return; if (size != bytecount) { /* zero-fill the rest */ - if (clear_user(ptr+size, bytecount-size) != 0) { + if (clear_user(ptr + size, bytecount - size) != 0) { err = -EFAULT; goto error_return; } @@ -153,13 +156,13 @@ error_return: return err; } -static int read_default_ldt(void __user * ptr, unsigned long bytecount) +static int read_default_ldt(void __user *ptr, unsigned long bytecount) { int err; unsigned long size; err = 0; - size = 5*sizeof(struct desc_struct); + size = 5 * sizeof(struct desc_struct); if (size > bytecount) size = bytecount; @@ -170,9 +173,9 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount) return err; } -static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) +static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) { - struct mm_struct * mm = current->mm; + struct mm_struct *mm = current->mm; __u32 entry_1, entry_2; int error; struct user_desc ldt_info; @@ -180,7 +183,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) error = -EINVAL; if (bytecount != sizeof(ldt_info)) goto out; - error = -EFAULT; + error = -EFAULT; if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) goto out; @@ -196,13 +199,14 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) mutex_lock(&mm->context.lock); if (ldt_info.entry_number >= mm->context.size) { - error = alloc_ldt(¤t->mm->context, ldt_info.entry_number+1, 1); + error = alloc_ldt(¤t->mm->context, + ldt_info.entry_number + 1, 1); if (error < 0) goto out_unlock; } - /* Allow LDTs to be cleared by the user. */ - if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { + /* Allow LDTs to be cleared by the user. */ + if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { if (oldmode || LDT_empty(&ldt_info)) { entry_1 = 0; entry_2 = 0; @@ -217,7 +221,8 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) /* Install the new entry ... */ install: - write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1, entry_2); + write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1, + entry_2); error = 0; out_unlock: @@ -226,7 +231,8 @@ out: return error; } -asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) +asmlinkage int sys_modify_ldt(int func, void __user *ptr, + unsigned long bytecount) { int ret = -ENOSYS; diff --git a/arch/x86/kernel/ldt_64.c b/arch/x86/kernel/ldt_64.c index 60e57abb8e90..6c41db367de8 100644 --- a/arch/x86/kernel/ldt_64.c +++ b/arch/x86/kernel/ldt_64.c @@ -2,7 +2,7 @@ * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds * Copyright (C) 1999 Ingo Molnar * Copyright (C) 2002 Andi Kleen - * + * * This handles calls from both 32bit and 64bit mode. */ @@ -20,11 +20,11 @@ #include #include -#ifdef CONFIG_SMP /* avoids "defined but not used" warnig */ +#ifdef CONFIG_SMP static void flush_ldt(void *null) { if (current->active_mm) - load_LDT(¤t->active_mm->context); + load_LDT(¤t->active_mm->context); } #endif @@ -37,19 +37,20 @@ static int alloc_ldt(mm_context_t *pc, unsigned mincount, int reload) if (mincount <= (unsigned)pc->size) return 0; oldsize = pc->size; - mincount = (mincount+511)&(~511); - if (mincount*LDT_ENTRY_SIZE > PAGE_SIZE) - newldt = vmalloc(mincount*LDT_ENTRY_SIZE); + mincount = (mincount + 511) & (~511); + if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE) + newldt = vmalloc(mincount * LDT_ENTRY_SIZE); else - newldt = kmalloc(mincount*LDT_ENTRY_SIZE, GFP_KERNEL); + newldt = kmalloc(mincount * LDT_ENTRY_SIZE, GFP_KERNEL); if (!newldt) return -ENOMEM; if (oldsize) - memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE); + memcpy(newldt, pc->ldt, oldsize * LDT_ENTRY_SIZE); oldldt = pc->ldt; - memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE); + memset(newldt + oldsize * LDT_ENTRY_SIZE, 0, + (mincount - oldsize) * LDT_ENTRY_SIZE); wmb(); pc->ldt = newldt; wmb(); @@ -70,7 +71,7 @@ static int alloc_ldt(mm_context_t *pc, unsigned mincount, int reload) #endif } if (oldsize) { - if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE) + if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE) vfree(oldldt); else kfree(oldldt); @@ -81,9 +82,10 @@ static int alloc_ldt(mm_context_t *pc, unsigned mincount, int reload) static inline int copy_ldt(mm_context_t *new, mm_context_t *old) { int err = alloc_ldt(new, old->size, 0); + if (err < 0) return err; - memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE); + memcpy(new->ldt, old->ldt, old->size * LDT_ENTRY_SIZE); return 0; } @@ -93,7 +95,7 @@ static inline int copy_ldt(mm_context_t *new, mm_context_t *old) */ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { - struct mm_struct * old_mm; + struct mm_struct *old_mm; int retval = 0; mutex_init(&mm->context.lock); @@ -108,13 +110,12 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) } /* - * * Don't touch the LDT register - we're already in the next thread. */ void destroy_context(struct mm_struct *mm) { if (mm->context.size) { - if ((unsigned)mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE) + if ((unsigned)mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE) vfree(mm->context.ldt); else kfree(mm->context.ldt); @@ -122,19 +123,19 @@ void destroy_context(struct mm_struct *mm) } } -static int read_ldt(void __user * ptr, unsigned long bytecount) +static int read_ldt(void __user *ptr, unsigned long bytecount) { int err; unsigned long size; - struct mm_struct * mm = current->mm; + struct mm_struct *mm = current->mm; if (!mm->context.size) return 0; - if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) - bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; + if (bytecount > LDT_ENTRY_SIZE * LDT_ENTRIES) + bytecount = LDT_ENTRY_SIZE * LDT_ENTRIES; mutex_lock(&mm->context.lock); - size = mm->context.size*LDT_ENTRY_SIZE; + size = mm->context.size * LDT_ENTRY_SIZE; if (size > bytecount) size = bytecount; @@ -146,7 +147,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) goto error_return; if (size != bytecount) { /* zero-fill the rest */ - if (clear_user(ptr+size, bytecount-size) != 0) { + if (clear_user(ptr + size, bytecount - size) != 0) { err = -EFAULT; goto error_return; } @@ -156,21 +157,21 @@ error_return: return err; } -static int read_default_ldt(void __user * ptr, unsigned long bytecount) +static int read_default_ldt(void __user *ptr, unsigned long bytecount) { - /* Arbitrary number */ + /* Arbitrary number */ /* x86-64 default LDT is all zeros */ - if (bytecount > 128) - bytecount = 128; + if (bytecount > 128) + bytecount = 128; if (clear_user(ptr, bytecount)) return -EFAULT; - return bytecount; + return bytecount; } -static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) +static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) { struct task_struct *me = current; - struct mm_struct * mm = me->mm; + struct mm_struct *mm = me->mm; __u32 entry_1, entry_2, *lp; int error; struct user_desc ldt_info; @@ -179,7 +180,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) if (bytecount != sizeof(ldt_info)) goto out; - error = -EFAULT; + error = -EFAULT; if (copy_from_user(&ldt_info, ptr, bytecount)) goto out; @@ -195,15 +196,16 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) mutex_lock(&mm->context.lock); if (ldt_info.entry_number >= (unsigned)mm->context.size) { - error = alloc_ldt(¤t->mm->context, ldt_info.entry_number+1, 1); + error = alloc_ldt(¤t->mm->context, + ldt_info.entry_number + 1, 1); if (error < 0) goto out_unlock; } - lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->context.ldt); + lp = (__u32 *)((ldt_info.entry_number << 3) + (char *)mm->context.ldt); - /* Allow LDTs to be cleared by the user. */ - if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { + /* Allow LDTs to be cleared by the user. */ + if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { if (oldmode || LDT_empty(&ldt_info)) { entry_1 = 0; entry_2 = 0; @@ -228,7 +230,8 @@ out: return error; } -asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) +asmlinkage int sys_modify_ldt(int func, void __user *ptr, + unsigned long bytecount) { int ret = -ENOSYS; From 4edc8f5454814201d2fb222354284365b4f0537c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:13 +0100 Subject: [PATCH 048/890] x86: clean up include/asm-x86/desc_64.h White space and coding style clenaup. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- include/asm-x86/desc_64.h | 95 +++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 44 deletions(-) diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h index 7d9c938e69fd..bb2009ecbbca 100644 --- a/include/asm-x86/desc_64.h +++ b/include/asm-x86/desc_64.h @@ -1,4 +1,4 @@ -/* Written 2000 by Andi Kleen */ +/* Written 2000 by Andi Kleen */ #ifndef __ARCH_DESC_H #define __ARCH_DESC_H @@ -35,7 +35,7 @@ static inline unsigned long __store_tr(void) * something other than this. */ extern struct desc_struct default_ldt[]; -extern struct gate_struct idt_table[]; +extern struct gate_struct idt_table[]; extern struct desc_ptr cpu_gdt_descr[]; /* the cpu gdt accessor */ @@ -51,40 +51,45 @@ static inline void store_gdt(struct desc_ptr *ptr) asm("sgdt %w0":"=m" (*ptr)); } -static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsigned dpl, unsigned ist) +static inline void _set_gate(void *adr, unsigned type, unsigned long func, + unsigned dpl, unsigned ist) { - struct gate_struct s; - s.offset_low = PTR_LOW(func); + struct gate_struct s; + + s.offset_low = PTR_LOW(func); s.segment = __KERNEL_CS; - s.ist = ist; + s.ist = ist; s.p = 1; - s.dpl = dpl; + s.dpl = dpl; s.zero0 = 0; - s.zero1 = 0; - s.type = type; - s.offset_middle = PTR_MIDDLE(func); - s.offset_high = PTR_HIGH(func); - /* does not need to be atomic because it is only done once at setup time */ - memcpy(adr, &s, 16); -} + s.zero1 = 0; + s.type = type; + s.offset_middle = PTR_MIDDLE(func); + s.offset_high = PTR_HIGH(func); + /* + * does not need to be atomic because it is only done once at + * setup time + */ + memcpy(adr, &s, 16); +} -static inline void set_intr_gate(int nr, void *func) -{ +static inline void set_intr_gate(int nr, void *func) +{ BUG_ON((unsigned)nr > 0xFF); - _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0); -} + _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0); +} -static inline void set_intr_gate_ist(int nr, void *func, unsigned ist) -{ +static inline void set_intr_gate_ist(int nr, void *func, unsigned ist) +{ BUG_ON((unsigned)nr > 0xFF); - _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist); -} + _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist); +} -static inline void set_system_gate(int nr, void *func) -{ +static inline void set_system_gate(int nr, void *func) +{ BUG_ON((unsigned)nr > 0xFF); - _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0); -} + _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0); +} static inline void set_system_gate_ist(int nr, void *func, unsigned ist) { @@ -101,24 +106,25 @@ static inline void store_idt(struct desc_ptr *dtr) asm("sidt %w0":"=m" (*dtr)); } -static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned type, - unsigned size) -{ +static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, + unsigned type, unsigned size) +{ struct ldttss_desc d; - memset(&d,0,sizeof(d)); + + memset(&d, 0, sizeof(d)); d.limit0 = size & 0xFFFF; - d.base0 = PTR_LOW(tss); - d.base1 = PTR_MIDDLE(tss) & 0xFF; + d.base0 = PTR_LOW(tss); + d.base1 = PTR_MIDDLE(tss) & 0xFF; d.type = type; - d.p = 1; + d.p = 1; d.limit1 = (size >> 16) & 0xF; - d.base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF; - d.base3 = PTR_HIGH(tss); - memcpy(ptr, &d, 16); + d.base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF; + d.base3 = PTR_HIGH(tss); + memcpy(ptr, &d, 16); } static inline void set_tss_desc(unsigned cpu, void *addr) -{ +{ /* * sizeof(unsigned long) coming from an extra "long" at the end * of the iobitmap. See tss_struct definition in processor.h @@ -129,18 +135,18 @@ static inline void set_tss_desc(unsigned cpu, void *addr) set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_TSS], (unsigned long)addr, DESC_TSS, IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1); -} +} static inline void set_ldt_desc(unsigned cpu, void *addr, int size) -{ +{ set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_LDT], (unsigned long)addr, DESC_LDT, size * 8 - 1); } #define LDT_entry_a(info) \ ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) -/* Don't allow setting of the lm bit. It is useless anyways because - 64bit system calls require __USER_CS. */ +/* Don't allow setting of the lm bit. It is useless anyways because + 64bit system calls require __USER_CS. */ #define LDT_entry_b(info) \ (((info)->base_addr & 0xff000000) | \ (((info)->base_addr & 0x00ff0000) >> 16) | \ @@ -172,12 +178,12 @@ static inline void load_TLS(struct thread_struct *t, unsigned int cpu) for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++) gdt[i] = t->tls_array[i]; -} +} /* * load one particular LDT into the current CPU */ -static inline void load_LDT_nolock (mm_context_t *pc, int cpu) +static inline void load_LDT_nolock(mm_context_t *pc, int cpu) { int count = pc->size; @@ -185,7 +191,7 @@ static inline void load_LDT_nolock (mm_context_t *pc, int cpu) clear_LDT(); return; } - + set_ldt_desc(cpu, pc->ldt, count); load_LDT_desc(); } @@ -193,6 +199,7 @@ static inline void load_LDT_nolock (mm_context_t *pc, int cpu) static inline void load_LDT(mm_context_t *pc) { int cpu = get_cpu(); + load_LDT_nolock(pc, cpu); put_cpu(); } From fc2d625c4fac18e672a3b7c61af5de22d7ab7d87 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:13 +0100 Subject: [PATCH 049/890] x86: introduce ldt_write accessor Create a ldt write accessor like the 32 bit one. Preparatory patch for merging ldt.c and anyway necessary for 64bit paravirt ops. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/ldt_64.c | 8 +++----- include/asm-x86/desc_64.h | 9 +++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/ldt_64.c b/arch/x86/kernel/ldt_64.c index 6c41db367de8..d72dc7a0636f 100644 --- a/arch/x86/kernel/ldt_64.c +++ b/arch/x86/kernel/ldt_64.c @@ -172,7 +172,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) { struct task_struct *me = current; struct mm_struct *mm = me->mm; - __u32 entry_1, entry_2, *lp; + __u32 entry_1, entry_2; int error; struct user_desc ldt_info; @@ -202,8 +202,6 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) goto out_unlock; } - lp = (__u32 *)((ldt_info.entry_number << 3) + (char *)mm->context.ldt); - /* Allow LDTs to be cleared by the user. */ if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { if (oldmode || LDT_empty(&ldt_info)) { @@ -220,8 +218,8 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) /* Install the new entry ... */ install: - *lp = entry_1; - *(lp+1) = entry_2; + write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1, + entry_2); error = 0; out_unlock: diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h index bb2009ecbbca..7d48df72aef2 100644 --- a/include/asm-x86/desc_64.h +++ b/include/asm-x86/desc_64.h @@ -38,6 +38,15 @@ extern struct desc_struct default_ldt[]; extern struct gate_struct idt_table[]; extern struct desc_ptr cpu_gdt_descr[]; +static inline void write_ldt_entry(struct desc_struct *ldt, + int entry, u32 entry_low, u32 entry_high) +{ + __u32 *lp = (__u32 *)((entry << 3) + (char *)ldt); + + lp[0] = entry_low; + lp[1] = entry_high; +} + /* the cpu gdt accessor */ #define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address) From 70f5088dd5e9fbd3a71b3a5b01395c676158194b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:13 +0100 Subject: [PATCH 050/890] x86: prepare arch/x86/kernel/ldt_32/64.c for merging White space and coding style cleanups. Change unsigned to int. There is no win when we compare mincount against pc->size, which is an int as well. Casting pc->size to unsigned just might hide real problems. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/ldt_32.c | 3 +-- arch/x86/kernel/ldt_64.c | 24 +++++++++++------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/ldt_32.c b/arch/x86/kernel/ldt_32.c index e366c5fd0d19..bb15753abaf2 100644 --- a/arch/x86/kernel/ldt_32.c +++ b/arch/x86/kernel/ldt_32.c @@ -27,8 +27,7 @@ static void flush_ldt(void *null) static int alloc_ldt(mm_context_t *pc, int mincount, int reload) { - void *oldldt; - void *newldt; + void *oldldt, *newldt; int oldsize; if (mincount <= pc->size) diff --git a/arch/x86/kernel/ldt_64.c b/arch/x86/kernel/ldt_64.c index d72dc7a0636f..95903938e7ad 100644 --- a/arch/x86/kernel/ldt_64.c +++ b/arch/x86/kernel/ldt_64.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #ifdef CONFIG_SMP static void flush_ldt(void *null) @@ -28,13 +28,12 @@ static void flush_ldt(void *null) } #endif -static int alloc_ldt(mm_context_t *pc, unsigned mincount, int reload) +static int alloc_ldt(mm_context_t *pc, int mincount, int reload) { - void *oldldt; - void *newldt; - unsigned oldsize; + void *oldldt, *newldt; + int oldsize; - if (mincount <= (unsigned)pc->size) + if (mincount <= pc->size) return 0; oldsize = pc->size; mincount = (mincount + 511) & (~511); @@ -56,13 +55,14 @@ static int alloc_ldt(mm_context_t *pc, unsigned mincount, int reload) wmb(); pc->size = mincount; wmb(); + if (reload) { #ifdef CONFIG_SMP cpumask_t mask; preempt_disable(); - mask = cpumask_of_cpu(smp_processor_id()); load_LDT(pc); + mask = cpumask_of_cpu(smp_processor_id()); if (!cpus_equal(current->mm->cpu_vm_mask, mask)) smp_call_function(flush_ldt, NULL, 1, 1); preempt_enable(); @@ -115,7 +115,7 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) void destroy_context(struct mm_struct *mm) { if (mm->context.size) { - if ((unsigned)mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE) + if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE) vfree(mm->context.ldt); else kfree(mm->context.ldt); @@ -170,18 +170,16 @@ static int read_default_ldt(void __user *ptr, unsigned long bytecount) static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) { - struct task_struct *me = current; - struct mm_struct *mm = me->mm; + struct mm_struct *mm = current->mm; __u32 entry_1, entry_2; int error; struct user_desc ldt_info; error = -EINVAL; - if (bytecount != sizeof(ldt_info)) goto out; error = -EFAULT; - if (copy_from_user(&ldt_info, ptr, bytecount)) + if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) goto out; error = -EINVAL; @@ -195,7 +193,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) } mutex_lock(&mm->context.lock); - if (ldt_info.entry_number >= (unsigned)mm->context.size) { + if (ldt_info.entry_number >= mm->context.size) { error = alloc_ldt(¤t->mm->context, ldt_info.entry_number + 1, 1); if (error < 0) From 77e463d1040d6310211ac5162729f5d4afc4dd8c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:14 +0100 Subject: [PATCH 051/890] x86: merge arch/x86/kernel/ldt_32/64.c Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/Makefile_32 | 2 +- arch/x86/kernel/Makefile_64 | 2 +- arch/x86/kernel/{ldt_64.c => ldt.c} | 25 ++- arch/x86/kernel/ldt_32.c | 253 ---------------------------- 4 files changed, 22 insertions(+), 260 deletions(-) rename arch/x86/kernel/{ldt_64.c => ldt.c} (90%) delete mode 100644 arch/x86/kernel/ldt_32.c diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32 index 0cc1981d1e38..31ff982bc26b 100644 --- a/arch/x86/kernel/Makefile_32 +++ b/arch/x86/kernel/Makefile_32 @@ -6,7 +6,7 @@ extra-y := head_32.o init_task.o vmlinux.lds CPPFLAGS_vmlinux.lds += -Ui386 obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \ - ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \ + ptrace_32.o time_32.o ioport_32.o ldt.o setup_32.o i8259_32.o sys_i386_32.o \ pci-dma_32.o i386_ksyms_32.o i387_32.o bootflag.o e820_32.o\ quirks.o i8237.o topology.o alternative.o i8253.o tsc_32.o io_delay.o diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64 index 08a68f0d8fda..9cb3df27c413 100644 --- a/arch/x86/kernel/Makefile_64 +++ b/arch/x86/kernel/Makefile_64 @@ -7,7 +7,7 @@ CPPFLAGS_vmlinux.lds += -Ux86_64 EXTRA_AFLAGS := -traditional obj-y := process_64.o signal_64.o entry_64.o traps_64.o irq_64.o \ - ptrace_64.o time_64.o ioport_64.o ldt_64.o setup_64.o i8259_64.o sys_x86_64.o \ + ptrace_64.o time_64.o ioport_64.o ldt.o setup_64.o i8259_64.o sys_x86_64.o \ x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \ setup64.o bootflag.o e820_64.o reboot_64.o quirks.o i8237.o \ pci-dma_64.o pci-nommu_64.o alternative.o hpet.o tsc_64.o bugs_64.o \ diff --git a/arch/x86/kernel/ldt_64.c b/arch/x86/kernel/ldt.c similarity index 90% rename from arch/x86/kernel/ldt_64.c rename to arch/x86/kernel/ldt.c index 95903938e7ad..a8cdca3615bf 100644 --- a/arch/x86/kernel/ldt_64.c +++ b/arch/x86/kernel/ldt.c @@ -50,7 +50,11 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) oldldt = pc->ldt; memset(newldt + oldsize * LDT_ENTRY_SIZE, 0, (mincount - oldsize) * LDT_ENTRY_SIZE); + +#ifdef CONFIG_X86_64 + /* CHECKME: Do we really need this ? */ wmb(); +#endif pc->ldt = newldt; wmb(); pc->size = mincount; @@ -110,11 +114,18 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) } /* - * Don't touch the LDT register - we're already in the next thread. + * No need to lock the MM as we are the last user + * + * 64bit: Don't touch the LDT register - we're already in the next thread. */ void destroy_context(struct mm_struct *mm) { if (mm->context.size) { +#ifdef CONFIG_X86_32 + /* CHECKME: Can this ever happen ? */ + if (mm == current->active_mm) + clear_LDT(); +#endif if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE) vfree(mm->context.ldt); else @@ -159,10 +170,14 @@ error_return: static int read_default_ldt(void __user *ptr, unsigned long bytecount) { - /* Arbitrary number */ - /* x86-64 default LDT is all zeros */ - if (bytecount > 128) - bytecount = 128; + /* CHECKME: Can we use _one_ random number ? */ +#ifdef CONFIG_X86_32 + unsigned long size = 5 * sizeof(struct desc_struct); +#else + unsigned long size = 128; +#endif + if (bytecount > size) + bytecount = size; if (clear_user(ptr, bytecount)) return -EFAULT; return bytecount; diff --git a/arch/x86/kernel/ldt_32.c b/arch/x86/kernel/ldt_32.c deleted file mode 100644 index bb15753abaf2..000000000000 --- a/arch/x86/kernel/ldt_32.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds - * Copyright (C) 1999 Ingo Molnar - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifdef CONFIG_SMP -static void flush_ldt(void *null) -{ - if (current->active_mm) - load_LDT(¤t->active_mm->context); -} -#endif - -static int alloc_ldt(mm_context_t *pc, int mincount, int reload) -{ - void *oldldt, *newldt; - int oldsize; - - if (mincount <= pc->size) - return 0; - oldsize = pc->size; - mincount = (mincount + 511) & (~511); - if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE) - newldt = vmalloc(mincount * LDT_ENTRY_SIZE); - else - newldt = kmalloc(mincount * LDT_ENTRY_SIZE, GFP_KERNEL); - - if (!newldt) - return -ENOMEM; - - if (oldsize) - memcpy(newldt, pc->ldt, oldsize * LDT_ENTRY_SIZE); - oldldt = pc->ldt; - memset(newldt + oldsize * LDT_ENTRY_SIZE, 0, - (mincount - oldsize) * LDT_ENTRY_SIZE); - pc->ldt = newldt; - wmb(); - pc->size = mincount; - wmb(); - - if (reload) { -#ifdef CONFIG_SMP - cpumask_t mask; - - preempt_disable(); - load_LDT(pc); - mask = cpumask_of_cpu(smp_processor_id()); - if (!cpus_equal(current->mm->cpu_vm_mask, mask)) - smp_call_function(flush_ldt, NULL, 1, 1); - preempt_enable(); -#else - load_LDT(pc); -#endif - } - if (oldsize) { - if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE) - vfree(oldldt); - else - kfree(oldldt); - } - return 0; -} - -static inline int copy_ldt(mm_context_t *new, mm_context_t *old) -{ - int err = alloc_ldt(new, old->size, 0); - - if (err < 0) - return err; - memcpy(new->ldt, old->ldt, old->size * LDT_ENTRY_SIZE); - return 0; -} - -/* - * we do not have to muck with descriptors here, that is - * done in switch_mm() as needed. - */ -int init_new_context(struct task_struct *tsk, struct mm_struct *mm) -{ - struct mm_struct *old_mm; - int retval = 0; - - mutex_init(&mm->context.lock); - mm->context.size = 0; - old_mm = current->mm; - if (old_mm && old_mm->context.size > 0) { - mutex_lock(&old_mm->context.lock); - retval = copy_ldt(&mm->context, &old_mm->context); - mutex_unlock(&old_mm->context.lock); - } - return retval; -} - -/* - * No need to lock the MM as we are the last user - */ -void destroy_context(struct mm_struct *mm) -{ - if (mm->context.size) { - if (mm == current->active_mm) - clear_LDT(); - if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE) - vfree(mm->context.ldt); - else - kfree(mm->context.ldt); - mm->context.size = 0; - } -} - -static int read_ldt(void __user *ptr, unsigned long bytecount) -{ - int err; - unsigned long size; - struct mm_struct *mm = current->mm; - - if (!mm->context.size) - return 0; - if (bytecount > LDT_ENTRY_SIZE * LDT_ENTRIES) - bytecount = LDT_ENTRY_SIZE * LDT_ENTRIES; - - mutex_lock(&mm->context.lock); - size = mm->context.size * LDT_ENTRY_SIZE; - if (size > bytecount) - size = bytecount; - - err = 0; - if (copy_to_user(ptr, mm->context.ldt, size)) - err = -EFAULT; - mutex_unlock(&mm->context.lock); - if (err < 0) - goto error_return; - if (size != bytecount) { - /* zero-fill the rest */ - if (clear_user(ptr + size, bytecount - size) != 0) { - err = -EFAULT; - goto error_return; - } - } - return bytecount; -error_return: - return err; -} - -static int read_default_ldt(void __user *ptr, unsigned long bytecount) -{ - int err; - unsigned long size; - - err = 0; - size = 5 * sizeof(struct desc_struct); - if (size > bytecount) - size = bytecount; - - err = size; - if (clear_user(ptr, size)) - err = -EFAULT; - - return err; -} - -static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) -{ - struct mm_struct *mm = current->mm; - __u32 entry_1, entry_2; - int error; - struct user_desc ldt_info; - - error = -EINVAL; - if (bytecount != sizeof(ldt_info)) - goto out; - error = -EFAULT; - if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) - goto out; - - error = -EINVAL; - if (ldt_info.entry_number >= LDT_ENTRIES) - goto out; - if (ldt_info.contents == 3) { - if (oldmode) - goto out; - if (ldt_info.seg_not_present == 0) - goto out; - } - - mutex_lock(&mm->context.lock); - if (ldt_info.entry_number >= mm->context.size) { - error = alloc_ldt(¤t->mm->context, - ldt_info.entry_number + 1, 1); - if (error < 0) - goto out_unlock; - } - - /* Allow LDTs to be cleared by the user. */ - if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { - if (oldmode || LDT_empty(&ldt_info)) { - entry_1 = 0; - entry_2 = 0; - goto install; - } - } - - entry_1 = LDT_entry_a(&ldt_info); - entry_2 = LDT_entry_b(&ldt_info); - if (oldmode) - entry_2 &= ~(1 << 20); - - /* Install the new entry ... */ -install: - write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1, - entry_2); - error = 0; - -out_unlock: - mutex_unlock(&mm->context.lock); -out: - return error; -} - -asmlinkage int sys_modify_ldt(int func, void __user *ptr, - unsigned long bytecount) -{ - int ret = -ENOSYS; - - switch (func) { - case 0: - ret = read_ldt(ptr, bytecount); - break; - case 1: - ret = write_ldt(ptr, bytecount, 1); - break; - case 2: - ret = read_default_ldt(ptr, bytecount); - break; - case 0x11: - ret = write_ldt(ptr, bytecount, 0); - break; - } - return ret; -} From 2d539553c96771bc8f77156f27500d35e1fe114c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:14 +0100 Subject: [PATCH 052/890] x86: unify include/asm-x86/apicdef_32/64.h Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- include/asm-x86/apicdef.h | 403 ++++++++++++++++++++++++++++++++++- include/asm-x86/apicdef_32.h | 375 -------------------------------- include/asm-x86/apicdef_64.h | 392 ---------------------------------- 3 files changed, 399 insertions(+), 771 deletions(-) delete mode 100644 include/asm-x86/apicdef_32.h delete mode 100644 include/asm-x86/apicdef_64.h diff --git a/include/asm-x86/apicdef.h b/include/asm-x86/apicdef.h index 4542c220bf4d..83ac1e6e3625 100644 --- a/include/asm-x86/apicdef.h +++ b/include/asm-x86/apicdef.h @@ -1,5 +1,400 @@ -#ifdef CONFIG_X86_32 -# include "apicdef_32.h" -#else -# include "apicdef_64.h" +#ifndef _ASM_X86_APICDEF_H +#define _ASM_X86_APICDEF_H + +/* + * Constants for various Intel APICs. (local APIC, IOAPIC, etc.) + * + * Alan Cox , 1995. + * Ingo Molnar , 1999, 2000 + */ + +#define APIC_DEFAULT_PHYS_BASE 0xfee00000 + +#define APIC_ID 0x20 + +#ifdef CONFIG_X86_64 +# define APIC_ID_MASK (0xFFu<<24) +# define GET_APIC_ID(x) (((x)>>24)&0xFFu) +# define SET_APIC_ID(x) (((x)<<24)) +#endif + +#define APIC_LVR 0x30 +#define APIC_LVR_MASK 0xFF00FF +#define GET_APIC_VERSION(x) ((x)&0xFFu) +#define GET_APIC_MAXLVT(x) (((x)>>16)&0xFFu) +#define APIC_INTEGRATED(x) ((x)&0xF0u) +#define APIC_XAPIC(x) ((x) >= 0x14) +#define APIC_TASKPRI 0x80 +#define APIC_TPRI_MASK 0xFFu +#define APIC_ARBPRI 0x90 +#define APIC_ARBPRI_MASK 0xFFu +#define APIC_PROCPRI 0xA0 +#define APIC_EOI 0xB0 +#define APIC_EIO_ACK 0x0 +#define APIC_RRR 0xC0 +#define APIC_LDR 0xD0 +#define APIC_LDR_MASK (0xFFu<<24) +#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFFu) +#define SET_APIC_LOGICAL_ID(x) (((x)<<24)) +#define APIC_ALL_CPUS 0xFFu +#define APIC_DFR 0xE0 +#define APIC_DFR_CLUSTER 0x0FFFFFFFul +#define APIC_DFR_FLAT 0xFFFFFFFFul +#define APIC_SPIV 0xF0 +#define APIC_SPIV_FOCUS_DISABLED (1<<9) +#define APIC_SPIV_APIC_ENABLED (1<<8) +#define APIC_ISR 0x100 +#define APIC_ISR_NR 0x8 /* Number of 32 bit ISR registers. */ +#define APIC_TMR 0x180 +#define APIC_IRR 0x200 +#define APIC_ESR 0x280 +#define APIC_ESR_SEND_CS 0x00001 +#define APIC_ESR_RECV_CS 0x00002 +#define APIC_ESR_SEND_ACC 0x00004 +#define APIC_ESR_RECV_ACC 0x00008 +#define APIC_ESR_SENDILL 0x00020 +#define APIC_ESR_RECVILL 0x00040 +#define APIC_ESR_ILLREGA 0x00080 +#define APIC_ICR 0x300 +#define APIC_DEST_SELF 0x40000 +#define APIC_DEST_ALLINC 0x80000 +#define APIC_DEST_ALLBUT 0xC0000 +#define APIC_ICR_RR_MASK 0x30000 +#define APIC_ICR_RR_INVALID 0x00000 +#define APIC_ICR_RR_INPROG 0x10000 +#define APIC_ICR_RR_VALID 0x20000 +#define APIC_INT_LEVELTRIG 0x08000 +#define APIC_INT_ASSERT 0x04000 +#define APIC_ICR_BUSY 0x01000 +#define APIC_DEST_LOGICAL 0x00800 +#define APIC_DEST_PHYSICAL 0x00000 +#define APIC_DM_FIXED 0x00000 +#define APIC_DM_LOWEST 0x00100 +#define APIC_DM_SMI 0x00200 +#define APIC_DM_REMRD 0x00300 +#define APIC_DM_NMI 0x00400 +#define APIC_DM_INIT 0x00500 +#define APIC_DM_STARTUP 0x00600 +#define APIC_DM_EXTINT 0x00700 +#define APIC_VECTOR_MASK 0x000FF +#define APIC_ICR2 0x310 +#define GET_APIC_DEST_FIELD(x) (((x)>>24)&0xFF) +#define SET_APIC_DEST_FIELD(x) ((x)<<24) +#define APIC_LVTT 0x320 +#define APIC_LVTTHMR 0x330 +#define APIC_LVTPC 0x340 +#define APIC_LVT0 0x350 +#define APIC_LVT_TIMER_BASE_MASK (0x3<<18) +#define GET_APIC_TIMER_BASE(x) (((x)>>18)&0x3) +#define SET_APIC_TIMER_BASE(x) (((x)<<18)) +#define APIC_TIMER_BASE_CLKIN 0x0 +#define APIC_TIMER_BASE_TMBASE 0x1 +#define APIC_TIMER_BASE_DIV 0x2 +#define APIC_LVT_TIMER_PERIODIC (1<<17) +#define APIC_LVT_MASKED (1<<16) +#define APIC_LVT_LEVEL_TRIGGER (1<<15) +#define APIC_LVT_REMOTE_IRR (1<<14) +#define APIC_INPUT_POLARITY (1<<13) +#define APIC_SEND_PENDING (1<<12) +#define APIC_MODE_MASK 0x700 +#define GET_APIC_DELIVERY_MODE(x) (((x)>>8)&0x7) +#define SET_APIC_DELIVERY_MODE(x,y) (((x)&~0x700)|((y)<<8)) +#define APIC_MODE_FIXED 0x0 +#define APIC_MODE_NMI 0x4 +#define APIC_MODE_EXTINT 0x7 +#define APIC_LVT1 0x360 +#define APIC_LVTERR 0x370 +#define APIC_TMICT 0x380 +#define APIC_TMCCT 0x390 +#define APIC_TDCR 0x3E0 +#define APIC_TDR_DIV_TMBASE (1<<2) +#define APIC_TDR_DIV_1 0xB +#define APIC_TDR_DIV_2 0x0 +#define APIC_TDR_DIV_4 0x1 +#define APIC_TDR_DIV_8 0x2 +#define APIC_TDR_DIV_16 0x3 +#define APIC_TDR_DIV_32 0x8 +#define APIC_TDR_DIV_64 0x9 +#define APIC_TDR_DIV_128 0xA +#define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) + +#ifdef CONFIG_X86_32 +# define MAX_IO_APICS 64 +#else +# define MAX_IO_APICS 128 +# define MAX_LOCAL_APIC 256 +#endif + +/* + * All x86-64 systems are xAPIC compatible. + * In the following, "apicid" is a physical APIC ID. + */ +#define XAPIC_DEST_CPUS_SHIFT 4 +#define XAPIC_DEST_CPUS_MASK ((1u << XAPIC_DEST_CPUS_SHIFT) - 1) +#define XAPIC_DEST_CLUSTER_MASK (XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT) +#define APIC_CLUSTER(apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK) +#define APIC_CLUSTERID(apicid) (APIC_CLUSTER(apicid) >> XAPIC_DEST_CPUS_SHIFT) +#define APIC_CPUID(apicid) ((apicid) & XAPIC_DEST_CPUS_MASK) +#define NUM_APIC_CLUSTERS ((BAD_APICID + 1) >> XAPIC_DEST_CPUS_SHIFT) + +/* + * the local APIC register structure, memory mapped. Not terribly well + * tested, but we might eventually use this one in the future - the + * problem why we cannot use it right now is the P5 APIC, it has an + * errata which cannot take 8-bit reads and writes, only 32-bit ones ... + */ +#define u32 unsigned int + +struct local_apic { + +/*000*/ struct { u32 __reserved[4]; } __reserved_01; + +/*010*/ struct { u32 __reserved[4]; } __reserved_02; + +/*020*/ struct { /* APIC ID Register */ + u32 __reserved_1 : 24, + phys_apic_id : 4, + __reserved_2 : 4; + u32 __reserved[3]; + } id; + +/*030*/ const + struct { /* APIC Version Register */ + u32 version : 8, + __reserved_1 : 8, + max_lvt : 8, + __reserved_2 : 8; + u32 __reserved[3]; + } version; + +/*040*/ struct { u32 __reserved[4]; } __reserved_03; + +/*050*/ struct { u32 __reserved[4]; } __reserved_04; + +/*060*/ struct { u32 __reserved[4]; } __reserved_05; + +/*070*/ struct { u32 __reserved[4]; } __reserved_06; + +/*080*/ struct { /* Task Priority Register */ + u32 priority : 8, + __reserved_1 : 24; + u32 __reserved_2[3]; + } tpr; + +/*090*/ const + struct { /* Arbitration Priority Register */ + u32 priority : 8, + __reserved_1 : 24; + u32 __reserved_2[3]; + } apr; + +/*0A0*/ const + struct { /* Processor Priority Register */ + u32 priority : 8, + __reserved_1 : 24; + u32 __reserved_2[3]; + } ppr; + +/*0B0*/ struct { /* End Of Interrupt Register */ + u32 eoi; + u32 __reserved[3]; + } eoi; + +/*0C0*/ struct { u32 __reserved[4]; } __reserved_07; + +/*0D0*/ struct { /* Logical Destination Register */ + u32 __reserved_1 : 24, + logical_dest : 8; + u32 __reserved_2[3]; + } ldr; + +/*0E0*/ struct { /* Destination Format Register */ + u32 __reserved_1 : 28, + model : 4; + u32 __reserved_2[3]; + } dfr; + +/*0F0*/ struct { /* Spurious Interrupt Vector Register */ + u32 spurious_vector : 8, + apic_enabled : 1, + focus_cpu : 1, + __reserved_2 : 22; + u32 __reserved_3[3]; + } svr; + +/*100*/ struct { /* In Service Register */ +/*170*/ u32 bitfield; + u32 __reserved[3]; + } isr [8]; + +/*180*/ struct { /* Trigger Mode Register */ +/*1F0*/ u32 bitfield; + u32 __reserved[3]; + } tmr [8]; + +/*200*/ struct { /* Interrupt Request Register */ +/*270*/ u32 bitfield; + u32 __reserved[3]; + } irr [8]; + +/*280*/ union { /* Error Status Register */ + struct { + u32 send_cs_error : 1, + receive_cs_error : 1, + send_accept_error : 1, + receive_accept_error : 1, + __reserved_1 : 1, + send_illegal_vector : 1, + receive_illegal_vector : 1, + illegal_register_address : 1, + __reserved_2 : 24; + u32 __reserved_3[3]; + } error_bits; + struct { + u32 errors; + u32 __reserved_3[3]; + } all_errors; + } esr; + +/*290*/ struct { u32 __reserved[4]; } __reserved_08; + +/*2A0*/ struct { u32 __reserved[4]; } __reserved_09; + +/*2B0*/ struct { u32 __reserved[4]; } __reserved_10; + +/*2C0*/ struct { u32 __reserved[4]; } __reserved_11; + +/*2D0*/ struct { u32 __reserved[4]; } __reserved_12; + +/*2E0*/ struct { u32 __reserved[4]; } __reserved_13; + +/*2F0*/ struct { u32 __reserved[4]; } __reserved_14; + +/*300*/ struct { /* Interrupt Command Register 1 */ + u32 vector : 8, + delivery_mode : 3, + destination_mode : 1, + delivery_status : 1, + __reserved_1 : 1, + level : 1, + trigger : 1, + __reserved_2 : 2, + shorthand : 2, + __reserved_3 : 12; + u32 __reserved_4[3]; + } icr1; + +/*310*/ struct { /* Interrupt Command Register 2 */ + union { + u32 __reserved_1 : 24, + phys_dest : 4, + __reserved_2 : 4; + u32 __reserved_3 : 24, + logical_dest : 8; + } dest; + u32 __reserved_4[3]; + } icr2; + +/*320*/ struct { /* LVT - Timer */ + u32 vector : 8, + __reserved_1 : 4, + delivery_status : 1, + __reserved_2 : 3, + mask : 1, + timer_mode : 1, + __reserved_3 : 14; + u32 __reserved_4[3]; + } lvt_timer; + +/*330*/ struct { /* LVT - Thermal Sensor */ + u32 vector : 8, + delivery_mode : 3, + __reserved_1 : 1, + delivery_status : 1, + __reserved_2 : 3, + mask : 1, + __reserved_3 : 15; + u32 __reserved_4[3]; + } lvt_thermal; + +/*340*/ struct { /* LVT - Performance Counter */ + u32 vector : 8, + delivery_mode : 3, + __reserved_1 : 1, + delivery_status : 1, + __reserved_2 : 3, + mask : 1, + __reserved_3 : 15; + u32 __reserved_4[3]; + } lvt_pc; + +/*350*/ struct { /* LVT - LINT0 */ + u32 vector : 8, + delivery_mode : 3, + __reserved_1 : 1, + delivery_status : 1, + polarity : 1, + remote_irr : 1, + trigger : 1, + mask : 1, + __reserved_2 : 15; + u32 __reserved_3[3]; + } lvt_lint0; + +/*360*/ struct { /* LVT - LINT1 */ + u32 vector : 8, + delivery_mode : 3, + __reserved_1 : 1, + delivery_status : 1, + polarity : 1, + remote_irr : 1, + trigger : 1, + mask : 1, + __reserved_2 : 15; + u32 __reserved_3[3]; + } lvt_lint1; + +/*370*/ struct { /* LVT - Error */ + u32 vector : 8, + __reserved_1 : 4, + delivery_status : 1, + __reserved_2 : 3, + mask : 1, + __reserved_3 : 15; + u32 __reserved_4[3]; + } lvt_error; + +/*380*/ struct { /* Timer Initial Count Register */ + u32 initial_count; + u32 __reserved_2[3]; + } timer_icr; + +/*390*/ const + struct { /* Timer Current Count Register */ + u32 curr_count; + u32 __reserved_2[3]; + } timer_ccr; + +/*3A0*/ struct { u32 __reserved[4]; } __reserved_16; + +/*3B0*/ struct { u32 __reserved[4]; } __reserved_17; + +/*3C0*/ struct { u32 __reserved[4]; } __reserved_18; + +/*3D0*/ struct { u32 __reserved[4]; } __reserved_19; + +/*3E0*/ struct { /* Timer Divide Configuration Register */ + u32 divisor : 4, + __reserved_1 : 28; + u32 __reserved_2[3]; + } timer_dcr; + +/*3F0*/ struct { u32 __reserved[4]; } __reserved_20; + +} __attribute__ ((packed)); + +#undef u32 + +#define BAD_APICID 0xFFu + #endif diff --git a/include/asm-x86/apicdef_32.h b/include/asm-x86/apicdef_32.h deleted file mode 100644 index 9f6995341fdc..000000000000 --- a/include/asm-x86/apicdef_32.h +++ /dev/null @@ -1,375 +0,0 @@ -#ifndef __ASM_APICDEF_H -#define __ASM_APICDEF_H - -/* - * Constants for various Intel APICs. (local APIC, IOAPIC, etc.) - * - * Alan Cox , 1995. - * Ingo Molnar , 1999, 2000 - */ - -#define APIC_DEFAULT_PHYS_BASE 0xfee00000 - -#define APIC_ID 0x20 -#define APIC_LVR 0x30 -#define APIC_LVR_MASK 0xFF00FF -#define GET_APIC_VERSION(x) ((x)&0xFF) -#define GET_APIC_MAXLVT(x) (((x)>>16)&0xFF) -#define APIC_INTEGRATED(x) ((x)&0xF0) -#define APIC_XAPIC(x) ((x) >= 0x14) -#define APIC_TASKPRI 0x80 -#define APIC_TPRI_MASK 0xFF -#define APIC_ARBPRI 0x90 -#define APIC_ARBPRI_MASK 0xFF -#define APIC_PROCPRI 0xA0 -#define APIC_EOI 0xB0 -#define APIC_EIO_ACK 0x0 /* Write this to the EOI register */ -#define APIC_RRR 0xC0 -#define APIC_LDR 0xD0 -#define APIC_LDR_MASK (0xFF<<24) -#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFF) -#define SET_APIC_LOGICAL_ID(x) (((x)<<24)) -#define APIC_ALL_CPUS 0xFF -#define APIC_DFR 0xE0 -#define APIC_DFR_CLUSTER 0x0FFFFFFFul -#define APIC_DFR_FLAT 0xFFFFFFFFul -#define APIC_SPIV 0xF0 -#define APIC_SPIV_FOCUS_DISABLED (1<<9) -#define APIC_SPIV_APIC_ENABLED (1<<8) -#define APIC_ISR 0x100 -#define APIC_ISR_NR 0x8 /* Number of 32 bit ISR registers. */ -#define APIC_TMR 0x180 -#define APIC_IRR 0x200 -#define APIC_ESR 0x280 -#define APIC_ESR_SEND_CS 0x00001 -#define APIC_ESR_RECV_CS 0x00002 -#define APIC_ESR_SEND_ACC 0x00004 -#define APIC_ESR_RECV_ACC 0x00008 -#define APIC_ESR_SENDILL 0x00020 -#define APIC_ESR_RECVILL 0x00040 -#define APIC_ESR_ILLREGA 0x00080 -#define APIC_ICR 0x300 -#define APIC_DEST_SELF 0x40000 -#define APIC_DEST_ALLINC 0x80000 -#define APIC_DEST_ALLBUT 0xC0000 -#define APIC_ICR_RR_MASK 0x30000 -#define APIC_ICR_RR_INVALID 0x00000 -#define APIC_ICR_RR_INPROG 0x10000 -#define APIC_ICR_RR_VALID 0x20000 -#define APIC_INT_LEVELTRIG 0x08000 -#define APIC_INT_ASSERT 0x04000 -#define APIC_ICR_BUSY 0x01000 -#define APIC_DEST_LOGICAL 0x00800 -#define APIC_DM_FIXED 0x00000 -#define APIC_DM_LOWEST 0x00100 -#define APIC_DM_SMI 0x00200 -#define APIC_DM_REMRD 0x00300 -#define APIC_DM_NMI 0x00400 -#define APIC_DM_INIT 0x00500 -#define APIC_DM_STARTUP 0x00600 -#define APIC_DM_EXTINT 0x00700 -#define APIC_VECTOR_MASK 0x000FF -#define APIC_ICR2 0x310 -#define GET_APIC_DEST_FIELD(x) (((x)>>24)&0xFF) -#define SET_APIC_DEST_FIELD(x) ((x)<<24) -#define APIC_LVTT 0x320 -#define APIC_LVTTHMR 0x330 -#define APIC_LVTPC 0x340 -#define APIC_LVT0 0x350 -#define APIC_LVT_TIMER_BASE_MASK (0x3<<18) -#define GET_APIC_TIMER_BASE(x) (((x)>>18)&0x3) -#define SET_APIC_TIMER_BASE(x) (((x)<<18)) -#define APIC_TIMER_BASE_CLKIN 0x0 -#define APIC_TIMER_BASE_TMBASE 0x1 -#define APIC_TIMER_BASE_DIV 0x2 -#define APIC_LVT_TIMER_PERIODIC (1<<17) -#define APIC_LVT_MASKED (1<<16) -#define APIC_LVT_LEVEL_TRIGGER (1<<15) -#define APIC_LVT_REMOTE_IRR (1<<14) -#define APIC_INPUT_POLARITY (1<<13) -#define APIC_SEND_PENDING (1<<12) -#define APIC_MODE_MASK 0x700 -#define GET_APIC_DELIVERY_MODE(x) (((x)>>8)&0x7) -#define SET_APIC_DELIVERY_MODE(x,y) (((x)&~0x700)|((y)<<8)) -#define APIC_MODE_FIXED 0x0 -#define APIC_MODE_NMI 0x4 -#define APIC_MODE_EXTINT 0x7 -#define APIC_LVT1 0x360 -#define APIC_LVTERR 0x370 -#define APIC_TMICT 0x380 -#define APIC_TMCCT 0x390 -#define APIC_TDCR 0x3E0 -#define APIC_TDR_DIV_TMBASE (1<<2) -#define APIC_TDR_DIV_1 0xB -#define APIC_TDR_DIV_2 0x0 -#define APIC_TDR_DIV_4 0x1 -#define APIC_TDR_DIV_8 0x2 -#define APIC_TDR_DIV_16 0x3 -#define APIC_TDR_DIV_32 0x8 -#define APIC_TDR_DIV_64 0x9 -#define APIC_TDR_DIV_128 0xA - -#define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) - -#define MAX_IO_APICS 64 - -/* - * the local APIC register structure, memory mapped. Not terribly well - * tested, but we might eventually use this one in the future - the - * problem why we cannot use it right now is the P5 APIC, it has an - * errata which cannot take 8-bit reads and writes, only 32-bit ones ... - */ -#define u32 unsigned int - - -struct local_apic { - -/*000*/ struct { u32 __reserved[4]; } __reserved_01; - -/*010*/ struct { u32 __reserved[4]; } __reserved_02; - -/*020*/ struct { /* APIC ID Register */ - u32 __reserved_1 : 24, - phys_apic_id : 4, - __reserved_2 : 4; - u32 __reserved[3]; - } id; - -/*030*/ const - struct { /* APIC Version Register */ - u32 version : 8, - __reserved_1 : 8, - max_lvt : 8, - __reserved_2 : 8; - u32 __reserved[3]; - } version; - -/*040*/ struct { u32 __reserved[4]; } __reserved_03; - -/*050*/ struct { u32 __reserved[4]; } __reserved_04; - -/*060*/ struct { u32 __reserved[4]; } __reserved_05; - -/*070*/ struct { u32 __reserved[4]; } __reserved_06; - -/*080*/ struct { /* Task Priority Register */ - u32 priority : 8, - __reserved_1 : 24; - u32 __reserved_2[3]; - } tpr; - -/*090*/ const - struct { /* Arbitration Priority Register */ - u32 priority : 8, - __reserved_1 : 24; - u32 __reserved_2[3]; - } apr; - -/*0A0*/ const - struct { /* Processor Priority Register */ - u32 priority : 8, - __reserved_1 : 24; - u32 __reserved_2[3]; - } ppr; - -/*0B0*/ struct { /* End Of Interrupt Register */ - u32 eoi; - u32 __reserved[3]; - } eoi; - -/*0C0*/ struct { u32 __reserved[4]; } __reserved_07; - -/*0D0*/ struct { /* Logical Destination Register */ - u32 __reserved_1 : 24, - logical_dest : 8; - u32 __reserved_2[3]; - } ldr; - -/*0E0*/ struct { /* Destination Format Register */ - u32 __reserved_1 : 28, - model : 4; - u32 __reserved_2[3]; - } dfr; - -/*0F0*/ struct { /* Spurious Interrupt Vector Register */ - u32 spurious_vector : 8, - apic_enabled : 1, - focus_cpu : 1, - __reserved_2 : 22; - u32 __reserved_3[3]; - } svr; - -/*100*/ struct { /* In Service Register */ -/*170*/ u32 bitfield; - u32 __reserved[3]; - } isr [8]; - -/*180*/ struct { /* Trigger Mode Register */ -/*1F0*/ u32 bitfield; - u32 __reserved[3]; - } tmr [8]; - -/*200*/ struct { /* Interrupt Request Register */ -/*270*/ u32 bitfield; - u32 __reserved[3]; - } irr [8]; - -/*280*/ union { /* Error Status Register */ - struct { - u32 send_cs_error : 1, - receive_cs_error : 1, - send_accept_error : 1, - receive_accept_error : 1, - __reserved_1 : 1, - send_illegal_vector : 1, - receive_illegal_vector : 1, - illegal_register_address : 1, - __reserved_2 : 24; - u32 __reserved_3[3]; - } error_bits; - struct { - u32 errors; - u32 __reserved_3[3]; - } all_errors; - } esr; - -/*290*/ struct { u32 __reserved[4]; } __reserved_08; - -/*2A0*/ struct { u32 __reserved[4]; } __reserved_09; - -/*2B0*/ struct { u32 __reserved[4]; } __reserved_10; - -/*2C0*/ struct { u32 __reserved[4]; } __reserved_11; - -/*2D0*/ struct { u32 __reserved[4]; } __reserved_12; - -/*2E0*/ struct { u32 __reserved[4]; } __reserved_13; - -/*2F0*/ struct { u32 __reserved[4]; } __reserved_14; - -/*300*/ struct { /* Interrupt Command Register 1 */ - u32 vector : 8, - delivery_mode : 3, - destination_mode : 1, - delivery_status : 1, - __reserved_1 : 1, - level : 1, - trigger : 1, - __reserved_2 : 2, - shorthand : 2, - __reserved_3 : 12; - u32 __reserved_4[3]; - } icr1; - -/*310*/ struct { /* Interrupt Command Register 2 */ - union { - u32 __reserved_1 : 24, - phys_dest : 4, - __reserved_2 : 4; - u32 __reserved_3 : 24, - logical_dest : 8; - } dest; - u32 __reserved_4[3]; - } icr2; - -/*320*/ struct { /* LVT - Timer */ - u32 vector : 8, - __reserved_1 : 4, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - timer_mode : 1, - __reserved_3 : 14; - u32 __reserved_4[3]; - } lvt_timer; - -/*330*/ struct { /* LVT - Thermal Sensor */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - __reserved_3 : 15; - u32 __reserved_4[3]; - } lvt_thermal; - -/*340*/ struct { /* LVT - Performance Counter */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - __reserved_3 : 15; - u32 __reserved_4[3]; - } lvt_pc; - -/*350*/ struct { /* LVT - LINT0 */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - polarity : 1, - remote_irr : 1, - trigger : 1, - mask : 1, - __reserved_2 : 15; - u32 __reserved_3[3]; - } lvt_lint0; - -/*360*/ struct { /* LVT - LINT1 */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - polarity : 1, - remote_irr : 1, - trigger : 1, - mask : 1, - __reserved_2 : 15; - u32 __reserved_3[3]; - } lvt_lint1; - -/*370*/ struct { /* LVT - Error */ - u32 vector : 8, - __reserved_1 : 4, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - __reserved_3 : 15; - u32 __reserved_4[3]; - } lvt_error; - -/*380*/ struct { /* Timer Initial Count Register */ - u32 initial_count; - u32 __reserved_2[3]; - } timer_icr; - -/*390*/ const - struct { /* Timer Current Count Register */ - u32 curr_count; - u32 __reserved_2[3]; - } timer_ccr; - -/*3A0*/ struct { u32 __reserved[4]; } __reserved_16; - -/*3B0*/ struct { u32 __reserved[4]; } __reserved_17; - -/*3C0*/ struct { u32 __reserved[4]; } __reserved_18; - -/*3D0*/ struct { u32 __reserved[4]; } __reserved_19; - -/*3E0*/ struct { /* Timer Divide Configuration Register */ - u32 divisor : 4, - __reserved_1 : 28; - u32 __reserved_2[3]; - } timer_dcr; - -/*3F0*/ struct { u32 __reserved[4]; } __reserved_20; - -} __attribute__ ((packed)); - -#undef u32 - -#endif diff --git a/include/asm-x86/apicdef_64.h b/include/asm-x86/apicdef_64.h deleted file mode 100644 index 1dd40067c67c..000000000000 --- a/include/asm-x86/apicdef_64.h +++ /dev/null @@ -1,392 +0,0 @@ -#ifndef __ASM_APICDEF_H -#define __ASM_APICDEF_H - -/* - * Constants for various Intel APICs. (local APIC, IOAPIC, etc.) - * - * Alan Cox , 1995. - * Ingo Molnar , 1999, 2000 - */ - -#define APIC_DEFAULT_PHYS_BASE 0xfee00000 - -#define APIC_ID 0x20 -#define APIC_ID_MASK (0xFFu<<24) -#define GET_APIC_ID(x) (((x)>>24)&0xFFu) -#define SET_APIC_ID(x) (((x)<<24)) -#define APIC_LVR 0x30 -#define APIC_LVR_MASK 0xFF00FF -#define GET_APIC_VERSION(x) ((x)&0xFFu) -#define GET_APIC_MAXLVT(x) (((x)>>16)&0xFFu) -#define APIC_INTEGRATED(x) ((x)&0xF0u) -#define APIC_TASKPRI 0x80 -#define APIC_TPRI_MASK 0xFFu -#define APIC_ARBPRI 0x90 -#define APIC_ARBPRI_MASK 0xFFu -#define APIC_PROCPRI 0xA0 -#define APIC_EOI 0xB0 -#define APIC_EIO_ACK 0x0 /* Write this to the EOI register */ -#define APIC_RRR 0xC0 -#define APIC_LDR 0xD0 -#define APIC_LDR_MASK (0xFFu<<24) -#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFFu) -#define SET_APIC_LOGICAL_ID(x) (((x)<<24)) -#define APIC_ALL_CPUS 0xFFu -#define APIC_DFR 0xE0 -#define APIC_DFR_CLUSTER 0x0FFFFFFFul -#define APIC_DFR_FLAT 0xFFFFFFFFul -#define APIC_SPIV 0xF0 -#define APIC_SPIV_FOCUS_DISABLED (1<<9) -#define APIC_SPIV_APIC_ENABLED (1<<8) -#define APIC_ISR 0x100 -#define APIC_ISR_NR 0x8 /* Number of 32 bit ISR registers. */ -#define APIC_TMR 0x180 -#define APIC_IRR 0x200 -#define APIC_ESR 0x280 -#define APIC_ESR_SEND_CS 0x00001 -#define APIC_ESR_RECV_CS 0x00002 -#define APIC_ESR_SEND_ACC 0x00004 -#define APIC_ESR_RECV_ACC 0x00008 -#define APIC_ESR_SENDILL 0x00020 -#define APIC_ESR_RECVILL 0x00040 -#define APIC_ESR_ILLREGA 0x00080 -#define APIC_ICR 0x300 -#define APIC_DEST_SELF 0x40000 -#define APIC_DEST_ALLINC 0x80000 -#define APIC_DEST_ALLBUT 0xC0000 -#define APIC_ICR_RR_MASK 0x30000 -#define APIC_ICR_RR_INVALID 0x00000 -#define APIC_ICR_RR_INPROG 0x10000 -#define APIC_ICR_RR_VALID 0x20000 -#define APIC_INT_LEVELTRIG 0x08000 -#define APIC_INT_ASSERT 0x04000 -#define APIC_ICR_BUSY 0x01000 -#define APIC_DEST_LOGICAL 0x00800 -#define APIC_DEST_PHYSICAL 0x00000 -#define APIC_DM_FIXED 0x00000 -#define APIC_DM_LOWEST 0x00100 -#define APIC_DM_SMI 0x00200 -#define APIC_DM_REMRD 0x00300 -#define APIC_DM_NMI 0x00400 -#define APIC_DM_INIT 0x00500 -#define APIC_DM_STARTUP 0x00600 -#define APIC_DM_EXTINT 0x00700 -#define APIC_VECTOR_MASK 0x000FF -#define APIC_ICR2 0x310 -#define GET_APIC_DEST_FIELD(x) (((x)>>24)&0xFF) -#define SET_APIC_DEST_FIELD(x) ((x)<<24) -#define APIC_LVTT 0x320 -#define APIC_LVTTHMR 0x330 -#define APIC_LVTPC 0x340 -#define APIC_LVT0 0x350 -#define APIC_LVT_TIMER_BASE_MASK (0x3<<18) -#define GET_APIC_TIMER_BASE(x) (((x)>>18)&0x3) -#define SET_APIC_TIMER_BASE(x) (((x)<<18)) -#define APIC_TIMER_BASE_CLKIN 0x0 -#define APIC_TIMER_BASE_TMBASE 0x1 -#define APIC_TIMER_BASE_DIV 0x2 -#define APIC_LVT_TIMER_PERIODIC (1<<17) -#define APIC_LVT_MASKED (1<<16) -#define APIC_LVT_LEVEL_TRIGGER (1<<15) -#define APIC_LVT_REMOTE_IRR (1<<14) -#define APIC_INPUT_POLARITY (1<<13) -#define APIC_SEND_PENDING (1<<12) -#define APIC_MODE_MASK 0x700 -#define GET_APIC_DELIVERY_MODE(x) (((x)>>8)&0x7) -#define SET_APIC_DELIVERY_MODE(x,y) (((x)&~0x700)|((y)<<8)) -#define APIC_MODE_FIXED 0x0 -#define APIC_MODE_NMI 0x4 -#define APIC_MODE_EXTINT 0x7 -#define APIC_LVT1 0x360 -#define APIC_LVTERR 0x370 -#define APIC_TMICT 0x380 -#define APIC_TMCCT 0x390 -#define APIC_TDCR 0x3E0 -#define APIC_TDR_DIV_TMBASE (1<<2) -#define APIC_TDR_DIV_1 0xB -#define APIC_TDR_DIV_2 0x0 -#define APIC_TDR_DIV_4 0x1 -#define APIC_TDR_DIV_8 0x2 -#define APIC_TDR_DIV_16 0x3 -#define APIC_TDR_DIV_32 0x8 -#define APIC_TDR_DIV_64 0x9 -#define APIC_TDR_DIV_128 0xA - -#define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) - -#define MAX_IO_APICS 128 -#define MAX_LOCAL_APIC 256 - -/* - * All x86-64 systems are xAPIC compatible. - * In the following, "apicid" is a physical APIC ID. - */ -#define XAPIC_DEST_CPUS_SHIFT 4 -#define XAPIC_DEST_CPUS_MASK ((1u << XAPIC_DEST_CPUS_SHIFT) - 1) -#define XAPIC_DEST_CLUSTER_MASK (XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT) -#define APIC_CLUSTER(apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK) -#define APIC_CLUSTERID(apicid) (APIC_CLUSTER(apicid) >> XAPIC_DEST_CPUS_SHIFT) -#define APIC_CPUID(apicid) ((apicid) & XAPIC_DEST_CPUS_MASK) -#define NUM_APIC_CLUSTERS ((BAD_APICID + 1) >> XAPIC_DEST_CPUS_SHIFT) - -/* - * the local APIC register structure, memory mapped. Not terribly well - * tested, but we might eventually use this one in the future - the - * problem why we cannot use it right now is the P5 APIC, it has an - * errata which cannot take 8-bit reads and writes, only 32-bit ones ... - */ -#define u32 unsigned int - -struct local_apic { - -/*000*/ struct { u32 __reserved[4]; } __reserved_01; - -/*010*/ struct { u32 __reserved[4]; } __reserved_02; - -/*020*/ struct { /* APIC ID Register */ - u32 __reserved_1 : 24, - phys_apic_id : 4, - __reserved_2 : 4; - u32 __reserved[3]; - } id; - -/*030*/ const - struct { /* APIC Version Register */ - u32 version : 8, - __reserved_1 : 8, - max_lvt : 8, - __reserved_2 : 8; - u32 __reserved[3]; - } version; - -/*040*/ struct { u32 __reserved[4]; } __reserved_03; - -/*050*/ struct { u32 __reserved[4]; } __reserved_04; - -/*060*/ struct { u32 __reserved[4]; } __reserved_05; - -/*070*/ struct { u32 __reserved[4]; } __reserved_06; - -/*080*/ struct { /* Task Priority Register */ - u32 priority : 8, - __reserved_1 : 24; - u32 __reserved_2[3]; - } tpr; - -/*090*/ const - struct { /* Arbitration Priority Register */ - u32 priority : 8, - __reserved_1 : 24; - u32 __reserved_2[3]; - } apr; - -/*0A0*/ const - struct { /* Processor Priority Register */ - u32 priority : 8, - __reserved_1 : 24; - u32 __reserved_2[3]; - } ppr; - -/*0B0*/ struct { /* End Of Interrupt Register */ - u32 eoi; - u32 __reserved[3]; - } eoi; - -/*0C0*/ struct { u32 __reserved[4]; } __reserved_07; - -/*0D0*/ struct { /* Logical Destination Register */ - u32 __reserved_1 : 24, - logical_dest : 8; - u32 __reserved_2[3]; - } ldr; - -/*0E0*/ struct { /* Destination Format Register */ - u32 __reserved_1 : 28, - model : 4; - u32 __reserved_2[3]; - } dfr; - -/*0F0*/ struct { /* Spurious Interrupt Vector Register */ - u32 spurious_vector : 8, - apic_enabled : 1, - focus_cpu : 1, - __reserved_2 : 22; - u32 __reserved_3[3]; - } svr; - -/*100*/ struct { /* In Service Register */ -/*170*/ u32 bitfield; - u32 __reserved[3]; - } isr [8]; - -/*180*/ struct { /* Trigger Mode Register */ -/*1F0*/ u32 bitfield; - u32 __reserved[3]; - } tmr [8]; - -/*200*/ struct { /* Interrupt Request Register */ -/*270*/ u32 bitfield; - u32 __reserved[3]; - } irr [8]; - -/*280*/ union { /* Error Status Register */ - struct { - u32 send_cs_error : 1, - receive_cs_error : 1, - send_accept_error : 1, - receive_accept_error : 1, - __reserved_1 : 1, - send_illegal_vector : 1, - receive_illegal_vector : 1, - illegal_register_address : 1, - __reserved_2 : 24; - u32 __reserved_3[3]; - } error_bits; - struct { - u32 errors; - u32 __reserved_3[3]; - } all_errors; - } esr; - -/*290*/ struct { u32 __reserved[4]; } __reserved_08; - -/*2A0*/ struct { u32 __reserved[4]; } __reserved_09; - -/*2B0*/ struct { u32 __reserved[4]; } __reserved_10; - -/*2C0*/ struct { u32 __reserved[4]; } __reserved_11; - -/*2D0*/ struct { u32 __reserved[4]; } __reserved_12; - -/*2E0*/ struct { u32 __reserved[4]; } __reserved_13; - -/*2F0*/ struct { u32 __reserved[4]; } __reserved_14; - -/*300*/ struct { /* Interrupt Command Register 1 */ - u32 vector : 8, - delivery_mode : 3, - destination_mode : 1, - delivery_status : 1, - __reserved_1 : 1, - level : 1, - trigger : 1, - __reserved_2 : 2, - shorthand : 2, - __reserved_3 : 12; - u32 __reserved_4[3]; - } icr1; - -/*310*/ struct { /* Interrupt Command Register 2 */ - union { - u32 __reserved_1 : 24, - phys_dest : 4, - __reserved_2 : 4; - u32 __reserved_3 : 24, - logical_dest : 8; - } dest; - u32 __reserved_4[3]; - } icr2; - -/*320*/ struct { /* LVT - Timer */ - u32 vector : 8, - __reserved_1 : 4, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - timer_mode : 1, - __reserved_3 : 14; - u32 __reserved_4[3]; - } lvt_timer; - -/*330*/ struct { /* LVT - Thermal Sensor */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - __reserved_3 : 15; - u32 __reserved_4[3]; - } lvt_thermal; - -/*340*/ struct { /* LVT - Performance Counter */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - __reserved_3 : 15; - u32 __reserved_4[3]; - } lvt_pc; - -/*350*/ struct { /* LVT - LINT0 */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - polarity : 1, - remote_irr : 1, - trigger : 1, - mask : 1, - __reserved_2 : 15; - u32 __reserved_3[3]; - } lvt_lint0; - -/*360*/ struct { /* LVT - LINT1 */ - u32 vector : 8, - delivery_mode : 3, - __reserved_1 : 1, - delivery_status : 1, - polarity : 1, - remote_irr : 1, - trigger : 1, - mask : 1, - __reserved_2 : 15; - u32 __reserved_3[3]; - } lvt_lint1; - -/*370*/ struct { /* LVT - Error */ - u32 vector : 8, - __reserved_1 : 4, - delivery_status : 1, - __reserved_2 : 3, - mask : 1, - __reserved_3 : 15; - u32 __reserved_4[3]; - } lvt_error; - -/*380*/ struct { /* Timer Initial Count Register */ - u32 initial_count; - u32 __reserved_2[3]; - } timer_icr; - -/*390*/ const - struct { /* Timer Current Count Register */ - u32 curr_count; - u32 __reserved_2[3]; - } timer_ccr; - -/*3A0*/ struct { u32 __reserved[4]; } __reserved_16; - -/*3B0*/ struct { u32 __reserved[4]; } __reserved_17; - -/*3C0*/ struct { u32 __reserved[4]; } __reserved_18; - -/*3D0*/ struct { u32 __reserved[4]; } __reserved_19; - -/*3E0*/ struct { /* Timer Divide Configuration Register */ - u32 divisor : 4, - __reserved_1 : 28; - u32 __reserved_2[3]; - } timer_dcr; - -/*3F0*/ struct { u32 __reserved[4]; } __reserved_20; - -} __attribute__ ((packed)); - -#undef u32 - -#define BAD_APICID 0xFFu - -#endif From cff90dbfe41f2c8eabe2d0a7e379829f4a9980af Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:14 +0100 Subject: [PATCH 053/890] x86: prepare unification of include/asm-x86/apic_32/64.h White space and coding style clenaup. Move the K8 local apic defines to apicdef.h, where they belong Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- include/asm-x86/apic_32.h | 49 ++++++++++++++++++--------------------- include/asm-x86/apic_64.h | 39 +++++++++++++------------------ include/asm-x86/apicdef.h | 10 +++++++- 3 files changed, 48 insertions(+), 50 deletions(-) diff --git a/include/asm-x86/apic_32.h b/include/asm-x86/apic_32.h index be158b27d54b..f909e2daf226 100644 --- a/include/asm-x86/apic_32.h +++ b/include/asm-x86/apic_32.h @@ -17,8 +17,6 @@ #define APIC_VERBOSE 1 #define APIC_DEBUG 2 -extern int apic_verbosity; - /* * Define the default level of output to be very little * This can be turned up by using apic=verbose for more @@ -35,6 +33,11 @@ extern void generic_apic_probe(void); #ifdef CONFIG_X86_LOCAL_APIC +extern int apic_verbosity; +extern int timer_over_8254; +extern int local_apic_timer_c2_ok; +extern int local_apic_timer_disabled; + /* * Basic functions accessing APICs. */ @@ -65,9 +68,9 @@ static __inline fastcall unsigned long native_apic_read(unsigned long reg) return *((volatile unsigned long *)(APIC_BASE+reg)); } -void apic_wait_icr_idle(void); -unsigned long safe_apic_wait_icr_idle(void); -int get_physical_broadcast(void); +extern void apic_wait_icr_idle(void); +extern unsigned long safe_apic_wait_icr_idle(void); +extern int get_physical_broadcast(void); #ifdef CONFIG_X86_GOOD_APIC # define FORCE_READ_AROUND_WRITE 0 @@ -94,30 +97,24 @@ static inline void ack_APIC_irq(void) extern int lapic_get_maxlvt(void); extern void clear_local_APIC(void); -extern void connect_bsp_APIC (void); -extern void disconnect_bsp_APIC (int virt_wire_setup); -extern void disable_local_APIC (void); -extern void lapic_shutdown (void); -extern int verify_local_APIC (void); -extern void cache_APIC_registers (void); -extern void sync_Arb_IDs (void); -extern void init_bsp_APIC (void); -extern void setup_local_APIC (void); -extern void init_apic_mappings (void); -extern void smp_local_timer_interrupt (void); -extern void setup_boot_APIC_clock (void); -extern void setup_secondary_APIC_clock (void); -extern int APIC_init_uniprocessor (void); - -extern void enable_NMI_through_LVT0 (void * dummy); +extern void connect_bsp_APIC(void); +extern void disconnect_bsp_APIC(int virt_wire_setup); +extern void disable_local_APIC(void); +extern void lapic_shutdown(void); +extern int verify_local_APIC(void); +extern void cache_APIC_registers(void); +extern void sync_Arb_IDs(void); +extern void init_bsp_APIC(void); +extern void setup_local_APIC(void); +extern void init_apic_mappings(void); +extern void smp_local_timer_interrupt(void); +extern void setup_boot_APIC_clock(void); +extern void setup_secondary_APIC_clock(void); +extern int APIC_init_uniprocessor(void); +extern void enable_NMI_through_LVT0(void *dummy); #define ARCH_APICTIMER_STOPS_ON_C3 1 -extern int timer_over_8254; -extern int local_apic_timer_c2_ok; - -extern int local_apic_timer_disabled; - #else /* !CONFIG_X86_LOCAL_APIC */ static inline void lapic_shutdown(void) { } #define local_apic_timer_c2_ok 1 diff --git a/include/asm-x86/apic_64.h b/include/asm-x86/apic_64.h index 2747a11a2b19..9a0ec02a49a1 100644 --- a/include/asm-x86/apic_64.h +++ b/include/asm-x86/apic_64.h @@ -64,22 +64,22 @@ static inline void ack_APIC_irq(void) apic_write(APIC_EOI, 0); } -extern int get_maxlvt (void); -extern void clear_local_APIC (void); -extern void connect_bsp_APIC (void); -extern void disconnect_bsp_APIC (int virt_wire_setup); -extern void disable_local_APIC (void); -extern void lapic_shutdown (void); -extern int verify_local_APIC (void); -extern void cache_APIC_registers (void); -extern void sync_Arb_IDs (void); -extern void init_bsp_APIC (void); -extern void setup_local_APIC (void); -extern void init_apic_mappings (void); -extern void smp_local_timer_interrupt (void); -extern void setup_boot_APIC_clock (void); -extern void setup_secondary_APIC_clock (void); -extern int APIC_init_uniprocessor (void); +extern int get_maxlvt(void); +extern void clear_local_APIC(void); +extern void connect_bsp_APIC(void); +extern void disconnect_bsp_APIC(int virt_wire_setup); +extern void disable_local_APIC(void); +extern void lapic_shutdown(void); +extern int verify_local_APIC(void); +extern void cache_APIC_registers(void); +extern void sync_Arb_IDs(void); +extern void init_bsp_APIC(void); +extern void setup_local_APIC(void); +extern void init_apic_mappings(void); +extern void smp_local_timer_interrupt(void); +extern void setup_boot_APIC_clock(void); +extern void setup_secondary_APIC_clock(void); +extern int APIC_init_uniprocessor(void); extern void setup_apic_routing(void); extern void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, @@ -87,13 +87,6 @@ extern void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, extern int apic_is_clustered_box(void); -#define K8_APIC_EXT_LVT_BASE 0x500 -#define K8_APIC_EXT_INT_MSG_FIX 0x0 -#define K8_APIC_EXT_INT_MSG_SMI 0x2 -#define K8_APIC_EXT_INT_MSG_NMI 0x4 -#define K8_APIC_EXT_INT_MSG_EXT 0x7 -#define K8_APIC_EXT_LVT_ENTRY_THRESHOLD 0 - #define ARCH_APICTIMER_STOPS_ON_C3 1 extern unsigned boot_cpu_id; diff --git a/include/asm-x86/apicdef.h b/include/asm-x86/apicdef.h index 83ac1e6e3625..5f7abe9b5f87 100644 --- a/include/asm-x86/apicdef.h +++ b/include/asm-x86/apicdef.h @@ -98,7 +98,7 @@ #define APIC_SEND_PENDING (1<<12) #define APIC_MODE_MASK 0x700 #define GET_APIC_DELIVERY_MODE(x) (((x)>>8)&0x7) -#define SET_APIC_DELIVERY_MODE(x,y) (((x)&~0x700)|((y)<<8)) +#define SET_APIC_DELIVERY_MODE(x, y) (((x)&~0x700)|((y)<<8)) #define APIC_MODE_FIXED 0x0 #define APIC_MODE_NMI 0x4 #define APIC_MODE_EXTINT 0x7 @@ -116,6 +116,14 @@ #define APIC_TDR_DIV_32 0x8 #define APIC_TDR_DIV_64 0x9 #define APIC_TDR_DIV_128 0xA + +#define K8_APIC_EXT_LVT_BASE 0x500 +#define K8_APIC_EXT_INT_MSG_FIX 0x0 +#define K8_APIC_EXT_INT_MSG_SMI 0x2 +#define K8_APIC_EXT_INT_MSG_NMI 0x4 +#define K8_APIC_EXT_INT_MSG_EXT 0x7 +#define K8_APIC_EXT_LVT_ENTRY_THRESHOLD 0 + #define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) #ifdef CONFIG_X86_32 From 37e650c7c8a27de533d409b53c29f4135dcc7af6 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:14 +0100 Subject: [PATCH 054/890] x86: rename get_maxlvt to lapic_get_maxlvt Use the same name for the 32 and 64 bit variant. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 12 ++++++------ arch/x86/kernel/io_apic_64.c | 2 +- arch/x86/kernel/smpboot_64.c | 2 +- include/asm-x86/apic_64.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index fa6cdee6d303..dfeda91fa80c 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -160,7 +160,7 @@ void enable_NMI_through_LVT0 (void * dummy) apic_write(APIC_LVT0, v); } -int get_maxlvt(void) +int lapic_get_maxlvt(void) { unsigned int v, maxlvt; @@ -194,7 +194,7 @@ void clear_local_APIC(void) int maxlvt; unsigned int v; - maxlvt = get_maxlvt(); + maxlvt = lapic_get_maxlvt(); /* * Masking an LVT entry can trigger a local APIC error @@ -333,7 +333,7 @@ int __init verify_local_APIC(void) reg1 = GET_APIC_VERSION(reg0); if (reg1 == 0x00 || reg1 == 0xff) return 0; - reg1 = get_maxlvt(); + reg1 = lapic_get_maxlvt(); if (reg1 < 0x02 || reg1 == 0xff) return 0; @@ -519,7 +519,7 @@ void __cpuinit setup_local_APIC (void) { unsigned oldvalue; - maxlvt = get_maxlvt(); + maxlvt = lapic_get_maxlvt(); oldvalue = apic_read(APIC_ESR); value = ERROR_APIC_VECTOR; // enables sending errors apic_write(APIC_LVTERR, value); @@ -571,7 +571,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) if (!apic_pm_state.active) return 0; - maxlvt = get_maxlvt(); + maxlvt = lapic_get_maxlvt(); apic_pm_state.apic_id = apic_read(APIC_ID); apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); @@ -605,7 +605,7 @@ static int lapic_resume(struct sys_device *dev) if (!apic_pm_state.active) return 0; - maxlvt = get_maxlvt(); + maxlvt = lapic_get_maxlvt(); local_irq_save(flags); rdmsr(MSR_IA32_APICBASE, l, h); diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 23a3ac06a23e..d4f5286101a9 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -1069,7 +1069,7 @@ void __apicdebuginit print_local_APIC(void * dummy) v = apic_read(APIC_LVR); printk(KERN_INFO "... APIC VERSION: %08x\n", v); ver = GET_APIC_VERSION(v); - maxlvt = get_maxlvt(); + maxlvt = lapic_get_maxlvt(); v = apic_read(APIC_TASKPRI); printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK); diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c index aaf4e1291217..8147b7d4db63 100644 --- a/arch/x86/kernel/smpboot_64.c +++ b/arch/x86/kernel/smpboot_64.c @@ -466,7 +466,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta */ Dprintk("#startup loops: %d.\n", num_starts); - maxlvt = get_maxlvt(); + maxlvt = lapic_get_maxlvt(); for (j = 1; j <= num_starts; j++) { Dprintk("Sending STARTUP #%d.\n",j); diff --git a/include/asm-x86/apic_64.h b/include/asm-x86/apic_64.h index 9a0ec02a49a1..b5f850f25114 100644 --- a/include/asm-x86/apic_64.h +++ b/include/asm-x86/apic_64.h @@ -64,7 +64,7 @@ static inline void ack_APIC_irq(void) apic_write(APIC_EOI, 0); } -extern int get_maxlvt(void); +extern int lapic_get_maxlvt(void); extern void clear_local_APIC(void); extern void connect_bsp_APIC(void); extern void disconnect_bsp_APIC(int virt_wire_setup); From 3c6bb07ac1b4174318606a26f0de8ceb9f6d8133 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:15 +0100 Subject: [PATCH 055/890] x86: use u32 for safe_apic_wait_icr_idle() Preperatory patch for merging apic headers. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_64.c | 4 ++-- arch/x86/kernel/smpboot_64.c | 11 ++++++----- include/asm-x86/apic_64.h | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index dfeda91fa80c..3de3764a862c 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -135,9 +135,9 @@ void apic_wait_icr_idle(void) cpu_relax(); } -unsigned int safe_apic_wait_icr_idle(void) +u32 safe_apic_wait_icr_idle(void) { - unsigned int send_status; + u32 send_status; int timeout; timeout = 0; diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c index 8147b7d4db63..b36d32ff0b39 100644 --- a/arch/x86/kernel/smpboot_64.c +++ b/arch/x86/kernel/smpboot_64.c @@ -384,19 +384,20 @@ static void inquire_remote_apic(int apicid) unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; char *names[] = { "ID", "VERSION", "SPIV" }; int timeout; - unsigned int status; + u32 status; printk(KERN_INFO "Inquiring remote APIC #%d...\n", apicid); for (i = 0; i < ARRAY_SIZE(regs); i++) { - printk("... APIC #%d %s: ", apicid, names[i]); + printk(KERN_INFO "... APIC #%d %s: ", apicid, names[i]); /* * Wait for idle. */ status = safe_apic_wait_icr_idle(); if (status) - printk("a previous APIC delivery may have failed\n"); + printk(KERN_CONT + "a previous APIC delivery may have failed\n"); apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]); @@ -410,10 +411,10 @@ static void inquire_remote_apic(int apicid) switch (status) { case APIC_ICR_RR_VALID: status = apic_read(APIC_RRR); - printk("%08x\n", status); + printk(KERN_CONT "%08x\n", status); break; default: - printk("failed\n"); + printk(KERN_CONT "failed\n"); } } } diff --git a/include/asm-x86/apic_64.h b/include/asm-x86/apic_64.h index b5f850f25114..7bfad0224178 100644 --- a/include/asm-x86/apic_64.h +++ b/include/asm-x86/apic_64.h @@ -49,7 +49,7 @@ static __inline unsigned int apic_read(unsigned long reg) } extern void apic_wait_icr_idle(void); -extern unsigned int safe_apic_wait_icr_idle(void); +extern u32 safe_apic_wait_icr_idle(void); static inline void ack_APIC_irq(void) { From 42e0a9aa5d467188687c6b705412578e53c14af6 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:15 +0100 Subject: [PATCH 056/890] x86: use u32 for some lapic functions Use u32 so 32 and 64bit have the same interface. Andrew Morton: xen, lguest build fixes Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/apic_32.c | 4 ++-- arch/x86/lguest/boot.c | 4 ++-- arch/x86/xen/enlighten.c | 4 ++-- include/asm-x86/apic_32.h | 16 +++++++--------- include/asm-x86/apic_64.h | 6 +++--- include/asm-x86/paravirt.h | 12 ++++++------ 6 files changed, 22 insertions(+), 24 deletions(-) diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index a56c782653be..3a069acb270c 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -135,9 +135,9 @@ void apic_wait_icr_idle(void) cpu_relax(); } -unsigned long safe_apic_wait_icr_idle(void) +u32 safe_apic_wait_icr_idle(void) { - unsigned long send_status; + u32 send_status; int timeout; timeout = 0; diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 92c56117eae5..df04bf884dd4 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -788,11 +788,11 @@ static void lguest_wbinvd(void) * code qualifies for Advanced. It will also never interrupt anything. It * does, however, allow us to get through the Linux boot code. */ #ifdef CONFIG_X86_LOCAL_APIC -static void lguest_apic_write(unsigned long reg, unsigned long v) +static void lguest_apic_write(unsigned long reg, u32 v) { } -static unsigned long lguest_apic_read(unsigned long reg) +static u32 lguest_apic_read(unsigned long reg) { return 0; } diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 79ad15252150..00829401389e 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -521,12 +521,12 @@ static void xen_io_delay(void) } #ifdef CONFIG_X86_LOCAL_APIC -static unsigned long xen_apic_read(unsigned long reg) +static u32 xen_apic_read(unsigned long reg) { return 0; } -static void xen_apic_write(unsigned long reg, unsigned long val) +static void xen_apic_write(unsigned long reg, u32 val) { /* Warn to see if there's any stray references */ WARN_ON(1); diff --git a/include/asm-x86/apic_32.h b/include/asm-x86/apic_32.h index f909e2daf226..649e9a6f6683 100644 --- a/include/asm-x86/apic_32.h +++ b/include/asm-x86/apic_32.h @@ -51,25 +51,23 @@ extern int local_apic_timer_disabled; #define setup_secondary_clock setup_secondary_APIC_clock #endif -static __inline fastcall void native_apic_write(unsigned long reg, - unsigned long v) +static __inline fastcall void native_apic_write(unsigned long reg, u32 v) { - *((volatile unsigned long *)(APIC_BASE+reg)) = v; + *((volatile u32 *)(APIC_BASE + reg)) = v; } -static __inline fastcall void native_apic_write_atomic(unsigned long reg, - unsigned long v) +static __inline fastcall void native_apic_write_atomic(unsigned long reg, u32 v) { - xchg((volatile unsigned long *)(APIC_BASE+reg), v); + (void) xchg((u32 *)(APIC_BASE + reg), v); } -static __inline fastcall unsigned long native_apic_read(unsigned long reg) +static __inline fastcall u32 native_apic_read(unsigned long reg) { - return *((volatile unsigned long *)(APIC_BASE+reg)); + return *((volatile u32 *)(APIC_BASE + reg)); } extern void apic_wait_icr_idle(void); -extern unsigned long safe_apic_wait_icr_idle(void); +extern u32 safe_apic_wait_icr_idle(void); extern int get_physical_broadcast(void); #ifdef CONFIG_X86_GOOD_APIC diff --git a/include/asm-x86/apic_64.h b/include/asm-x86/apic_64.h index 7bfad0224178..9d0c06c4df91 100644 --- a/include/asm-x86/apic_64.h +++ b/include/asm-x86/apic_64.h @@ -38,14 +38,14 @@ struct pt_regs; * Basic functions accessing APICs. */ -static __inline void apic_write(unsigned long reg, unsigned int v) +static __inline void apic_write(unsigned long reg, u32 v) { *((volatile unsigned int *)(APIC_BASE+reg)) = v; } -static __inline unsigned int apic_read(unsigned long reg) +static __inline u32 apic_read(unsigned long reg) { - return *((volatile unsigned int *)(APIC_BASE+reg)); + return *((volatile u32 *)(APIC_BASE+reg)); } extern void apic_wait_icr_idle(void); diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index f59d370c5df4..19fd3e67b08c 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -150,9 +150,9 @@ struct pv_apic_ops { * Direct APIC operations, principally for VMI. Ideally * these shouldn't be in this interface. */ - void (*apic_write)(unsigned long reg, unsigned long v); - void (*apic_write_atomic)(unsigned long reg, unsigned long v); - unsigned long (*apic_read)(unsigned long reg); + void (*apic_write)(unsigned long reg, u32 v); + void (*apic_write_atomic)(unsigned long reg, u32 v); + u32 (*apic_read)(unsigned long reg); void (*setup_boot_clock)(void); void (*setup_secondary_clock)(void); @@ -690,17 +690,17 @@ static inline void slow_down_io(void) { /* * Basic functions accessing APICs. */ -static inline void apic_write(unsigned long reg, unsigned long v) +static inline void apic_write(unsigned long reg, u32 v) { PVOP_VCALL2(pv_apic_ops.apic_write, reg, v); } -static inline void apic_write_atomic(unsigned long reg, unsigned long v) +static inline void apic_write_atomic(unsigned long reg, u32 v) { PVOP_VCALL2(pv_apic_ops.apic_write_atomic, reg, v); } -static inline unsigned long apic_read(unsigned long reg) +static inline u32 apic_read(unsigned long reg) { return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg); } From 67c5fc5c330f63360e26609534b219df1aaa03ca Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:15 +0100 Subject: [PATCH 057/890] x86: merge apic_32/64.h Unify apic.h variants. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- include/asm-x86/apic.h | 140 +++++++++++++++++++++++++++++++++++++- include/asm-x86/apic_32.h | 122 --------------------------------- include/asm-x86/apic_64.h | 95 -------------------------- 3 files changed, 137 insertions(+), 220 deletions(-) delete mode 100644 include/asm-x86/apic_32.h delete mode 100644 include/asm-x86/apic_64.h diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h index 9fbcc0bd2ac4..c064c1f84bab 100644 --- a/include/asm-x86/apic.h +++ b/include/asm-x86/apic.h @@ -1,5 +1,139 @@ -#ifdef CONFIG_X86_32 -# include "apic_32.h" +#ifndef _ASM_X86_APIC_H +#define _ASM_X86_APIC_H + +#include +#include +#include +#include +#include +#include + +#define ARCH_APICTIMER_STOPS_ON_C3 1 + +#define Dprintk(x...) + +/* + * Debugging macros + */ +#define APIC_QUIET 0 +#define APIC_VERBOSE 1 +#define APIC_DEBUG 2 + +/* + * Define the default level of output to be very little + * This can be turned up by using apic=verbose for more + * information and apic=debug for _lots_ of information. + * apic_verbosity is defined in apic.c + */ +#define apic_printk(v, s, a...) do { \ + if ((v) <= apic_verbosity) \ + printk(s, ##a); \ + } while (0) + + +extern void generic_apic_probe(void); + +#ifdef CONFIG_X86_LOCAL_APIC + +extern int apic_verbosity; +extern int timer_over_8254; +extern int local_apic_timer_c2_ok; +extern int local_apic_timer_disabled; + +extern int apic_runs_main_timer; +extern int ioapic_force; +extern int disable_apic_timer; +extern unsigned boot_cpu_id; + +/* + * Basic functions accessing APICs. + */ +#ifdef CONFIG_PARAVIRT +#include #else -# include "apic_64.h" +#define apic_write native_apic_write +#define apic_write_atomic native_apic_write_atomic +#define apic_read native_apic_read +#define setup_boot_clock setup_boot_APIC_clock +#define setup_secondary_clock setup_secondary_APIC_clock #endif + +static inline fastcall void native_apic_write(unsigned long reg, u32 v) +{ + *((volatile u32 *)(APIC_BASE + reg)) = v; +} + +static inline fastcall void native_apic_write_atomic(unsigned long reg, u32 v) +{ + (void) xchg((u32*)(APIC_BASE + reg), v); +} + +static inline fastcall u32 native_apic_read(unsigned long reg) +{ + return *((volatile u32 *)(APIC_BASE + reg)); +} + +extern void apic_wait_icr_idle(void); +extern u32 safe_apic_wait_icr_idle(void); +extern int get_physical_broadcast(void); + +#ifdef CONFIG_X86_GOOD_APIC +# define FORCE_READ_AROUND_WRITE 0 +# define apic_read_around(x) +# define apic_write_around(x, y) apic_write((x), (y)) +#else +# define FORCE_READ_AROUND_WRITE 1 +# define apic_read_around(x) apic_read(x) +# define apic_write_around(x, y) apic_write_atomic((x), (y)) +#endif + +static inline void ack_APIC_irq(void) +{ + /* + * ack_APIC_irq() actually gets compiled as a single instruction: + * - a single rmw on Pentium/82489DX + * - a single write on P6+ cores (CONFIG_X86_GOOD_APIC) + * ... yummie. + */ + + /* Docs say use 0 for future compatibility */ + apic_write_around(APIC_EOI, 0); +} + +extern int lapic_get_maxlvt(void); +extern void clear_local_APIC(void); +extern void connect_bsp_APIC(void); +extern void disconnect_bsp_APIC(int virt_wire_setup); +extern void disable_local_APIC(void); +extern void lapic_shutdown(void); +extern int verify_local_APIC(void); +extern void cache_APIC_registers(void); +extern void sync_Arb_IDs(void); +extern void init_bsp_APIC(void); +extern void setup_local_APIC(void); +extern void init_apic_mappings(void); +extern void smp_local_timer_interrupt(void); +extern void setup_boot_APIC_clock(void); +extern void setup_secondary_APIC_clock(void); +extern int APIC_init_uniprocessor(void); +extern void enable_NMI_through_LVT0(void *dummy); + +/* + * On 32bit this is mach-xxx local + */ +#ifdef CONFIG_X86_64 +extern void setup_apic_routing(void); +#endif + +extern void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, + unsigned char msg_type, unsigned char mask); + +extern int apic_is_clustered_box(void); + +#else /* !CONFIG_X86_LOCAL_APIC */ +static inline void lapic_shutdown(void) { } +#define local_apic_timer_c2_ok 1 + +#endif /* !CONFIG_X86_LOCAL_APIC */ + +#endif /* __ASM_APIC_H */ diff --git a/include/asm-x86/apic_32.h b/include/asm-x86/apic_32.h deleted file mode 100644 index 649e9a6f6683..000000000000 --- a/include/asm-x86/apic_32.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef __ASM_APIC_H -#define __ASM_APIC_H - -#include -#include -#include -#include -#include -#include - -#define Dprintk(x...) - -/* - * Debugging macros - */ -#define APIC_QUIET 0 -#define APIC_VERBOSE 1 -#define APIC_DEBUG 2 - -/* - * Define the default level of output to be very little - * This can be turned up by using apic=verbose for more - * information and apic=debug for _lots_ of information. - * apic_verbosity is defined in apic.c - */ -#define apic_printk(v, s, a...) do { \ - if ((v) <= apic_verbosity) \ - printk(s, ##a); \ - } while (0) - - -extern void generic_apic_probe(void); - -#ifdef CONFIG_X86_LOCAL_APIC - -extern int apic_verbosity; -extern int timer_over_8254; -extern int local_apic_timer_c2_ok; -extern int local_apic_timer_disabled; - -/* - * Basic functions accessing APICs. - */ -#ifdef CONFIG_PARAVIRT -#include -#else -#define apic_write native_apic_write -#define apic_write_atomic native_apic_write_atomic -#define apic_read native_apic_read -#define setup_boot_clock setup_boot_APIC_clock -#define setup_secondary_clock setup_secondary_APIC_clock -#endif - -static __inline fastcall void native_apic_write(unsigned long reg, u32 v) -{ - *((volatile u32 *)(APIC_BASE + reg)) = v; -} - -static __inline fastcall void native_apic_write_atomic(unsigned long reg, u32 v) -{ - (void) xchg((u32 *)(APIC_BASE + reg), v); -} - -static __inline fastcall u32 native_apic_read(unsigned long reg) -{ - return *((volatile u32 *)(APIC_BASE + reg)); -} - -extern void apic_wait_icr_idle(void); -extern u32 safe_apic_wait_icr_idle(void); -extern int get_physical_broadcast(void); - -#ifdef CONFIG_X86_GOOD_APIC -# define FORCE_READ_AROUND_WRITE 0 -# define apic_read_around(x) -# define apic_write_around(x,y) apic_write((x),(y)) -#else -# define FORCE_READ_AROUND_WRITE 1 -# define apic_read_around(x) apic_read(x) -# define apic_write_around(x,y) apic_write_atomic((x),(y)) -#endif - -static inline void ack_APIC_irq(void) -{ - /* - * ack_APIC_irq() actually gets compiled as a single instruction: - * - a single rmw on Pentium/82489DX - * - a single write on P6+ cores (CONFIG_X86_GOOD_APIC) - * ... yummie. - */ - - /* Docs say use 0 for future compatibility */ - apic_write_around(APIC_EOI, 0); -} - -extern int lapic_get_maxlvt(void); -extern void clear_local_APIC(void); -extern void connect_bsp_APIC(void); -extern void disconnect_bsp_APIC(int virt_wire_setup); -extern void disable_local_APIC(void); -extern void lapic_shutdown(void); -extern int verify_local_APIC(void); -extern void cache_APIC_registers(void); -extern void sync_Arb_IDs(void); -extern void init_bsp_APIC(void); -extern void setup_local_APIC(void); -extern void init_apic_mappings(void); -extern void smp_local_timer_interrupt(void); -extern void setup_boot_APIC_clock(void); -extern void setup_secondary_APIC_clock(void); -extern int APIC_init_uniprocessor(void); -extern void enable_NMI_through_LVT0(void *dummy); - -#define ARCH_APICTIMER_STOPS_ON_C3 1 - -#else /* !CONFIG_X86_LOCAL_APIC */ -static inline void lapic_shutdown(void) { } -#define local_apic_timer_c2_ok 1 - -#endif /* !CONFIG_X86_LOCAL_APIC */ - -#endif /* __ASM_APIC_H */ diff --git a/include/asm-x86/apic_64.h b/include/asm-x86/apic_64.h deleted file mode 100644 index 9d0c06c4df91..000000000000 --- a/include/asm-x86/apic_64.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef __ASM_APIC_H -#define __ASM_APIC_H - -#include -#include -#include -#include -#include - -#define Dprintk(x...) - -/* - * Debugging macros - */ -#define APIC_QUIET 0 -#define APIC_VERBOSE 1 -#define APIC_DEBUG 2 - -extern int apic_verbosity; -extern int apic_runs_main_timer; -extern int ioapic_force; -extern int disable_apic_timer; - -/* - * Define the default level of output to be very little - * This can be turned up by using apic=verbose for more - * information and apic=debug for _lots_ of information. - * apic_verbosity is defined in apic.c - */ -#define apic_printk(v, s, a...) do { \ - if ((v) <= apic_verbosity) \ - printk(s, ##a); \ - } while (0) - -struct pt_regs; - -/* - * Basic functions accessing APICs. - */ - -static __inline void apic_write(unsigned long reg, u32 v) -{ - *((volatile unsigned int *)(APIC_BASE+reg)) = v; -} - -static __inline u32 apic_read(unsigned long reg) -{ - return *((volatile u32 *)(APIC_BASE+reg)); -} - -extern void apic_wait_icr_idle(void); -extern u32 safe_apic_wait_icr_idle(void); - -static inline void ack_APIC_irq(void) -{ - /* - * ack_APIC_irq() actually gets compiled as a single instruction: - * - a single rmw on Pentium/82489DX - * - a single write on P6+ cores (CONFIG_X86_GOOD_APIC) - * ... yummie. - */ - - /* Docs say use 0 for future compatibility */ - apic_write(APIC_EOI, 0); -} - -extern int lapic_get_maxlvt(void); -extern void clear_local_APIC(void); -extern void connect_bsp_APIC(void); -extern void disconnect_bsp_APIC(int virt_wire_setup); -extern void disable_local_APIC(void); -extern void lapic_shutdown(void); -extern int verify_local_APIC(void); -extern void cache_APIC_registers(void); -extern void sync_Arb_IDs(void); -extern void init_bsp_APIC(void); -extern void setup_local_APIC(void); -extern void init_apic_mappings(void); -extern void smp_local_timer_interrupt(void); -extern void setup_boot_APIC_clock(void); -extern void setup_secondary_APIC_clock(void); -extern int APIC_init_uniprocessor(void); -extern void setup_apic_routing(void); - -extern void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, - unsigned char msg_type, unsigned char mask); - -extern int apic_is_clustered_box(void); - -#define ARCH_APICTIMER_STOPS_ON_C3 1 - -extern unsigned boot_cpu_id; -extern int local_apic_timer_c2_ok; - -#endif /* __ASM_APIC_H */ From 63fefb7d5bac6e65b5df2b7eb4aa56bb4bbadd48 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:15 +0100 Subject: [PATCH 058/890] x86: remove duplicated declarations Remove declarations which are made already in the appropriate header file. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- include/asm-x86/io_apic_64.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/asm-x86/io_apic_64.h b/include/asm-x86/io_apic_64.h index e2c13675ee4e..762a841b939e 100644 --- a/include/asm-x86/io_apic_64.h +++ b/include/asm-x86/io_apic_64.h @@ -129,10 +129,4 @@ extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int, int); extern int sis_apic_bug; /* dummy */ -void enable_NMI_through_LVT0 (void * dummy); - -extern spinlock_t i8259A_lock; - -extern int timer_over_8254; - #endif From 376ff0352c24a5fa47f1250dd60937b5a9077672 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 30 Jan 2008 13:30:16 +0100 Subject: [PATCH 059/890] x86: move acpi and pci declarations Move acpi/pci related declarations to the correct headers and remove the duplicate. Build fix from: Andrew Morton Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup_32.c | 3 +-- arch/x86/kernel/setup_64.c | 2 -- include/asm-x86/acpi_32.h | 2 -- include/asm-x86/pci.h | 4 +++- include/asm-x86/proto.h | 3 --- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index 51bdc0b1b72e..236d30b264d8 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -44,6 +44,7 @@ #include #include #include +#include #include