···3737/* includes */3838#include "fpsr.h" /* FP control and status register definitions */3939#include "milieu.h"4040+4141+struct roundingData {4242+ int8 mode;4343+ int8 precision;4444+ signed char exception;4545+};4646+4047#include "softfloat.h"41484249#define typeNone 0x00···9184 initialised. */9285} FPA11;93869494-extern void SetRoundingMode(const unsigned int);9595-extern void SetRoundingPrecision(const unsigned int);8787+extern int8 SetRoundingMode(const unsigned int);8888+extern int8 SetRoundingPrecision(const unsigned int);9689extern void nwfpe_init_fpa(union fp_state *fp);97909891#endif
+17-11
arch/arm/nwfpe/fpa11_cpdo.c
···2424#include "fpa11.h"2525#include "fpopcode.h"26262727-unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd);2828-unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd);2929-unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd);2727+unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);2828+unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);2929+unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);30303131unsigned int EmulateCPDO(const unsigned int opcode)3232{3333 FPA11 *fpa11 = GET_FPA11();3434 FPREG *rFd;3535 unsigned int nType, nDest, nRc;3636+ struct roundingData roundData;36373738 /* Get the destination size. If not valid let Linux perform3839 an invalid instruction trap. */···4140 if (typeNone == nDest)4241 return 0;43424444- SetRoundingMode(opcode);4343+ roundData.mode = SetRoundingMode(opcode);4444+ roundData.precision = SetRoundingPrecision(opcode);4545+ roundData.exception = 0;45464647 /* Compare the size of the operands in Fn and Fm.4748 Choose the largest size and perform operations in that size,···66636764 switch (nType) {6865 case typeSingle:6969- nRc = SingleCPDO(opcode, rFd);6666+ nRc = SingleCPDO(&roundData, opcode, rFd);7067 break;7168 case typeDouble:7272- nRc = DoubleCPDO(opcode, rFd);6969+ nRc = DoubleCPDO(&roundData, opcode, rFd);7370 break;7471#ifdef CONFIG_FPE_NWFPE_XP7572 case typeExtended:7676- nRc = ExtendedCPDO(opcode, rFd);7373+ nRc = ExtendedCPDO(&roundData, opcode, rFd);7774 break;7875#endif7976 default:···9693 case typeSingle:9794 {9895 if (typeDouble == nType)9999- rFd->fSingle = float64_to_float32(rFd->fDouble);9696+ rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);10097 else101101- rFd->fSingle = floatx80_to_float32(rFd->fExtended);9898+ rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended);10299 }103100 break;104101···107104 if (typeSingle == nType)108105 rFd->fDouble = float32_to_float64(rFd->fSingle);109106 else110110- rFd->fDouble = floatx80_to_float64(rFd->fExtended);107107+ rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended);111108 }112109 break;113110···124121#else125122 if (nDest != nType) {126123 if (nDest == typeSingle)127127- rFd->fSingle = float64_to_float32(rFd->fDouble);124124+ rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);128125 else129126 rFd->fDouble = float32_to_float64(rFd->fSingle);130127 }131128#endif132129 }130130+131131+ if (roundData.exception)132132+ float_raise(roundData.exception);133133134134 return nRc;135135}
+14-8
arch/arm/nwfpe/fpa11_cpdt.c
···9696 }9797}98989999-static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem)9999+static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)100100{101101 FPA11 *fpa11 = GET_FPA11();102102 union {···106106107107 switch (fpa11->fType[Fn]) {108108 case typeDouble:109109- val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);109109+ val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);110110 break;111111112112#ifdef CONFIG_FPE_NWFPE_XP113113 case typeExtended:114114- val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);114114+ val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);115115 break;116116#endif117117···122122 put_user(val.i[0], pMem);123123}124124125125-static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)125125+static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)126126{127127 FPA11 *fpa11 = GET_FPA11();128128 union {···137137138138#ifdef CONFIG_FPE_NWFPE_XP139139 case typeExtended:140140- val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);140140+ val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);141141 break;142142#endif143143···259259{260260 unsigned int __user *pBase, *pAddress, *pFinal;261261 unsigned int nRc = 1, write_back = WRITE_BACK(opcode);262262+ struct roundingData roundData;262263263263- SetRoundingMode(ROUND_TO_NEAREST);264264+ roundData.mode = SetRoundingMode(opcode);265265+ roundData.precision = SetRoundingPrecision(opcode);266266+ roundData.exception = 0;264267265268 pBase = (unsigned int __user *) readRegister(getRn(opcode));266269 if (REG_PC == getRn(opcode)) {···284281285282 switch (opcode & MASK_TRANSFER_LENGTH) {286283 case TRANSFER_SINGLE:287287- storeSingle(getFd(opcode), pAddress);284284+ storeSingle(&roundData, getFd(opcode), pAddress);288285 break;289286 case TRANSFER_DOUBLE:290290- storeDouble(getFd(opcode), pAddress);287287+ storeDouble(&roundData, getFd(opcode), pAddress);291288 break;292289#ifdef CONFIG_FPE_NWFPE_XP293290 case TRANSFER_EXTENDED:···297294 default:298295 nRc = 0;299296 }297297+298298+ if (roundData.exception)299299+ float_raise(roundData.exception);300300301301 if (write_back)302302 writeRegister(getRn(opcode), (unsigned long) pFinal);
+19-9
arch/arm/nwfpe/fpa11_cprt.c
···3333extern flag float64_is_nan(float64);3434extern flag float32_is_nan(float32);35353636-void SetRoundingMode(const unsigned int opcode);3737-3836unsigned int PerformFLT(const unsigned int opcode);3937unsigned int PerformFIX(const unsigned int opcode);4038···7577unsigned int PerformFLT(const unsigned int opcode)7678{7779 FPA11 *fpa11 = GET_FPA11();7878- SetRoundingMode(opcode);7979- SetRoundingPrecision(opcode);8080+ struct roundingData roundData;8181+8282+ roundData.mode = SetRoundingMode(opcode);8383+ roundData.precision = SetRoundingPrecision(opcode);8484+ roundData.exception = 0;80858186 switch (opcode & MASK_ROUNDING_PRECISION) {8287 case ROUND_SINGLE:8388 {8489 fpa11->fType[getFn(opcode)] = typeSingle;8585- fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode)));9090+ fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode)));8691 }8792 break;8893···109108 return 0;110109 }111110111111+ if (roundData.exception)112112+ float_raise(roundData.exception);113113+112114 return 1;113115}114116···119115{120116 FPA11 *fpa11 = GET_FPA11();121117 unsigned int Fn = getFm(opcode);118118+ struct roundingData roundData;122119123123- SetRoundingMode(opcode);120120+ roundData.mode = SetRoundingMode(opcode);121121+ roundData.precision = SetRoundingPrecision(opcode);122122+ roundData.exception = 0;124123125124 switch (fpa11->fType[Fn]) {126125 case typeSingle:127126 {128128- writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle));127127+ writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle));129128 }130129 break;131130132131 case typeDouble:133132 {134134- writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble));133133+ writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble));135134 }136135 break;137136138137#ifdef CONFIG_FPE_NWFPE_XP139138 case typeExtended:140139 {141141- writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended));140140+ writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended));142141 }143142 break;144143#endif···149142 default:150143 return 0;151144 }145145+146146+ if (roundData.exception)147147+ float_raise(roundData.exception);152148153149 return 1;154150}
+6-9
arch/arm/nwfpe/fpmodule.c
···116116code to access data in user space in some other source files at the 117117moment (grep for get_user / put_user calls). --philb]118118119119-float_exception_flags is a global variable in SoftFloat.120120-121119This function is called by the SoftFloat routines to raise a floating122120point exception. We check the trap enable byte in the FPSR, and raise123121a SIGFPE exception if necessary. If not the relevant bits in the ···127129 register unsigned int fpsr, cumulativeTraps;128130129131#ifdef CONFIG_DEBUG_USER130130- printk(KERN_DEBUG131131- "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",132132- current->comm, current->pid, flags,133133- __builtin_return_address(0), GET_USERREG()->ARM_pc);132132+ /* Ignore inexact errors as there are far too many of them to log */133133+ if (flags & ~BIT_IXC)134134+ printk(KERN_DEBUG135135+ "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n",136136+ current->comm, current->pid, flags,137137+ __builtin_return_address(0), GET_USERREG()->ARM_pc);134138#endif135135-136136- /* Keep SoftFloat exception flags up to date. */137137- float_exception_flags |= flags;138139139140 /* Read fpsr and initialize the cumulativeTraps. */140141 fpsr = readFPSR();
···3636#include <asm/uaccess.h>37373838#define OSCR_FREQ CLOCK_TICK_RATE3939-#define SA1100_CLOSE_MAGIC (0x5afc4453)40394140static unsigned long sa1100wdt_users;4242-static int expect_close;4341static int pre_margin;4442static int boot_status;4545-static int nowayout = WATCHDOG_NOWAYOUT;46434744/*4845 * Allow only one person to hold it open···5962}60636164/*6262- * Shut off the timer.6363- * Lock it in if it's a module and we defined ...NOWAYOUT6464- * Oddly, the watchdog can only be enabled, but we can turn off6565- * the interrupt, which appears to prevent the watchdog timing out.6565+ * The watchdog cannot be disabled.6666+ *6767+ * Previous comments suggested that turning off the interrupt by6868+ * clearing OIER[E3] would prevent the watchdog timing out but this6969+ * does not appear to be true (at least on the PXA255).6670 */6771static int sa1100dog_release(struct inode *inode, struct file *file)6872{6969- OSMR3 = OSCR + pre_margin;7070-7171- if (expect_close == SA1100_CLOSE_MAGIC) {7272- OIER &= ~OIER_E3;7373- } else {7474- printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n");7575- }7373+ printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n");76747775 clear_bit(1, &sa1100wdt_users);7878- expect_close = 0;79768077 return 0;8178}82798380static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)8481{8585- if (len) {8686- if (!nowayout) {8787- size_t i;8888-8989- expect_close = 0;9090-9191- for (i = 0; i != len; i++) {9292- char c;9393-9494- if (get_user(c, data + i))9595- return -EFAULT;9696- if (c == 'V')9797- expect_close = SA1100_CLOSE_MAGIC;9898- }9999- }8282+ if (len)10083 /* Refresh OSMR3 timer. */10184 OSMR3 = OSCR + pre_margin;102102- }1038510486 return len;10587}1068810789static struct watchdog_info ident = {108108- .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |109109- WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,110110- .identity = "SA1100 Watchdog",9090+ .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,9191+ .identity = "SA1100/PXA255 Watchdog",11192};1129311394static int sa1100dog_ioctl(struct inode *inode, struct file *file,···147172static struct miscdevice sa1100dog_miscdev =148173{149174 .minor = WATCHDOG_MINOR,150150- .name = "SA1100/PXA2xx watchdog",175175+ .name = "watchdog",151176 .fops = &sa1100dog_fops,152177};153178···169194 if (ret == 0)170195 printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",171196 margin);172172-173197 return ret;174198}175199···185211186212module_param(margin, int, 0);187213MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");188188-189189-module_param(nowayout, int, 0);190190-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");191214192215MODULE_LICENSE("GPL");193216MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);