···711711/*712712 * Change "struct page" to physical address.713713 */714714-#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)714714+#define page_to_phys(page) ((phys_addr_t)page_to_pfn(page) << PAGE_SHIFT)715715716716/* We do NOT want virtual merging, it would put too much pressure on717717 * our iommu allocator. Instead, we want drivers to be smart enough
+7-1
arch/powerpc/include/asm/page_32.h
···1313#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES1414#endif15151616+#ifdef CONFIG_PTE_64BIT1717+#define PTE_FLAGS_OFFSET 4 /* offset of PTE flags, in bytes */1818+#else1919+#define PTE_FLAGS_OFFSET 02020+#endif2121+1622#ifndef __ASSEMBLY__1723/*1824 * The basic type of a PTE - 64 bits for those CPUs with > 32 bit1919- * physical addressing. For now this just the IBM PPC440.2525+ * physical addressing.2026 */2127#ifdef CONFIG_PTE_64BIT2228typedef unsigned long long pte_basic_t;
+49-10
arch/powerpc/include/asm/pgtable-ppc32.h
···261261#define _PAGE_HWEXEC 0x00000004 /* H: Execute permission */262262#define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */263263#define _PAGE_DIRTY 0x00000010 /* S: Page dirty */264264+#define _PAGE_SPECIAL 0x00000020 /* S: Special page */264265#define _PAGE_USER 0x00000040 /* S: User page */265266#define _PAGE_ENDIAN 0x00000080 /* H: E bit */266267#define _PAGE_GUARDED 0x00000100 /* H: G bit */···277276/* ERPN in a PTE never gets cleared, ignore it */278277#define _PTE_NONE_MASK 0xffffffff00000000ULL279278279279+#define __HAVE_ARCH_PTE_SPECIAL280280281281#elif defined(CONFIG_FSL_BOOKE)282282/*···307305#define _PAGE_COHERENT 0x00100 /* H: M bit */308306#define _PAGE_NO_CACHE 0x00200 /* H: I bit */309307#define _PAGE_WRITETHRU 0x00400 /* H: W bit */308308+#define _PAGE_SPECIAL 0x00800 /* S: Special page */310309311310#ifdef CONFIG_PTE_64BIT312311/* ERPN in a PTE never gets cleared, ignore it */···317314#define _PMD_PRESENT 0318315#define _PMD_PRESENT_MASK (PAGE_MASK)319316#define _PMD_BAD (~PAGE_MASK)317317+318318+#define __HAVE_ARCH_PTE_SPECIAL320319321320#elif defined(CONFIG_8xx)322321/* Definitions for 8xx embedded chips. */···367362#define _PAGE_ACCESSED 0x100 /* R: page referenced */368363#define _PAGE_EXEC 0x200 /* software: i-cache coherency required */369364#define _PAGE_RW 0x400 /* software: user write access allowed */365365+#define _PAGE_SPECIAL 0x800 /* software: Special page */370366367367+#ifdef CONFIG_PTE_64BIT368368+/* We never clear the high word of the pte */369369+#define _PTE_NONE_MASK (0xffffffff00000000ULL | _PAGE_HASHPTE)370370+#else371371#define _PTE_NONE_MASK _PAGE_HASHPTE372372+#endif372373373374#define _PMD_PRESENT 0374375#define _PMD_PRESENT_MASK (PAGE_MASK)···382371383372/* Hash table based platforms need atomic updates of the linux PTE */384373#define PTE_ATOMIC_UPDATES 1374374+375375+#define __HAVE_ARCH_PTE_SPECIAL385376386377#endif387378···416403#endif417404#ifndef _PAGE_WRITETHRU418405#define _PAGE_WRITETHRU 0406406+#endif407407+#ifndef _PAGE_SPECIAL408408+#define _PAGE_SPECIAL 0419409#endif420410#ifndef _PMD_PRESENT_MASK421411#define _PMD_PRESENT_MASK _PMD_PRESENT···533517534518#define pte_none(pte) ((pte_val(pte) & ~_PTE_NONE_MASK) == 0)535519#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)536536-#define pte_clear(mm,addr,ptep) do { set_pte_at((mm), (addr), (ptep), __pte(0)); } while (0)520520+#define pte_clear(mm, addr, ptep) \521521+ do { pte_update(ptep, ~_PAGE_HASHPTE, 0); } while (0)537522538523#define pmd_none(pmd) (!pmd_val(pmd))539524#define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD)···550533static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }551534static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }552535static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }553553-static inline int pte_special(pte_t pte) { return 0; }536536+static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }554537555538static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }556539static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }···569552static inline pte_t pte_mkyoung(pte_t pte) {570553 pte_val(pte) |= _PAGE_ACCESSED; return pte; }571554static inline pte_t pte_mkspecial(pte_t pte) {572572- return pte; }555555+ pte_val(pte) |= _PAGE_SPECIAL; return pte; }573556static inline unsigned long pte_pgprot(pte_t pte)574557{575558 return __pgprot(pte_val(pte)) & PAGE_PROT_BITS;···591574/* Add an HPTE to the hash table */592575extern void add_hash_page(unsigned context, unsigned long va,593576 unsigned long pmdval);577577+578578+/* Flush an entry from the TLB/hash table */579579+extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep,580580+ unsigned long address);594581595582/*596583 * Atomic PTE updates.···633612 return old;634613}635614#else /* CONFIG_PTE_64BIT */636636-/* TODO: Change that to only modify the low word and move set_pte_at()637637- * out of line638638- */639615static inline unsigned long long pte_update(pte_t *p,640616 unsigned long clr,641617 unsigned long set)···670652 * On machines which use an MMU hash table we avoid changing the671653 * _PAGE_HASHPTE bit.672654 */655655+656656+static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,657657+ pte_t *ptep, pte_t pte)658658+{659659+#if (_PAGE_HASHPTE != 0) && defined(CONFIG_SMP) && !defined(CONFIG_PTE_64BIT)660660+ pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE);661661+#elif defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP)662662+#if _PAGE_HASHPTE != 0663663+ if (pte_val(*ptep) & _PAGE_HASHPTE)664664+ flush_hash_entry(mm, ptep, addr);665665+#endif666666+ __asm__ __volatile__("\667667+ stw%U0%X0 %2,%0\n\668668+ eieio\n\669669+ stw%U0%X0 %L2,%1"670670+ : "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))671671+ : "r" (pte) : "memory");672672+#else673673+ *ptep = (*ptep & _PAGE_HASHPTE) | (pte & ~_PAGE_HASHPTE);674674+#endif675675+}676676+673677static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,674678 pte_t *ptep, pte_t pte)675679{676676-#if _PAGE_HASHPTE != 0677677- pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE);678678-#else679679- *ptep = pte;680680+#if defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP)681681+ WARN_ON(pte_present(*ptep));680682#endif683683+ __set_pte_at(mm, addr, ptep, pte);681684}682685683686/*
+7
arch/powerpc/include/asm/reg_booke.h
···109109#define SPRN_EVPR 0x3D6 /* Exception Vector Prefix Register */110110#define SPRN_L1CSR0 0x3F2 /* L1 Cache Control and Status Register 0 */111111#define SPRN_L1CSR1 0x3F3 /* L1 Cache Control and Status Register 1 */112112+#define SPRN_MMUCSR0 0x3F4 /* MMU Control and Status Register 0 */112113#define SPRN_PIT 0x3DB /* Programmable Interval Timer */113114#define SPRN_BUCSR 0x3F5 /* Branch Unit Control and Status */114115#define SPRN_L2CSR0 0x3F9 /* L2 Data Cache Control and Status Register 0 */···410409#define L2CSR0_L2LFC 0x00000400 /* L2 Cache Lock Flash Clear */411410#define L2CSR0_L2LOA 0x00000080 /* L2 Cache Lock Overflow Allocate */412411#define L2CSR0_L2LO 0x00000020 /* L2 Cache Lock Overflow */412412+413413+/* Bit definitions for MMUCSR0 */414414+#define MMUCSR0_TLB1FI 0x00000002 /* TLB1 Flash invalidate */415415+#define MMUCSR0_TLB0FI 0x00000004 /* TLB0 Flash invalidate */416416+#define MMUCSR0_TLB2FI 0x00000040 /* TLB2 Flash invalidate */417417+#define MMUCSR0_TLB3FI 0x00000020 /* TLB3 Flash invalidate */413418414419/* Bit definitions for SGR. */415420#define SGR_NORMAL 0 /* Speculative fetching allowed. */
+8-5
arch/powerpc/include/asm/tlbflush.h
···2929#include <linux/mm.h>30303131extern void _tlbie(unsigned long address, unsigned int pid);3232+extern void _tlbil_all(void);3333+extern void _tlbil_pid(unsigned int pid);3434+extern void _tlbil_va(unsigned long address, unsigned int pid);32353336#if defined(CONFIG_40x) || defined(CONFIG_8xx)3437#define _tlbia() asm volatile ("tlbia; sync" : : : "memory")···41384239static inline void flush_tlb_mm(struct mm_struct *mm)4340{4444- _tlbia();4141+ _tlbil_pid(mm->context.id);4542}46434744static inline void flush_tlb_page(struct vm_area_struct *vma,4845 unsigned long vmaddr)4946{5050- _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0);4747+ _tlbil_va(vmaddr, vma ? vma->vm_mm->context.id : 0);5148}52495350static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,5451 unsigned long vmaddr)5552{5656- _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0);5353+ flush_tlb_page(vma, vmaddr);5754}58555956static inline void flush_tlb_range(struct vm_area_struct *vma,6057 unsigned long start, unsigned long end)6158{6262- _tlbia();5959+ _tlbil_pid(vma->vm_mm->context.id);6360}64616562static inline void flush_tlb_kernel_range(unsigned long start,6663 unsigned long end)6764{6868- _tlbia();6565+ _tlbil_pid(0);6966}70677168#elif defined(CONFIG_PPC32)
···274274/*275275 * Flush MMU TLB276276 */277277+#ifndef CONFIG_FSL_BOOKE278278+_GLOBAL(_tlbil_all)279279+_GLOBAL(_tlbil_pid)280280+#endif277281_GLOBAL(_tlbia)278282#if defined(CONFIG_40x)279283 sync /* Flush to memory before changing mapping */···348344/*349345 * Flush MMU TLB for a particular address350346 */347347+#ifndef CONFIG_FSL_BOOKE348348+_GLOBAL(_tlbil_va)349349+#endif351350_GLOBAL(_tlbie)352351#if defined(CONFIG_40x)353352 /* We run the search with interrupts disabled because we have to change···442435#endif /* CONFIG_SMP */443436#endif /* ! CONFIG_40x */444437 blr438438+439439+#if defined(CONFIG_FSL_BOOKE)440440+/*441441+ * Flush MMU TLB, but only on the local processor (no broadcast)442442+ */443443+_GLOBAL(_tlbil_all)444444+#define MMUCSR0_TLBFI (MMUCSR0_TLB0FI | MMUCSR0_TLB1FI | \445445+ MMUCSR0_TLB2FI | MMUCSR0_TLB3FI)446446+ li r3,(MMUCSR0_TLBFI)@l447447+ mtspr SPRN_MMUCSR0, r3448448+1:449449+ mfspr r3,SPRN_MMUCSR0450450+ andi. r3,r3,MMUCSR0_TLBFI@l451451+ bne 1b452452+ blr453453+454454+/*455455+ * Flush MMU TLB for a particular process id, but only on the local processor456456+ * (no broadcast)457457+ */458458+_GLOBAL(_tlbil_pid)459459+/* we currently do an invalidate all since we don't have per pid invalidate */460460+ li r3,(MMUCSR0_TLBFI)@l461461+ mtspr SPRN_MMUCSR0, r3462462+1:463463+ mfspr r3,SPRN_MMUCSR0464464+ andi. r3,r3,MMUCSR0_TLBFI@l465465+ bne 1b466466+ blr467467+468468+/*469469+ * Flush MMU TLB for a particular address, but only on the local processor470470+ * (no broadcast)471471+ */472472+_GLOBAL(_tlbil_va)473473+ slwi r4,r4,16474474+ mtspr SPRN_MAS6,r4 /* assume AS=0 for now */475475+ tlbsx 0,r3476476+ mfspr r4,SPRN_MAS1 /* check valid */477477+ andis. r3,r4,MAS1_VALID@h478478+ beqlr479479+ rlwinm r4,r4,0,1,31480480+ mtspr SPRN_MAS1,r4481481+ tlbwe482482+ blr483483+#endif /* CONFIG_FSL_BOOKE */484484+445485446486/*447487 * Flush instruction cache.
···7575 * Returns to the caller if the access is illegal or there is no7676 * mapping for the address. Otherwise it places an appropriate PTE7777 * in the hash table and returns from the exception.7878- * Uses r0, r3 - r8, ctr, lr.7878+ * Uses r0, r3 - r8, r10, ctr, lr.7979 */8080 .text8181_GLOBAL(hash_page)···106106 addi r5,r5,swapper_pg_dir@l /* kernel page table */107107 rlwimi r3,r9,32-12,29,29 /* MSR_PR -> _PAGE_USER */108108112: add r5,r5,r7 /* convert to phys addr */109109+#ifndef CONFIG_PTE_64BIT109110 rlwimi r5,r4,12,20,29 /* insert top 10 bits of address */110111 lwz r8,0(r5) /* get pmd entry */111112 rlwinm. r8,r8,0,0,19 /* extract address of pte page */113113+#else114114+ rlwinm r8,r4,13,19,29 /* Compute pgdir/pmd offset */115115+ lwzx r8,r8,r5 /* Get L1 entry */116116+ rlwinm. r8,r8,0,0,20 /* extract pt base address */117117+#endif112118#ifdef CONFIG_SMP113119 beq- hash_page_out /* return if no mapping */114120#else···124118 to the address following the rfi. */125119 beqlr-126120#endif121121+#ifndef CONFIG_PTE_64BIT127122 rlwimi r8,r4,22,20,29 /* insert next 10 bits of address */123123+#else124124+ rlwimi r8,r4,23,20,28 /* compute pte address */125125+#endif128126 rlwinm r0,r3,32-3,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */129127 ori r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE130128···137127 * because almost always, there won't be a permission violation138128 * and there won't already be an HPTE, and thus we will have139129 * to update the PTE to set _PAGE_HASHPTE. -- paulus.130130+ *131131+ * If PTE_64BIT is set, the low word is the flags word; use that132132+ * word for locking since it contains all the interesting bits.140133 */134134+#if (PTE_FLAGS_OFFSET != 0)135135+ addi r8,r8,PTE_FLAGS_OFFSET136136+#endif141137retry:142142- lwarx r6,0,r8 /* get linux-style pte */138138+ lwarx r6,0,r8 /* get linux-style pte, flag word */143139 andc. r5,r3,r6 /* check access & ~permission */144140#ifdef CONFIG_SMP145141 bne- hash_page_out /* return if access not permitted */···153137 bnelr-154138#endif155139 or r5,r0,r6 /* set accessed/dirty bits */140140+#ifdef CONFIG_PTE_64BIT141141+#ifdef CONFIG_SMP142142+ subf r10,r6,r8 /* create false data dependency */143143+ subi r10,r10,PTE_FLAGS_OFFSET144144+ lwzx r10,r6,r10 /* Get upper PTE word */145145+#else146146+ lwz r10,-PTE_FLAGS_OFFSET(r8)147147+#endif /* CONFIG_SMP */148148+#endif /* CONFIG_PTE_64BIT */156149 stwcx. r5,0,r8 /* attempt to update PTE */157150 bne- retry /* retry if someone got there first */158151···228203 * we can't take a hash table miss (assuming the code is229204 * covered by a BAT). -- paulus230205 */231231- mfmsr r10206206+ mfmsr r9232207 SYNC233233- rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */208208+ rlwinm r0,r9,0,17,15 /* clear bit 16 (MSR_EE) */234209 rlwinm r0,r0,0,28,26 /* clear MSR_DR */235210 mtmsr r0236211 SYNC_601···239214 tophys(r7,0)240215241216#ifdef CONFIG_SMP242242- addis r9,r7,mmu_hash_lock@ha243243- addi r9,r9,mmu_hash_lock@l244244-10: lwarx r0,0,r9 /* take the mmu_hash_lock */217217+ addis r6,r7,mmu_hash_lock@ha218218+ addi r6,r6,mmu_hash_lock@l219219+10: lwarx r0,0,r6 /* take the mmu_hash_lock */245220 cmpi 0,r0,0246221 bne- 11f247247- stwcx. r8,0,r9222222+ stwcx. r8,0,r6248223 beq+ 12f249249-11: lwz r0,0(r9)224224+11: lwz r0,0(r6)250225 cmpi 0,r0,0251226 beq 10b252227 b 11b···259234 * HPTE, so we just unlock and return.260235 */261236 mr r8,r5237237+#ifndef CONFIG_PTE_64BIT262238 rlwimi r8,r4,22,20,29239239+#else240240+ rlwimi r8,r4,23,20,28241241+ addi r8,r8,PTE_FLAGS_OFFSET242242+#endif2632431: lwarx r6,0,r8264244 andi. r0,r6,_PAGE_HASHPTE265245 bne 9f /* if HASHPTE already set, done */246246+#ifdef CONFIG_PTE_64BIT247247+#ifdef CONFIG_SMP248248+ subf r10,r6,r8 /* create false data dependency */249249+ subi r10,r10,PTE_FLAGS_OFFSET250250+ lwzx r10,r6,r10 /* Get upper PTE word */251251+#else252252+ lwz r10,-PTE_FLAGS_OFFSET(r8)253253+#endif /* CONFIG_SMP */254254+#endif /* CONFIG_PTE_64BIT */266255 ori r5,r6,_PAGE_HASHPTE267256 stwcx. r5,0,r8268257 bne- 1b···2852462862479:287248#ifdef CONFIG_SMP249249+ addis r6,r7,mmu_hash_lock@ha250250+ addi r6,r6,mmu_hash_lock@l288251 eieio289252 li r0,0290290- stw r0,0(r9) /* clear mmu_hash_lock */253253+ stw r0,0(r6) /* clear mmu_hash_lock */291254#endif292255293256 /* reenable interrupts and DR */294294- mtmsr r10257257+ mtmsr r9295258 SYNC_601296259 isync297260···308267 * r5 contains the linux PTE, r6 contains the old value of the309268 * linux PTE (before setting _PAGE_HASHPTE) and r7 contains the310269 * offset to be added to addresses (0 if the MMU is on,311311- * -KERNELBASE if it is off).270270+ * -KERNELBASE if it is off). r10 contains the upper half of271271+ * the PTE if CONFIG_PTE_64BIT.312272 * On SMP, the caller should have the mmu_hash_lock held.313273 * We assume that the caller has (or will) set the _PAGE_HASHPTE314274 * bit in the linux PTE in memory. The value passed in r6 should···355313BEGIN_FTR_SECTION356314 ori r8,r8,_PAGE_COHERENT /* set M (coherence required) */357315END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT)316316+#ifdef CONFIG_PTE_64BIT317317+ /* Put the XPN bits into the PTE */318318+ rlwimi r8,r10,8,20,22319319+ rlwimi r8,r10,2,29,29320320+#endif358321359322 /* Construct the high word of the PPC-style PTE (r5) */360323 rlwinm r5,r3,7,1,24 /* put VSID in 0x7fffff80 bits */···546499 isync547500548501 /* First find a PTE in the range that has _PAGE_HASHPTE set */502502+#ifndef CONFIG_PTE_64BIT549503 rlwimi r5,r4,22,20,29550550-1: lwz r0,0(r5)504504+#else505505+ rlwimi r5,r4,23,20,28506506+#endif507507+1: lwz r0,PTE_FLAGS_OFFSET(r5)551508 cmpwi cr1,r6,1552509 andi. r0,r0,_PAGE_HASHPTE553510 bne 2f554511 ble cr1,19f555512 addi r4,r4,0x1000556556- addi r5,r5,4513513+ addi r5,r5,PTE_SIZE557514 addi r6,r6,-1558515 b 1b559516···596545 * already clear, we're done (for this pte). If not,597546 * clear it (atomically) and proceed. -- paulus.598547 */599599-33: lwarx r8,0,r5 /* fetch the pte */548548+#if (PTE_FLAGS_OFFSET != 0)549549+ addi r5,r5,PTE_FLAGS_OFFSET550550+#endif551551+33: lwarx r8,0,r5 /* fetch the pte flags word */600552 andi. r0,r8,_PAGE_HASHPTE601553 beq 8f /* done if HASHPTE is already clear */602554 rlwinm r8,r8,0,31,29 /* clear HASHPTE bit */···6445906455918: ble cr1,9f /* if all ptes checked */64659281: addi r6,r6,-1647647- addi r5,r5,4 /* advance to next pte */593593+ addi r5,r5,PTE_SIZE648594 addi r4,r4,0x1000649595 lwz r0,0(r5) /* check next pte */650596 cmpwi cr1,r6,1
+2-2
arch/powerpc/mm/pgtable_32.c
···7373#endif /* HAVE_TLBCAM */74747575#ifdef CONFIG_PTE_64BIT7676-/* 44x uses an 8kB pgdir because it has 8-byte Linux PTEs. */7676+/* Some processors use an 8kB pgdir because they have 8-byte Linux PTEs. */7777#define PGDIR_ORDER 17878#else7979#define PGDIR_ORDER 0···288288}289289290290/*291291- * Map in all of physical memory starting at KERNELBASE.291291+ * Map in a big chunk of physical memory starting at KERNELBASE.292292 */293293void __init mapin_ram(void)294294{
+1
arch/powerpc/mm/tlb_32.c
···4545 flush_hash_pages(mm->context.id, addr, ptephys, 1);4646 }4747}4848+EXPORT_SYMBOL(flush_hash_entry);48494950/*5051 * Called by ptep_set_access_flags, must flush on CPUs for which the
+10-7
arch/powerpc/platforms/Kconfig.cputype
···5050 select PPC_UDBG_165505151 select 4xx_SOC5252 select PPC_PCI_CHOICE5353+ select PHYS_64BIT53545455config E2005556 bool "Freescale e200"···129128130129config PTE_64BIT131130 bool132132- depends on 44x || E500133133- default y if 44x134134- default y if E500 && PHYS_64BIT131131+ depends on 44x || E500 || PPC_86xx132132+ default y if PHYS_64BIT135133136134config PHYS_64BIT137137- bool 'Large physical address support' if E500138138- depends on 44x || E500135135+ bool 'Large physical address support' if E500 || PPC_86xx136136+ depends on (44x || E500 || PPC_86xx) && !PPC_83xx && !PPC_82xx139137 select RESOURCES_64BIT140140- default y if 44x141138 ---help---142139 This option enables kernel support for larger than 32-bit physical143143- addresses. This features is not be available on all e500 cores.140140+ addresses. This feature may not be available on all cores.141141+142142+ If you have more than 3.5GB of RAM or so, you also need to enable143143+ SWIOTLB under Kernel Options for this to work. The actual number144144+ is platform-dependent.144145145146 If in doubt, say N here.146147