* [RFC 4/6] LVHPT - find architectured page size help
From: Ian Wienand @ 2006-05-10 3:42 UTC (permalink / raw)
To: linux-ia64; +Cc: linux-mm, Ian Wienand
In-Reply-To: <20060510034206.17792.82504.sendpatchset@wagner.orchestra.cse.unsw.EDU.AU>
Find biggest page
Split out a handy function for finding the largest page the
architecture can map over a region.
Signed-Off-By: Ian Wienand <ianw@gelato.unsw.edu.au>
---
arch/ia64/mm/tlb.c | 43 +++++++++++++++++++++++--------------------
include/asm-ia64/tlb.h | 25 +++++++++++++++++++++++++
2 files changed, 48 insertions(+), 20 deletions(-)
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/mm/tlb.c
===================================================================
--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/arch/ia64/mm/tlb.c 2006-05-03 17:11:43.000000000 +1000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/mm/tlb.c 2006-05-10 09:13:08.000000000 +1000
@@ -26,11 +26,10 @@
#include <asm/pal.h>
#include <asm/tlbflush.h>
#include <asm/dma.h>
+#include <asm/pgtable.h>
+#include <asm/tlb.h>
-static struct {
- unsigned long mask; /* mask of supported purge page-sizes */
- unsigned long max_bits; /* log2 of largest supported purge page-size */
-} purge;
+struct ia64_page_sizes_t ia64_page_sizes;
struct ia64_ctx ia64_ctx = {
.lock = SPIN_LOCK_UNLOCKED,
@@ -138,7 +137,6 @@
unsigned long end)
{
struct mm_struct *mm = vma->vm_mm;
- unsigned long size = end - start;
unsigned long nbits;
#ifndef CONFIG_SMP
@@ -148,12 +146,7 @@
}
#endif
- nbits = ia64_fls(size + 0xfff);
- while (unlikely (((1UL << nbits) & purge.mask) == 0) &&
- (nbits < purge.max_bits))
- ++nbits;
- if (nbits > purge.max_bits)
- nbits = purge.max_bits;
+ nbits = find_largest_page_size(end-start);
start &= ~((1UL << nbits) - 1);
preempt_disable();
@@ -173,19 +166,29 @@
}
EXPORT_SYMBOL(flush_tlb_range);
+/*
+ * We need this data early in the boot, so it gets called from
+ * setup_arch()
+ */
+void __devinit
+ia64_tlb_early_init (void)
+{
+ long status;
+ unsigned long tr_pgbits;
+
+ /* Setup valid page sizes for find_largest_page() */
+ if ((status = ia64_pal_vm_page_size(&tr_pgbits, &ia64_page_sizes.mask)) != 0) {
+ printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld;"
+ "defaulting to architected purge page-sizes.\n", status);
+ ia64_page_sizes.mask = 0x115557000UL;
+ }
+ ia64_page_sizes.max_bits = ia64_fls(ia64_page_sizes.mask);
+}
+
void __devinit
ia64_tlb_init (void)
{
ia64_ptce_info_t ptce_info;
- unsigned long tr_pgbits;
- long status;
-
- if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) {
- printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld;"
- "defaulting to architected purge page-sizes.\n", status);
- purge.mask = 0x115557000UL;
- }
- purge.max_bits = ia64_fls(purge.mask);
ia64_get_ptce(&ptce_info);
local_cpu_data->ptce_base = ptce_info.base;
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/include/asm-ia64/tlb.h
===================================================================
--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/include/asm-ia64/tlb.h 2006-05-03 17:11:43.000000000 +1000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/include/asm-ia64/tlb.h 2006-05-10 09:04:39.000000000 +1000
@@ -200,6 +200,31 @@
tlb->end_addr = address + PAGE_SIZE;
}
+/*
+ * Find an architecture suitable page size based big enough to map
+ * input size. Return the number of bits; i.e. (1 << nbits) is the
+ * page size in bytes.
+ */
+struct ia64_page_sizes_t {
+ unsigned long mask; /* mask of supported page-sizes */
+ unsigned long max_bits; /* log2 of largest supported page-size */
+};
+
+ /* initalised in ia64_tlb_init() from EFI */
+extern struct ia64_page_sizes_t ia64_page_sizes;
+
+static inline unsigned long
+find_largest_page_size(unsigned long size)
+{
+ int nbits = ia64_fls(size + 0xfff);
+ while (unlikely (((1UL << nbits) & ia64_page_sizes.mask) == 0) &&
+ (nbits < ia64_page_sizes.max_bits))
+ ++nbits;
+ if (nbits > ia64_page_sizes.max_bits)
+ nbits = ia64_page_sizes.max_bits;
+ return nbits;
+}
+
#define tlb_migrate_finish(mm) platform_tlb_migrate_finish(mm)
#define tlb_start_vma(tlb, vma) do { } while (0)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [RFC 4/6] LVHPT - find architectured page size help
From: Ian Wienand @ 2006-05-10 3:42 UTC (permalink / raw)
To: linux-ia64; +Cc: linux-mm, Ian Wienand
In-Reply-To: <20060510034206.17792.82504.sendpatchset@wagner.orchestra.cse.unsw.EDU.AU>
Find biggest page
Split out a handy function for finding the largest page the
architecture can map over a region.
Signed-Off-By: Ian Wienand <ianw@gelato.unsw.edu.au>
---
arch/ia64/mm/tlb.c | 43 +++++++++++++++++++++++--------------------
include/asm-ia64/tlb.h | 25 +++++++++++++++++++++++++
2 files changed, 48 insertions(+), 20 deletions(-)
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/mm/tlb.c
=================================--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/arch/ia64/mm/tlb.c 2006-05-03 17:11:43.000000000 +1000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/mm/tlb.c 2006-05-10 09:13:08.000000000 +1000
@@ -26,11 +26,10 @@
#include <asm/pal.h>
#include <asm/tlbflush.h>
#include <asm/dma.h>
+#include <asm/pgtable.h>
+#include <asm/tlb.h>
-static struct {
- unsigned long mask; /* mask of supported purge page-sizes */
- unsigned long max_bits; /* log2 of largest supported purge page-size */
-} purge;
+struct ia64_page_sizes_t ia64_page_sizes;
struct ia64_ctx ia64_ctx = {
.lock = SPIN_LOCK_UNLOCKED,
@@ -138,7 +137,6 @@
unsigned long end)
{
struct mm_struct *mm = vma->vm_mm;
- unsigned long size = end - start;
unsigned long nbits;
#ifndef CONFIG_SMP
@@ -148,12 +146,7 @@
}
#endif
- nbits = ia64_fls(size + 0xfff);
- while (unlikely (((1UL << nbits) & purge.mask) = 0) &&
- (nbits < purge.max_bits))
- ++nbits;
- if (nbits > purge.max_bits)
- nbits = purge.max_bits;
+ nbits = find_largest_page_size(end-start);
start &= ~((1UL << nbits) - 1);
preempt_disable();
@@ -173,19 +166,29 @@
}
EXPORT_SYMBOL(flush_tlb_range);
+/*
+ * We need this data early in the boot, so it gets called from
+ * setup_arch()
+ */
+void __devinit
+ia64_tlb_early_init (void)
+{
+ long status;
+ unsigned long tr_pgbits;
+
+ /* Setup valid page sizes for find_largest_page() */
+ if ((status = ia64_pal_vm_page_size(&tr_pgbits, &ia64_page_sizes.mask)) != 0) {
+ printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld;"
+ "defaulting to architected purge page-sizes.\n", status);
+ ia64_page_sizes.mask = 0x115557000UL;
+ }
+ ia64_page_sizes.max_bits = ia64_fls(ia64_page_sizes.mask);
+}
+
void __devinit
ia64_tlb_init (void)
{
ia64_ptce_info_t ptce_info;
- unsigned long tr_pgbits;
- long status;
-
- if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) {
- printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld;"
- "defaulting to architected purge page-sizes.\n", status);
- purge.mask = 0x115557000UL;
- }
- purge.max_bits = ia64_fls(purge.mask);
ia64_get_ptce(&ptce_info);
local_cpu_data->ptce_base = ptce_info.base;
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/include/asm-ia64/tlb.h
=================================--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/include/asm-ia64/tlb.h 2006-05-03 17:11:43.000000000 +1000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/include/asm-ia64/tlb.h 2006-05-10 09:04:39.000000000 +1000
@@ -200,6 +200,31 @@
tlb->end_addr = address + PAGE_SIZE;
}
+/*
+ * Find an architecture suitable page size based big enough to map
+ * input size. Return the number of bits; i.e. (1 << nbits) is the
+ * page size in bytes.
+ */
+struct ia64_page_sizes_t {
+ unsigned long mask; /* mask of supported page-sizes */
+ unsigned long max_bits; /* log2 of largest supported page-size */
+};
+
+ /* initalised in ia64_tlb_init() from EFI */
+extern struct ia64_page_sizes_t ia64_page_sizes;
+
+static inline unsigned long
+find_largest_page_size(unsigned long size)
+{
+ int nbits = ia64_fls(size + 0xfff);
+ while (unlikely (((1UL << nbits) & ia64_page_sizes.mask) = 0) &&
+ (nbits < ia64_page_sizes.max_bits))
+ ++nbits;
+ if (nbits > ia64_page_sizes.max_bits)
+ nbits = ia64_page_sizes.max_bits;
+ return nbits;
+}
+
#define tlb_migrate_finish(mm) platform_tlb_migrate_finish(mm)
#define tlb_start_vma(tlb, vma) do { } while (0)
^ permalink raw reply
* [RFC 3/6] LVHPT - ivt.S long format support
From: Ian Wienand @ 2006-05-10 3:42 UTC (permalink / raw)
To: linux-ia64; +Cc: linux-mm, Ian Wienand
In-Reply-To: <20060510034206.17792.82504.sendpatchset@wagner.orchestra.cse.unsw.EDU.AU>
LVHPT ivt long format support
Add templates for long format VHPT support, to be merged into ivt.S
Signed-Off-By: Ian Wienand <ianw@gelato.unsw.edu.au>
---
Kconfig | 10 +
kernel/Makefile | 9
kernel/ivt-lfvhpt.in | 466 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 484 insertions(+), 1 deletion(-)
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/Makefile
===================================================================
--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/arch/ia64/kernel/Makefile 2006-05-05 10:09:38.000000000 +1000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/Makefile 2006-05-05 10:12:36.000000000 +1000
@@ -62,5 +62,12 @@
# The real ivt.S needs to be built
AFLAGS_ivt.o += -I$(srctree)/arch/ia64/kernel
-$(obj)/ivt.S: $(src)/ivt.S.in $(src)/ivt-sfvhpt.in
+
+ifeq ($(CONFIG_IA64_LONG_FORMAT_VHPT),)
+fault_handler_in = ivt-sfvhpt.in
+else
+fault_handler_in = ivt-lfvhpt.in
+endif
+
+$(obj)/ivt.S: $(src)/ivt.S.in $(src)/$(fault_handler_in)
$(srctree)/arch/ia64/scripts/merge.py $@ $^
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt-lfvhpt.in
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt-lfvhpt.in 2006-05-05 10:12:36.000000000 +1000
@@ -0,0 +1,466 @@
+/*
+ * Long Format VHPT fault handlers
+ *
+ * Copyright (C) 2006; see ivt.S for original authors
+ * These bits by
+ * Matthew Chapman <matthewc@cse.unsw.edu.au>
+ * Darren Williams <darren.williams@nicta.com.au>
+ * Ian Wienand <ianw@gelato.unsw.edu.au>
+ *
+ * This file is to be processed and inserted into the actual ivt.S
+ *
+ * Any variable $name in ivt.S will be replaced with what is between
+ *__begin_name__ and __end_name__ in this file.
+ *
+ */
+
+//vhpt_miss
+__begin_vhpt_miss_handler__
+// This fault can not happen with long format VHPT
+ FAULT(0)
+__end_vhpt_miss_handler__
+
+// itlb_miss
+__begin_itlb_miss_handler__
+ mov r16=cr.ifa // get virtual address
+ mov r29=b0 // save b0
+ mov r31=pr // save predicates
+ ;;
+.itlb_fault:
+ // walk the page table to satisfy this miss
+ rsm psr.dt // switch to using physical data addressing
+ mov r19=IA64_KR(PT_BASE) // get the page table base address
+ shl r21=r16,3 // shift bit 60 into sign bit
+ mov r18=cr.itir
+ ;;
+ shr.u r17=r16,61 // get the region number into ppte
+ extr.u r18=r18,2,6 // get the faulting page size
+ ;;
+ cmp.eq p6,p7=5,r17 // is faulting address in region 5?
+ add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
+ add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
+ ;;
+ shr.u r22=r16,r22
+ shr.u r18=r16,r18
+(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
+
+ srlz.d
+ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
+
+ .pred.rel "mutex", p6, p7
+(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+ ;;
+(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // ppte=pgd_offset for region 5
+(p7) dep r17=r18,r17,3,(PAGE_SHIFT-3)-3 // ppte=pgd_offset for region[0-4]
+ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+ shr.u r18=r22,PUD_SHIFT // shift pud index into position
+#else
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+#endif
+ ;;
+ ld8 r17=[r17] // get *pgd (may be 0)
+ ;;
+(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // ppte=p[u|m]d_offset(pgd,addr)
+ ;;
+#ifdef CONFIG_PGTABLE_4
+(p7) ld8 r17=[r17] // get *pud (may be 0)
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) == NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // ppte=pmd_offset(pud,addr)
+ ;;
+#endif
+(p7) ld8 r17=[r17] // get *pmd (may be 0)
+ shr.u r19=r22,PAGE_SHIFT // shift pte index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) == NULL?
+ dep r17=r19,r17,3,(PAGE_SHIFT-3) // ppte=pte_offset(pmd,addr)
+ ;;
+(p7) ld8 r18=[r17]
+ ;;
+(p7) tbit.z p6,p0=r18,_PAGE_P_BIT /* page present bit cleared? */
+(p6) br.cond.spnt page_fault
+ // insert vhpt mapping
+ mov r22=cr.iha
+ mov r26=cr.itir
+ ;;
+ tpa r22=r22 /* make hash address physical */
+ ttag r25=r16
+ ;;
+ add r24=16,r22
+ ;;
+ st8 [r22]=r18,8 /* fill out VHPT entry */
+ st8 [r24]=r25,8
+ ;;
+ st8 [r22]=r26,8
+ st8 [r24]=r17
+ //insert actual translation
+ ;;
+ itc.i r18
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r19=[r17] // read *pte again and see if same
+ mov r20=PAGE_SHIFT<<2 // setup page size for purge
+ ;;
+ cmp.ne p7,p0=r18,r19
+ ;;
+(p7) dep r25=-1,r0,63,1 /* set tag-invalid bit */
+ ;;
+(p7) st8 [r22]=r25 /* hpte already points to tag (see above) */
+(p7) ptc.l r16,r20
+#endif
+ mov pr=r31,-1
+ rfi
+__end_itlb_miss_handler__
+
+// dtlb_miss
+__begin_dtlb_miss_handler__
+ mov r16=cr.ifa // get virtual address
+ mov r29=b0 // save b0
+ mov r31=pr // save predicates
+ ;;
+.dtlb_fault:
+ // walk the page table to satisfy this miss
+ rsm psr.dt // switch to using physical data addressing
+ mov r19=IA64_KR(PT_BASE) // get the page table base address
+ shl r21=r16,3 // shift bit 60 into sign bit
+ mov r18=cr.itir
+ ;;
+ shr.u r17=r16,61 // get the region number into ppte
+ extr.u r18=r18,2,6 // get the faulting page size
+ ;;
+ cmp.eq p6,p7=5,r17 // is faulting address in region 5?
+ add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
+ add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
+ ;;
+ shr.u r22=r16,r22
+ shr.u r18=r16,r18
+(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
+
+ srlz.d
+ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
+
+ .pred.rel "mutex", p6, p7
+(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+ ;;
+(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // ppte=pgd_offset for region 5
+(p7) dep r17=r18,r17,3,(PAGE_SHIFT-3)-3 // ppte=pgd_offset for region[0-4]
+ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+ shr.u r18=r22,PUD_SHIFT // shift pud index into position
+#else
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+#endif
+ ;;
+ ld8 r17=[r17] // get *pgd (may be 0)
+ ;;
+(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // ppte=p[u|m]d_offset(pgd,addr)
+ ;;
+#ifdef CONFIG_PGTABLE_4
+(p7) ld8 r17=[r17] // get *pud (may be 0)
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) == NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // ppte=pmd_offset(pud,addr)
+ ;;
+#endif
+(p7) ld8 r17=[r17] // get *pmd (may be 0)
+ shr.u r19=r22,PAGE_SHIFT // shift pte index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) == NULL?
+ dep r17=r19,r17,3,(PAGE_SHIFT-3) // ppte=pte_offset(pmd,addr)
+ ;;
+(p7) ld8 r18=[r17]
+ ;;
+(p7) tbit.z p6,p0=r18,_PAGE_P_BIT /* page present bit cleared? */
+(p6) br.cond.spnt page_fault
+// insert vhpt mapping
+ mov r22=cr.iha
+ mov r26=cr.itir
+ ;;
+ tpa r22=r22 /* make hash address physical */
+ ttag r25=r16
+ ;;
+ add r24=16,r22
+ ;;
+ st8 [r22]=r18,8 /* fill out VHPT entry */
+ st8 [r24]=r25,8
+ ;;
+ st8 [r22]=r26,8
+ st8 [r24]=r17
+//insert actual translation
+ ;;
+ itc.d r18
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r19=[r17] // read *pte again and see if same
+ mov r20=PAGE_SHIFT<<2 // setup page size for purge
+ ;;
+ cmp.ne p7,p0=r18,r19
+ ;;
+(p7) dep r25=-1,r0,63,1 /* set tag-invalid bit */
+ ;;
+(p7) st8 [r22]=r25 /* hpte already points to tag (see above) */
+(p7) ptc.l r16,r20
+#endif
+ mov pr=r31,-1
+ rfi
+__end_dtlb_miss_handler__
+
+// nested_dtlb_miss
+__begin_nested_dtlb_miss_handler__
+// This fault can not happen with long format VHPT
+ FAULT(5)
+__end_nested_dtlb_miss_handler__
+
+// dirty bit
+__begin_dirty_bit_handler__
+ mov r16=cr.ifa // get the address that caused the fault
+ mov r29=b0 // save b0 for nested fault (XXX)
+ mov r31=pr // save pr
+ /*
+ * we try to find the address via the VHPT, if not fall back to
+ * dtlb_fault.
+ */
+ ;;
+ thash r28=r16
+ rsm psr.dt
+ ;;
+ tpa r22=r28 // make hash address physical
+ ttag r25=r16
+ ;;
+ srlz.d
+ add r24=16,r22
+ add r17=24,r22
+ ;;
+ ld8 r26=[r24] // load tag
+ ld8 r17=[r17]
+ ;;
+ cmp.ne p6,p7=r26, r25 // verify tag
+ ;;
+(p7) ld8 r18=[r17]
+ ;;
+(p6) mov cr.iha=r28 // set cr.iha only if we are going to take
+(p6) br.cond.spnt .dtlb_fault // the failfn fault - it depends on it.
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only update if page is present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present
+ ;;
+(p6) st8 [r22]=r18,16 // update VHPT
+(p6) itc.d r25 // install updated PTE
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) dep r25=-1,r0,63,1 // set tag-invalid bit
+ ;;
+(p7) st8 [r22]=r25 // hpte already points to tag (see above)
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else
+ ;;
+ or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+(p0) st8 [r22]=r18,16 // update VHPT (p0 set from dtlb_fault)
+ itc.d r18 // install updated PTE
+#endif
+ mov pr=r31,-1 // restore pr
+ rfi
+__end_dirty_bit_handler__
+
+// iaccess bit
+__begin_iaccess_bit_handler__
+ // Like dirty bit handler, except for instruction access
+ mov r16=cr.ifa // get the address that caused the fault
+ mov r29=b0
+ mov r31=pr // save predicates
+ ;;
+ /*
+ * we try to find the address via the VHPT, if not fall back to
+ * dtlb_fault.
+ */
+ thash r28=r16
+ rsm psr.dt
+ ;;
+ tpa r22=r28 // make hash address physical
+ ttag r25=r16
+ ;;
+ srlz.d
+ add r24=16,r22
+ add r17=24,r22
+ ;;
+ ld8 r26=[r24] // load tag
+ ld8 r17=[r17]
+ ;;
+ cmp.ne p6,p7=r26, r25 // verify tag
+ ;;
+(p7) ld8 r18=[r17]
+ ;;
+(p6) mov cr.iha=r28 // set cr.iha only if we are going to take
+(p6) br.cond.spnt .itlb_fault // the failfn fault - it depends on it.
+#ifdef CONFIG_ITANIUM
+ /*
+ * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
+ */
+ mov r17=cr.ipsr
+ ;;
+ mov r18=cr.iip
+ tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set?
+ ;;
+(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa
+#endif /* CONFIG_ITANIUM */
+ ;;
+ mov b0=r29 // restore b0
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_A,r18 // set the accessed bit
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only if page present
+ ;;
+(p6) st8 [r22]=r18,16 // update VHPT
+(p6) itc.i r25 // install updated PTE
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) dep r25=-1,r0,63,1 // set tag-invalid bit
+ ;;
+(p7) st8 [r22]=r25 // hpte already points to tag (see above)
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else /* !CONFIG_SMP */
+ ;;
+ or r18=_PAGE_A,r18 // set the accessed bit
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+(p0) st8 [r22]=r18,16 // update VHPT (p0 from itlb_miss)
+ itc.i r18 // install updated PTE
+#endif /* !CONFIG_SMP */
+ mov pr=r31,-1
+ rfi
+__end_iaccess_bit_handler__
+
+// daccess bit
+__begin_daccess_bit_handler__
+ // Like dirty bit handler, except for data access
+ mov r16=cr.ifa // get the address that caused the fault
+ mov r29=b0
+ mov r31=pr // save predicates
+ ;;
+ /*
+ * we try to find the address via the VHPT, if not fall back to
+ * dtlb_fault.
+ */
+ ;;
+ thash r28=r16
+ rsm psr.dt
+ ;;
+ tpa r22=r28 // make hash address physical
+ ttag r25=r16
+ ;;
+ srlz.d
+ add r24=16,r22
+ add r17=24,r22
+ ;;
+ ld8 r26=[r24] // load tag
+ ld8 r17=[r17]
+ ;;
+ cmp.ne p6,p7=r26, r25 // verify tag
+ ;;
+(p7) ld8 r18=[r17]
+ ;;
+(p6) mov cr.iha=r28 // set cr.iha only if we are going to take
+(p6) br.cond.spnt .dtlb_fault // the failfn fault - it depends on it.
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_A,r18 // set the accessed bit
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only if page present
+ ;;
+(p6) st8 [r22]=r18,16 // update VHPT
+(p6) itc.d r25 // install updated PTE
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) dep r25=-1,r0,63,1 // set tag-invalid bit
+ ;;
+(p7) st8 [r22]=r25 // hpte already points to tag (see above)
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else /* !CONFIG_SMP */
+ ;;
+ or r18=_PAGE_A,r18 // set the accessed bit
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+(p0) st8 [r22]=r18,16 // update VHPT (p0 from itlb_miss)
+ itc.i r18 // install updated PTE
+#endif /* !CONFIG_SMP */
+ mov pr=r31,-1
+ rfi
+__end_daccess_bit_handler__
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/Kconfig
===================================================================
--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/arch/ia64/Kconfig 2006-05-05 10:02:39.000000000 +1000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/Kconfig 2006-05-05 10:12:36.000000000 +1000
@@ -374,6 +374,16 @@
def_bool y
depends on NEED_MULTIPLE_NODES
+config IA64_LONG_FORMAT_VHPT
+ bool "Long format VHPT"
+ depends on !DISABLE_VHPT
+ help
+ The long format VHPT is an alternative hashed page table.
+ It is more TLB friendly, but less cache friendly. By its
+ self this may have a negative, neutral, or positive impact
+ on performance, depending on your workloads. If you're
+ unsure, answer N and keep the default short-format VHPT.
+
config IA32_SUPPORT
bool "Support for Linux/x86 binaries"
help
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [RFC 3/6] LVHPT - ivt.S long format support
From: Ian Wienand @ 2006-05-10 3:42 UTC (permalink / raw)
To: linux-ia64; +Cc: linux-mm, Ian Wienand
In-Reply-To: <20060510034206.17792.82504.sendpatchset@wagner.orchestra.cse.unsw.EDU.AU>
LVHPT ivt long format support
Add templates for long format VHPT support, to be merged into ivt.S
Signed-Off-By: Ian Wienand <ianw@gelato.unsw.edu.au>
---
Kconfig | 10 +
kernel/Makefile | 9
kernel/ivt-lfvhpt.in | 466 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 484 insertions(+), 1 deletion(-)
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/Makefile
=================================--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/arch/ia64/kernel/Makefile 2006-05-05 10:09:38.000000000 +1000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/Makefile 2006-05-05 10:12:36.000000000 +1000
@@ -62,5 +62,12 @@
# The real ivt.S needs to be built
AFLAGS_ivt.o += -I$(srctree)/arch/ia64/kernel
-$(obj)/ivt.S: $(src)/ivt.S.in $(src)/ivt-sfvhpt.in
+
+ifeq ($(CONFIG_IA64_LONG_FORMAT_VHPT),)
+fault_handler_in = ivt-sfvhpt.in
+else
+fault_handler_in = ivt-lfvhpt.in
+endif
+
+$(obj)/ivt.S: $(src)/ivt.S.in $(src)/$(fault_handler_in)
$(srctree)/arch/ia64/scripts/merge.py $@ $^
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt-lfvhpt.in
=================================--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt-lfvhpt.in 2006-05-05 10:12:36.000000000 +1000
@@ -0,0 +1,466 @@
+/*
+ * Long Format VHPT fault handlers
+ *
+ * Copyright (C) 2006; see ivt.S for original authors
+ * These bits by
+ * Matthew Chapman <matthewc@cse.unsw.edu.au>
+ * Darren Williams <darren.williams@nicta.com.au>
+ * Ian Wienand <ianw@gelato.unsw.edu.au>
+ *
+ * This file is to be processed and inserted into the actual ivt.S
+ *
+ * Any variable $name in ivt.S will be replaced with what is between
+ *__begin_name__ and __end_name__ in this file.
+ *
+ */
+
+//vhpt_miss
+__begin_vhpt_miss_handler__
+// This fault can not happen with long format VHPT
+ FAULT(0)
+__end_vhpt_miss_handler__
+
+// itlb_miss
+__begin_itlb_miss_handler__
+ mov r16=cr.ifa // get virtual address
+ mov r29° // save b0
+ mov r31=pr // save predicates
+ ;;
+.itlb_fault:
+ // walk the page table to satisfy this miss
+ rsm psr.dt // switch to using physical data addressing
+ mov r19=IA64_KR(PT_BASE) // get the page table base address
+ shl r21=r16,3 // shift bit 60 into sign bit
+ mov r18=cr.itir
+ ;;
+ shr.u r17=r16,61 // get the region number into ppte
+ extr.u r18=r18,2,6 // get the faulting page size
+ ;;
+ cmp.eq p6,p7=5,r17 // is faulting address in region 5?
+ add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
+ add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
+ ;;
+ shr.u r22=r16,r22
+ shr.u r18=r16,r18
+(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
+
+ srlz.d
+ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
+
+ .pred.rel "mutex", p6, p7
+(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+ ;;
+(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // ppte=pgd_offset for region 5
+(p7) dep r17=r18,r17,3,(PAGE_SHIFT-3)-3 // ppte=pgd_offset for region[0-4]
+ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+ shr.u r18=r22,PUD_SHIFT // shift pud index into position
+#else
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+#endif
+ ;;
+ ld8 r17=[r17] // get *pgd (may be 0)
+ ;;
+(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) = NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // ppte=p[u|m]d_offset(pgd,addr)
+ ;;
+#ifdef CONFIG_PGTABLE_4
+(p7) ld8 r17=[r17] // get *pud (may be 0)
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) = NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // ppte=pmd_offset(pud,addr)
+ ;;
+#endif
+(p7) ld8 r17=[r17] // get *pmd (may be 0)
+ shr.u r19=r22,PAGE_SHIFT // shift pte index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) = NULL?
+ dep r17=r19,r17,3,(PAGE_SHIFT-3) // ppte=pte_offset(pmd,addr)
+ ;;
+(p7) ld8 r18=[r17]
+ ;;
+(p7) tbit.z p6,p0=r18,_PAGE_P_BIT /* page present bit cleared? */
+(p6) br.cond.spnt page_fault
+ // insert vhpt mapping
+ mov r22=cr.iha
+ mov r26=cr.itir
+ ;;
+ tpa r22=r22 /* make hash address physical */
+ ttag r25=r16
+ ;;
+ add r24\x16,r22
+ ;;
+ st8 [r22]=r18,8 /* fill out VHPT entry */
+ st8 [r24]=r25,8
+ ;;
+ st8 [r22]=r26,8
+ st8 [r24]=r17
+ //insert actual translation
+ ;;
+ itc.i r18
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r19=[r17] // read *pte again and see if same
+ mov r20=PAGE_SHIFT<<2 // setup page size for purge
+ ;;
+ cmp.ne p7,p0=r18,r19
+ ;;
+(p7) dep r25=-1,r0,63,1 /* set tag-invalid bit */
+ ;;
+(p7) st8 [r22]=r25 /* hpte already points to tag (see above) */
+(p7) ptc.l r16,r20
+#endif
+ mov pr=r31,-1
+ rfi
+__end_itlb_miss_handler__
+
+// dtlb_miss
+__begin_dtlb_miss_handler__
+ mov r16=cr.ifa // get virtual address
+ mov r29° // save b0
+ mov r31=pr // save predicates
+ ;;
+.dtlb_fault:
+ // walk the page table to satisfy this miss
+ rsm psr.dt // switch to using physical data addressing
+ mov r19=IA64_KR(PT_BASE) // get the page table base address
+ shl r21=r16,3 // shift bit 60 into sign bit
+ mov r18=cr.itir
+ ;;
+ shr.u r17=r16,61 // get the region number into ppte
+ extr.u r18=r18,2,6 // get the faulting page size
+ ;;
+ cmp.eq p6,p7=5,r17 // is faulting address in region 5?
+ add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
+ add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
+ ;;
+ shr.u r22=r16,r22
+ shr.u r18=r16,r18
+(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
+
+ srlz.d
+ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
+
+ .pred.rel "mutex", p6, p7
+(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+ ;;
+(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // ppte=pgd_offset for region 5
+(p7) dep r17=r18,r17,3,(PAGE_SHIFT-3)-3 // ppte=pgd_offset for region[0-4]
+ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+ shr.u r18=r22,PUD_SHIFT // shift pud index into position
+#else
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+#endif
+ ;;
+ ld8 r17=[r17] // get *pgd (may be 0)
+ ;;
+(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) = NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // ppte=p[u|m]d_offset(pgd,addr)
+ ;;
+#ifdef CONFIG_PGTABLE_4
+(p7) ld8 r17=[r17] // get *pud (may be 0)
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) = NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // ppte=pmd_offset(pud,addr)
+ ;;
+#endif
+(p7) ld8 r17=[r17] // get *pmd (may be 0)
+ shr.u r19=r22,PAGE_SHIFT // shift pte index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) = NULL?
+ dep r17=r19,r17,3,(PAGE_SHIFT-3) // ppte=pte_offset(pmd,addr)
+ ;;
+(p7) ld8 r18=[r17]
+ ;;
+(p7) tbit.z p6,p0=r18,_PAGE_P_BIT /* page present bit cleared? */
+(p6) br.cond.spnt page_fault
+// insert vhpt mapping
+ mov r22=cr.iha
+ mov r26=cr.itir
+ ;;
+ tpa r22=r22 /* make hash address physical */
+ ttag r25=r16
+ ;;
+ add r24\x16,r22
+ ;;
+ st8 [r22]=r18,8 /* fill out VHPT entry */
+ st8 [r24]=r25,8
+ ;;
+ st8 [r22]=r26,8
+ st8 [r24]=r17
+//insert actual translation
+ ;;
+ itc.d r18
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r19=[r17] // read *pte again and see if same
+ mov r20=PAGE_SHIFT<<2 // setup page size for purge
+ ;;
+ cmp.ne p7,p0=r18,r19
+ ;;
+(p7) dep r25=-1,r0,63,1 /* set tag-invalid bit */
+ ;;
+(p7) st8 [r22]=r25 /* hpte already points to tag (see above) */
+(p7) ptc.l r16,r20
+#endif
+ mov pr=r31,-1
+ rfi
+__end_dtlb_miss_handler__
+
+// nested_dtlb_miss
+__begin_nested_dtlb_miss_handler__
+// This fault can not happen with long format VHPT
+ FAULT(5)
+__end_nested_dtlb_miss_handler__
+
+// dirty bit
+__begin_dirty_bit_handler__
+ mov r16=cr.ifa // get the address that caused the fault
+ mov r29° // save b0 for nested fault (XXX)
+ mov r31=pr // save pr
+ /*
+ * we try to find the address via the VHPT, if not fall back to
+ * dtlb_fault.
+ */
+ ;;
+ thash r28=r16
+ rsm psr.dt
+ ;;
+ tpa r22=r28 // make hash address physical
+ ttag r25=r16
+ ;;
+ srlz.d
+ add r24\x16,r22
+ add r17$,r22
+ ;;
+ ld8 r26=[r24] // load tag
+ ld8 r17=[r17]
+ ;;
+ cmp.ne p6,p7=r26, r25 // verify tag
+ ;;
+(p7) ld8 r18=[r17]
+ ;;
+(p6) mov cr.iha=r28 // set cr.iha only if we are going to take
+(p6) br.cond.spnt .dtlb_fault // the failfn fault - it depends on it.
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only update if page is present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present
+ ;;
+(p6) st8 [r22]=r18,16 // update VHPT
+(p6) itc.d r25 // install updated PTE
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) dep r25=-1,r0,63,1 // set tag-invalid bit
+ ;;
+(p7) st8 [r22]=r25 // hpte already points to tag (see above)
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else
+ ;;
+ or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+(p0) st8 [r22]=r18,16 // update VHPT (p0 set from dtlb_fault)
+ itc.d r18 // install updated PTE
+#endif
+ mov pr=r31,-1 // restore pr
+ rfi
+__end_dirty_bit_handler__
+
+// iaccess bit
+__begin_iaccess_bit_handler__
+ // Like dirty bit handler, except for instruction access
+ mov r16=cr.ifa // get the address that caused the fault
+ mov r29°
+ mov r31=pr // save predicates
+ ;;
+ /*
+ * we try to find the address via the VHPT, if not fall back to
+ * dtlb_fault.
+ */
+ thash r28=r16
+ rsm psr.dt
+ ;;
+ tpa r22=r28 // make hash address physical
+ ttag r25=r16
+ ;;
+ srlz.d
+ add r24\x16,r22
+ add r17$,r22
+ ;;
+ ld8 r26=[r24] // load tag
+ ld8 r17=[r17]
+ ;;
+ cmp.ne p6,p7=r26, r25 // verify tag
+ ;;
+(p7) ld8 r18=[r17]
+ ;;
+(p6) mov cr.iha=r28 // set cr.iha only if we are going to take
+(p6) br.cond.spnt .itlb_fault // the failfn fault - it depends on it.
+#ifdef CONFIG_ITANIUM
+ /*
+ * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
+ */
+ mov r17=cr.ipsr
+ ;;
+ mov r18=cr.iip
+ tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set?
+ ;;
+(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa
+#endif /* CONFIG_ITANIUM */
+ ;;
+ mov b0=r29 // restore b0
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_A,r18 // set the accessed bit
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only if page present
+ ;;
+(p6) st8 [r22]=r18,16 // update VHPT
+(p6) itc.i r25 // install updated PTE
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) dep r25=-1,r0,63,1 // set tag-invalid bit
+ ;;
+(p7) st8 [r22]=r25 // hpte already points to tag (see above)
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else /* !CONFIG_SMP */
+ ;;
+ or r18=_PAGE_A,r18 // set the accessed bit
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+(p0) st8 [r22]=r18,16 // update VHPT (p0 from itlb_miss)
+ itc.i r18 // install updated PTE
+#endif /* !CONFIG_SMP */
+ mov pr=r31,-1
+ rfi
+__end_iaccess_bit_handler__
+
+// daccess bit
+__begin_daccess_bit_handler__
+ // Like dirty bit handler, except for data access
+ mov r16=cr.ifa // get the address that caused the fault
+ mov r29°
+ mov r31=pr // save predicates
+ ;;
+ /*
+ * we try to find the address via the VHPT, if not fall back to
+ * dtlb_fault.
+ */
+ ;;
+ thash r28=r16
+ rsm psr.dt
+ ;;
+ tpa r22=r28 // make hash address physical
+ ttag r25=r16
+ ;;
+ srlz.d
+ add r24\x16,r22
+ add r17$,r22
+ ;;
+ ld8 r26=[r24] // load tag
+ ld8 r17=[r17]
+ ;;
+ cmp.ne p6,p7=r26, r25 // verify tag
+ ;;
+(p7) ld8 r18=[r17]
+ ;;
+(p6) mov cr.iha=r28 // set cr.iha only if we are going to take
+(p6) br.cond.spnt .dtlb_fault // the failfn fault - it depends on it.
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_A,r18 // set the accessed bit
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only if page present
+ ;;
+(p6) st8 [r22]=r18,16 // update VHPT
+(p6) itc.d r25 // install updated PTE
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) dep r25=-1,r0,63,1 // set tag-invalid bit
+ ;;
+(p7) st8 [r22]=r25 // hpte already points to tag (see above)
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else /* !CONFIG_SMP */
+ ;;
+ or r18=_PAGE_A,r18 // set the accessed bit
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+(p0) st8 [r22]=r18,16 // update VHPT (p0 from itlb_miss)
+ itc.i r18 // install updated PTE
+#endif /* !CONFIG_SMP */
+ mov pr=r31,-1
+ rfi
+__end_daccess_bit_handler__
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/Kconfig
=================================--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/arch/ia64/Kconfig 2006-05-05 10:02:39.000000000 +1000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/Kconfig 2006-05-05 10:12:36.000000000 +1000
@@ -374,6 +374,16 @@
def_bool y
depends on NEED_MULTIPLE_NODES
+config IA64_LONG_FORMAT_VHPT
+ bool "Long format VHPT"
+ depends on !DISABLE_VHPT
+ help
+ The long format VHPT is an alternative hashed page table.
+ It is more TLB friendly, but less cache friendly. By its
+ self this may have a negative, neutral, or positive impact
+ on performance, depending on your workloads. If you're
+ unsure, answer N and keep the default short-format VHPT.
+
config IA32_SUPPORT
bool "Support for Linux/x86 binaries"
help
^ permalink raw reply
* [RFC 2/6] LVHPT - Create ivt.S dyanamically
From: Ian Wienand @ 2006-05-10 3:42 UTC (permalink / raw)
To: linux-ia64; +Cc: linux-mm, Ian Wienand
In-Reply-To: <20060510034206.17792.82504.sendpatchset@wagner.orchestra.cse.unsw.EDU.AU>
LVHPT ivt break apart
Create a script to dynamically create ivt.S. Pull out code from ivt.S
into a template file. The template(s) are then inserted back into
ivt.S at build time.
This approach avoids
- replicating the entire file
- #including a multitude of smaller files
- using CPP defines (which makes editing assembly hard)
- using assembler macros, which can be confusing as you do not get
context
Signed-Off-By: Ian Wienand <ianw@gelato.unsw.edu.au>
---
kernel/Makefile | 5
kernel/ivt-sfvhpt.in | 444 +++++++++++++++++
kernel/ivt.S.in | 1324 +++++++++++++++++++++++++++++++++++++++++++++++++++
scripts/merge.py | 58 ++
4 files changed, 1831 insertions(+)
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/scripts/merge.py
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/scripts/merge.py 2006-05-05 10:09:38.000000000 +1000
@@ -0,0 +1,58 @@
+#!/usr/bin/env python2.4
+# nb. requires python2.4 for string templating
+#
+# Usage: merge.py output template code
+#
+# merge the code in 'code' into 'template', writing out to 'output'
+#
+# Anything between lines __begin_name__ and __end_name__ in 'code'
+# gets inserted into $name in 'template'.
+#
+# Ian Wienand <ianw@gelato.unsw.edu.au>
+#
+import os
+import sys
+from string import Template
+
+if len(sys.argv) != 4:
+ print "Usage: %s output template code" % sys.argv[0]
+ sys.exit(2)
+
+print "Merging %s and template %s to %s" % (sys.argv[2], sys.argv[3], sys.argv[1])
+
+# bring the code file into a dictionary
+# anything between lines __begin_name__ and __end_name__ goes into
+# a dictionary entry of name
+template_dictionary = {}
+am_processing = False
+current_template = ""
+current_template_name = ""
+for line in open(sys.argv[3], 'r').readlines():
+
+ if am_processing:
+ # if this line is the end, stop
+ # XXX check this end is actually the name we are processing
+ if line[:6] == "__end_":
+ template_dictionary[current_template_name] = current_template
+ am_processing = False
+ print "... done"
+ continue
+ # otherwise, add this line to the current template
+ current_template += line
+ continue
+ # if we got here, we are not processing
+ if line[:8] == "__begin_":
+ am_processing = True
+ current_template_name = line[8:-3] #newline
+ print "Processing %s" % (current_template_name),
+ current_template = ""
+ continue
+ # this is some random line
+ continue
+
+#now open the file where we put these templates
+template = Template(open(sys.argv[2],'r').read())
+
+#finally, substitute them all in
+output = open(sys.argv[1],'w')
+output.write(template.substitute(template_dictionary))
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt.S.in
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt.S.in 2006-05-05 10:09:38.000000000 +1000
@@ -0,0 +1,1324 @@
+/*
+ * arch/ia64/kernel/ivt.S
+ *
+ * Copyright (C) 1998-2001, 2003, 2005 Hewlett-Packard Co
+ * Stephane Eranian <eranian@hpl.hp.com>
+ * David Mosberger <davidm@hpl.hp.com>
+ * Copyright (C) 2000, 2002-2003 Intel Co
+ * Asit Mallick <asit.k.mallick@intel.com>
+ * Suresh Siddha <suresh.b.siddha@intel.com>
+ * Kenneth Chen <kenneth.w.chen@intel.com>
+ * Fenghua Yu <fenghua.yu@intel.com>
+ *
+ * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling for SMP
+ * 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB handler now uses virtual PT.
+ */
+/*
+ * This file defines the interruption vector table used by the CPU.
+ * It does not include one entry per possible cause of interruption.
+ *
+ * The first 20 entries of the table contain 64 bundles each while the
+ * remaining 48 entries contain only 16 bundles each.
+ *
+ * The 64 bundles are used to allow inlining the whole handler for critical
+ * interruptions like TLB misses.
+ *
+ * For each entry, the comment is as follows:
+ *
+ * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ * entry offset ----/ / / / /
+ * entry number ---------/ / / /
+ * size of the entry -------------/ / /
+ * vector name -------------------------------------/ /
+ * interruptions triggering this vector ----------------------/
+ *
+ * The table is 32KB in size and must be aligned on 32KB boundary.
+ * (The CPU ignores the 15 lower bits of the address)
+ *
+ * Table is based upon EAS2.6 (Oct 1999)
+ */
+
+#include <linux/config.h>
+
+#include <asm/asmmacro.h>
+#include <asm/break.h>
+#include <asm/ia32.h>
+#include <asm/kregs.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+
+#if 1
+# define PSR_DEFAULT_BITS psr.ac
+#else
+# define PSR_DEFAULT_BITS 0
+#endif
+
+#if 0
+ /*
+ * This lets you track the last eight faults that occurred on the CPU. Make sure ar.k2 isn't
+ * needed for something else before enabling this...
+ */
+# define DBG_FAULT(i) mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16
+#else
+# define DBG_FAULT(i)
+#endif
+
+#include "minstate.h"
+
+#define FAULT(n) \
+ mov r31=pr; \
+ mov r19=n;; /* prepare to save predicates */ \
+ br.sptk.many dispatch_to_fault_handler
+
+ .section .text.ivt,"ax"
+
+ .align 32768 // align on 32KB boundary
+ .global ia64_ivt
+ia64_ivt:
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
+ENTRY(vhpt_miss)
+ DBG_FAULT(0)
+ /*
+ * The VHPT vector is invoked when the TLB entry for the virtual page table
+ * is missing. This happens only as a result of a previous
+ * (the "original") TLB miss, which may either be caused by an instruction
+ * fetch or a data access (or non-access).
+ *
+ * What we do here is normal TLB miss handing for the _original_ miss,
+ * followed by inserting the TLB entry for the virtual page table page
+ * that the VHPT walker was attempting to access. The latter gets
+ * inserted as long as page table entry above pte level have valid
+ * mappings for the faulting address. The TLB entry for the original
+ * miss gets inserted only if the pte entry indicates that the page is
+ * present.
+ *
+ * do_page_fault gets invoked in the following cases:
+ * - the faulting virtual address uses unimplemented address bits
+ * - the faulting virtual address has no valid page table mapping
+ */
+$vhpt_miss_handler
+END(vhpt_miss)
+
+ .org ia64_ivt+0x400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
+ENTRY(itlb_miss)
+ DBG_FAULT(1)
+ /*
+ * The ITLB handler accesses the PTE via the virtually mapped linear
+ * page table. If a nested TLB miss occurs, we switch into physical
+ * mode, walk the page table, and then re-execute the PTE read and
+ * go on normally after that.
+ */
+$itlb_miss_handler
+END(itlb_miss)
+
+ .org ia64_ivt+0x0800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
+ENTRY(dtlb_miss)
+ DBG_FAULT(2)
+ /*
+ * The DTLB handler accesses the PTE via the virtually mapped linear
+ * page table. If a nested TLB miss occurs, we switch into physical
+ * mode, walk the page table, and then re-execute the PTE read and
+ * go on normally after that.
+ */
+$dtlb_miss_handler
+END(dtlb_miss)
+
+ .org ia64_ivt+0x0c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
+ENTRY(alt_itlb_miss)
+ DBG_FAULT(3)
+ mov r16=cr.ifa // get address that caused the TLB miss
+ movl r17=PAGE_KERNEL
+ mov r21=cr.ipsr
+ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+ mov r31=pr
+ ;;
+#ifdef CONFIG_DISABLE_VHPT
+ shr.u r22=r16,61 // get the region number into r21
+ ;;
+ cmp.gt p8,p0=6,r22 // user mode
+ ;;
+(p8) thash r17=r16
+ ;;
+(p8) mov cr.iha=r17
+(p8) mov r29=b0 // save b0
+(p8) br.cond.dptk .itlb_fault
+#endif
+ extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
+ and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
+ shr.u r18=r16,57 // move address bit 61 to bit 4
+ ;;
+ andcm r18=0x10,r18 // bit 4=~address-bit(61)
+ cmp.ne p8,p0=r0,r23 // psr.cpl != 0?
+ or r19=r17,r19 // insert PTE control bits into r19
+ ;;
+ or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
+(p8) br.cond.spnt page_fault
+ ;;
+ itc.i r19 // insert the TLB entry
+ mov pr=r31,-1
+ rfi
+END(alt_itlb_miss)
+
+ .org ia64_ivt+0x1000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
+ENTRY(alt_dtlb_miss)
+ DBG_FAULT(4)
+ mov r16=cr.ifa // get address that caused the TLB miss
+ movl r17=PAGE_KERNEL
+ mov r20=cr.isr
+ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+ mov r21=cr.ipsr
+ mov r31=pr
+ ;;
+#ifdef CONFIG_DISABLE_VHPT
+ shr.u r22=r16,61 // get the region number into r21
+ ;;
+ cmp.gt p8,p0=6,r22 // access to region 0-5
+ ;;
+(p8) thash r17=r16
+ ;;
+(p8) mov cr.iha=r17
+(p8) mov r29=b0 // save b0
+(p8) br.cond.dptk dtlb_fault
+#endif
+ extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
+ and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
+ tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
+ shr.u r18=r16,57 // move address bit 61 to bit 4
+ and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
+ tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
+ ;;
+ andcm r18=0x10,r18 // bit 4=~address-bit(61)
+ cmp.ne p8,p0=r0,r23
+(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
+(p8) br.cond.spnt page_fault
+
+ dep r21=-1,r21,IA64_PSR_ED_BIT,1
+ or r19=r19,r17 // insert PTE control bits into r19
+ ;;
+ or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
+(p6) mov cr.ipsr=r21
+ ;;
+(p7) itc.d r19 // insert the TLB entry
+ mov pr=r31,-1
+ rfi
+END(alt_dtlb_miss)
+
+ .org ia64_ivt+0x1400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
+ENTRY(nested_dtlb_miss)
+ /*
+ * In the absence of kernel bugs, we get here when the virtually mapped linear
+ * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
+ * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page
+ * table is missing, a nested TLB miss fault is triggered and control is
+ * transferred to this point. When this happens, we lookup the pte for the
+ * faulting address by walking the page table in physical mode and return to the
+ * continuation point passed in register r30 (or call page_fault if the address is
+ * not mapped).
+ *
+ * Input: r16: faulting address
+ * r29: saved b0
+ * r30: continuation address
+ * r31: saved pr
+ *
+ * Output: r17: physical address of PTE of faulting address
+ * r29: saved b0
+ * r30: continuation address
+ * r31: saved pr
+ *
+ * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared)
+ */
+$nested_dtlb_miss_handler
+END(nested_dtlb_miss)
+
+ .org ia64_ivt+0x1800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
+ENTRY(ikey_miss)
+ DBG_FAULT(6)
+ FAULT(6)
+END(ikey_miss)
+
+ //-----------------------------------------------------------------------------------
+ // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
+ENTRY(page_fault)
+ ssm psr.dt
+ ;;
+ srlz.i
+ ;;
+ SAVE_MIN_WITH_COVER
+ alloc r15=ar.pfs,0,0,3,0
+ mov out0=cr.ifa
+ mov out1=cr.isr
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collectin is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ movl r14=ia64_leave_kernel
+ ;;
+ SAVE_REST
+ mov rp=r14
+ ;;
+ adds out2=16,r12 // out2 = pointer to pt_regs
+ br.call.sptk.many b6=ia64_do_page_fault // ignore return address
+END(page_fault)
+
+ .org ia64_ivt+0x1c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ENTRY(dkey_miss)
+ DBG_FAULT(7)
+ FAULT(7)
+END(dkey_miss)
+
+ .org ia64_ivt+0x2000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
+ENTRY(dirty_bit)
+ DBG_FAULT(8)
+$dirty_bit_handler
+END(dirty_bit)
+
+ .org ia64_ivt+0x2400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
+ENTRY(iaccess_bit)
+ DBG_FAULT(9)
+$iaccess_bit_handler
+END(iaccess_bit)
+
+ .org ia64_ivt+0x2800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
+ENTRY(daccess_bit)
+ DBG_FAULT(10)
+$daccess_bit_handler
+END(daccess_bit)
+
+ .org ia64_ivt+0x2c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
+ENTRY(break_fault)
+ /*
+ * The streamlined system call entry/exit paths only save/restore the initial part
+ * of pt_regs. This implies that the callers of system-calls must adhere to the
+ * normal procedure calling conventions.
+ *
+ * Registers to be saved & restored:
+ * CR registers: cr.ipsr, cr.iip, cr.ifs
+ * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr
+ * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15
+ * Registers to be restored only:
+ * r8-r11: output value from the system call.
+ *
+ * During system call exit, scratch registers (including r15) are modified/cleared
+ * to prevent leaking bits from kernel to user level.
+ */
+ DBG_FAULT(11)
+ mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc)
+ mov r29=cr.ipsr // M2 (12 cyc)
+ mov r31=pr // I0 (2 cyc)
+
+ mov r17=cr.iim // M2 (2 cyc)
+ mov.m r27=ar.rsc // M2 (12 cyc)
+ mov r18=__IA64_BREAK_SYSCALL // A
+
+ mov.m ar.rsc=0 // M2
+ mov.m r21=ar.fpsr // M2 (12 cyc)
+ mov r19=b6 // I0 (2 cyc)
+ ;;
+ mov.m r23=ar.bspstore // M2 (12 cyc)
+ mov.m r24=ar.rnat // M2 (5 cyc)
+ mov.i r26=ar.pfs // I0 (2 cyc)
+
+ invala // M0|1
+ nop.m 0 // M
+ mov r20=r1 // A save r1
+
+ nop.m 0
+ movl r30=sys_call_table // X
+
+ mov r28=cr.iip // M2 (2 cyc)
+ cmp.eq p0,p7=r18,r17 // I0 is this a system call?
+(p7) br.cond.spnt non_syscall // B no ->
+ //
+ // From this point on, we are definitely on the syscall-path
+ // and we can use (non-banked) scratch registers.
+ //
+///////////////////////////////////////////////////////////////////////
+ mov r1=r16 // A move task-pointer to "addl"-addressable reg
+ mov r2=r16 // A setup r2 for ia64_syscall_setup
+ add r9=TI_FLAGS+IA64_TASK_SIZE,r16 // A r9 = ¤t_thread_info()->flags
+
+ adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16
+ adds r15=-1024,r15 // A subtract 1024 from syscall number
+ mov r3=NR_syscalls - 1
+ ;;
+ ld1.bias r17=[r16] // M0|1 r17 = current->thread.on_ustack flag
+ ld4 r9=[r9] // M0|1 r9 = current_thread_info()->flags
+ extr.u r8=r29,41,2 // I0 extract ei field from cr.ipsr
+
+ shladd r30=r15,3,r30 // A r30 = sys_call_table + 8*(syscall-1024)
+ addl r22=IA64_RBS_OFFSET,r1 // A compute base of RBS
+ cmp.leu p6,p7=r15,r3 // A syscall number in range?
+ ;;
+
+ lfetch.fault.excl.nt1 [r22] // M0|1 prefetch RBS
+(p6) ld8 r30=[r30] // M0|1 load address of syscall entry point
+ tnat.nz.or p7,p0=r15 // I0 is syscall nr a NaT?
+
+ mov.m ar.bspstore=r22 // M2 switch to kernel RBS
+ cmp.eq p8,p9=2,r8 // A isr.ei==2?
+ ;;
+
+(p8) mov r8=0 // A clear ei to 0
+(p7) movl r30=sys_ni_syscall // X
+
+(p8) adds r28=16,r28 // A switch cr.iip to next bundle
+(p9) adds r8=1,r8 // A increment ei to next slot
+ nop.i 0
+ ;;
+
+ mov.m r25=ar.unat // M2 (5 cyc)
+ dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr
+ adds r15=1024,r15 // A restore original syscall number
+ //
+ // If any of the above loads miss in L1D, we'll stall here until
+ // the data arrives.
+ //
+///////////////////////////////////////////////////////////////////////
+ st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag
+ mov b6=r30 // I0 setup syscall handler branch reg early
+ cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already?
+
+ and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit
+ mov r18=ar.bsp // M2 (12 cyc)
+(pKStk) br.cond.spnt .break_fixup // B we're already in kernel-mode -- fix up RBS
+ ;;
+.back_from_break_fixup:
+(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A compute base of memory stack
+ cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited?
+ br.call.sptk.many b7=ia64_syscall_setup // B
+1:
+ mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
+ nop 0
+ bsw.1 // B (6 cyc) regs are saved, switch to bank 1
+ ;;
+
+ ssm psr.ic | PSR_DEFAULT_BITS // M2 now it's safe to re-enable intr.-collection
+ movl r3=ia64_ret_from_syscall // X
+ ;;
+
+ srlz.i // M0 ensure interruption collection is on
+ mov rp=r3 // I0 set the real return addr
+(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT
+
+(p15) ssm psr.i // M2 restore psr.i
+(p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr)
+ br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic
+ // NOT REACHED
+///////////////////////////////////////////////////////////////////////
+ // On entry, we optimistically assumed that we're coming from user-space.
+ // For the rare cases where a system-call is done from within the kernel,
+ // we fix things up at this point:
+.break_fixup:
+ add r1=-IA64_PT_REGS_SIZE,sp // A allocate space for pt_regs structure
+ mov ar.rnat=r24 // M2 restore kernel's AR.RNAT
+ ;;
+ mov ar.bspstore=r23 // M2 restore kernel's AR.BSPSTORE
+ br.cond.sptk .back_from_break_fixup
+END(break_fault)
+
+ .org ia64_ivt+0x3000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
+ENTRY(interrupt)
+ DBG_FAULT(12)
+ mov r31=pr // prepare to save predicates
+ ;;
+ SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ srlz.i // ensure everybody knows psr.ic is back on
+ ;;
+ SAVE_REST
+ ;;
+ MCA_RECOVER_RANGE(interrupt)
+ alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
+ mov out0=cr.ivr // pass cr.ivr as first arg
+ add out1=16,sp // pass pointer to pt_regs as second arg
+ ;;
+ srlz.d // make sure we see the effect of cr.ivr
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+ br.call.sptk.many b6=ia64_handle_irq
+END(interrupt)
+
+ .org ia64_ivt+0x3400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3400 Entry 13 (size 64 bundles) Reserved
+ DBG_FAULT(13)
+ FAULT(13)
+
+ .org ia64_ivt+0x3800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3800 Entry 14 (size 64 bundles) Reserved
+ DBG_FAULT(14)
+ FAULT(14)
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ *
+ * ia64_syscall_setup() is a separate subroutine so that it can
+ * allocate stacked registers so it can safely demine any
+ * potential NaT values from the input registers.
+ *
+ * On entry:
+ * - executing on bank 0 or bank 1 register set (doesn't matter)
+ * - r1: stack pointer
+ * - r2: current task pointer
+ * - r3: preserved
+ * - r11: original contents (saved ar.pfs to be saved)
+ * - r12: original contents (sp to be saved)
+ * - r13: original contents (tp to be saved)
+ * - r15: original contents (syscall # to be saved)
+ * - r18: saved bsp (after switching to kernel stack)
+ * - r19: saved b6
+ * - r20: saved r1 (gp)
+ * - r21: saved ar.fpsr
+ * - r22: kernel's register backing store base (krbs_base)
+ * - r23: saved ar.bspstore
+ * - r24: saved ar.rnat
+ * - r25: saved ar.unat
+ * - r26: saved ar.pfs
+ * - r27: saved ar.rsc
+ * - r28: saved cr.iip
+ * - r29: saved cr.ipsr
+ * - r31: saved pr
+ * - b0: original contents (to be saved)
+ * On exit:
+ * - p10: TRUE if syscall is invoked with more than 8 out
+ * registers or r15's Nat is true
+ * - r1: kernel's gp
+ * - r3: preserved (same as on entry)
+ * - r8: -EINVAL if p10 is true
+ * - r12: points to kernel stack
+ * - r13: points to current task
+ * - r14: preserved (same as on entry)
+ * - p13: preserved
+ * - p15: TRUE if interrupts need to be re-enabled
+ * - ar.fpsr: set to kernel settings
+ * - b6: preserved (same as on entry)
+ */
+GLOBAL_ENTRY(ia64_syscall_setup)
+#if PT(B6) != 0
+# error This code assumes that b6 is the first field in pt_regs.
+#endif
+ st8 [r1]=r19 // save b6
+ add r16=PT(CR_IPSR),r1 // initialize first base pointer
+ add r17=PT(R11),r1 // initialize second base pointer
+ ;;
+ alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable
+ st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr
+ tnat.nz p8,p0=in0
+
+ st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11
+ tnat.nz p9,p0=in1
+(pKStk) mov r18=r0 // make sure r18 isn't NaT
+ ;;
+
+ st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs
+ st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip
+ mov r28=b0 // save b0 (2 cyc)
+ ;;
+
+ st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat
+ dep r19=0,r19,38,26 // clear all bits but 0..37 [I0]
+(p8) mov in0=-1
+ ;;
+
+ st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs
+ extr.u r11=r19,7,7 // I0 // get sol of ar.pfs
+ and r8=0x7f,r19 // A // get sof of ar.pfs
+
+ st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc
+ tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0
+(p9) mov in1=-1
+ ;;
+
+(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8
+ tnat.nz p10,p0=in2
+ add r11=8,r11
+ ;;
+(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field
+(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field
+ tnat.nz p11,p0=in3
+ ;;
+(p10) mov in2=-1
+ tnat.nz p12,p0=in4 // [I0]
+(p11) mov in3=-1
+ ;;
+(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat
+(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore
+ shl r18=r18,16 // compute ar.rsc to be used for "loadrs"
+ ;;
+ st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates
+ st8 [r17]=r28,PT(R1)-PT(B0) // save b0
+ tnat.nz p13,p0=in5 // [I0]
+ ;;
+ st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs"
+ st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1
+(p12) mov in4=-1
+ ;;
+
+.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12
+.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13
+(p13) mov in5=-1
+ ;;
+ st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr
+ tnat.nz p13,p0=in6
+ cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8
+ ;;
+ mov r8=1
+(p9) tnat.nz p10,p0=r15
+ adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch)
+
+ st8.spill [r17]=r15 // save r15
+ tnat.nz p8,p0=in7
+ nop.i 0
+
+ mov r13=r2 // establish `current'
+ movl r1=__gp // establish kernel global pointer
+ ;;
+ st8 [r16]=r8 // ensure pt_regs.r8 != 0 (see handle_syscall_error)
+(p13) mov in6=-1
+(p8) mov in7=-1
+
+ cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
+ movl r17=FPSR_DEFAULT
+ ;;
+ mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value
+(p10) mov r8=-EINVAL
+ br.ret.sptk.many b7
+END(ia64_syscall_setup)
+
+ .org ia64_ivt+0x3c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3c00 Entry 15 (size 64 bundles) Reserved
+ DBG_FAULT(15)
+ FAULT(15)
+
+ /*
+ * Squatting in this space ...
+ *
+ * This special case dispatcher for illegal operation faults allows preserved
+ * registers to be modified through a callback function (asm only) that is handed
+ * back from the fault handler in r8. Up to three arguments can be passed to the
+ * callback function by returning an aggregate with the callback as its first
+ * element, followed by the arguments.
+ */
+ENTRY(dispatch_illegal_op_fault)
+ .prologue
+ .body
+ SAVE_MIN_WITH_COVER
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ ;;
+ alloc r14=ar.pfs,0,0,1,0 // must be first in insn group
+ mov out0=ar.ec
+ ;;
+ SAVE_REST
+ PT_REGS_UNWIND_INFO(0)
+ ;;
+ br.call.sptk.many rp=ia64_illegal_op_fault
+.ret0: ;;
+ alloc r14=ar.pfs,0,0,3,0 // must be first in insn group
+ mov out0=r9
+ mov out1=r10
+ mov out2=r11
+ movl r15=ia64_leave_kernel
+ ;;
+ mov rp=r15
+ mov b6=r8
+ ;;
+ cmp.ne p6,p0=0,r8
+(p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel
+ br.sptk.many ia64_leave_kernel
+END(dispatch_illegal_op_fault)
+
+ .org ia64_ivt+0x4000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4000 Entry 16 (size 64 bundles) Reserved
+ DBG_FAULT(16)
+ FAULT(16)
+
+ .org ia64_ivt+0x4400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4400 Entry 17 (size 64 bundles) Reserved
+ DBG_FAULT(17)
+ FAULT(17)
+
+ENTRY(non_syscall)
+ mov ar.rsc=r27 // restore ar.rsc before SAVE_MIN_WITH_COVER
+ ;;
+ SAVE_MIN_WITH_COVER
+
+ // There is no particular reason for this code to be here, other than that
+ // there happens to be space here that would go unused otherwise. If this
+ // fault ever gets "unreserved", simply moved the following code to a more
+ // suitable spot...
+
+ alloc r14=ar.pfs,0,0,2,0
+ mov out0=cr.iim
+ add out1=16,sp
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ movl r15=ia64_leave_kernel
+ ;;
+ SAVE_REST
+ mov rp=r15
+ ;;
+ br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr
+END(non_syscall)
+
+ .org ia64_ivt+0x4800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4800 Entry 18 (size 64 bundles) Reserved
+ DBG_FAULT(18)
+ FAULT(18)
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ */
+
+ENTRY(dispatch_unaligned_handler)
+ SAVE_MIN_WITH_COVER
+ ;;
+ alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
+ mov out0=cr.ifa
+ adds out1=16,sp
+
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ SAVE_REST
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+ br.sptk.many ia64_prepare_handle_unaligned
+END(dispatch_unaligned_handler)
+
+ .org ia64_ivt+0x4c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4c00 Entry 19 (size 64 bundles) Reserved
+ DBG_FAULT(19)
+ FAULT(19)
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ */
+
+ENTRY(dispatch_to_fault_handler)
+ /*
+ * Input:
+ * psr.ic: off
+ * r19: fault vector number (e.g., 24 for General Exception)
+ * r31: contains saved predicates (pr)
+ */
+ SAVE_MIN_WITH_COVER_R19
+ alloc r14=ar.pfs,0,0,5,0
+ mov out0=r15
+ mov out1=cr.isr
+ mov out2=cr.ifa
+ mov out3=cr.iim
+ mov out4=cr.itir
+ ;;
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ ;;
+ SAVE_REST
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+ br.call.sptk.many b6=ia64_fault
+END(dispatch_to_fault_handler)
+
+//
+// --- End of long entries, Beginning of short entries
+//
+
+ .org ia64_ivt+0x5000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
+ENTRY(page_not_present)
+ DBG_FAULT(20)
+ mov r16=cr.ifa
+ rsm psr.dt
+ /*
+ * The Linux page fault handler doesn't expect non-present pages to be in
+ * the TLB. Flush the existing entry now, so we meet that expectation.
+ */
+ mov r17=PAGE_SHIFT<<2
+ ;;
+ ptc.l r16,r17
+ ;;
+ mov r31=pr
+ srlz.d
+ br.sptk.many page_fault
+END(page_not_present)
+
+ .org ia64_ivt+0x5100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
+ENTRY(key_permission)
+ DBG_FAULT(21)
+ mov r16=cr.ifa
+ rsm psr.dt
+ mov r31=pr
+ ;;
+ srlz.d
+ br.sptk.many page_fault
+END(key_permission)
+
+ .org ia64_ivt+0x5200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
+ENTRY(iaccess_rights)
+ DBG_FAULT(22)
+ mov r16=cr.ifa
+ rsm psr.dt
+ mov r31=pr
+ ;;
+ srlz.d
+ br.sptk.many page_fault
+END(iaccess_rights)
+
+ .org ia64_ivt+0x5300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
+ENTRY(daccess_rights)
+ DBG_FAULT(23)
+ mov r16=cr.ifa
+ rsm psr.dt
+ mov r31=pr
+ ;;
+ srlz.d
+ br.sptk.many page_fault
+END(daccess_rights)
+
+ .org ia64_ivt+0x5400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
+ENTRY(general_exception)
+ DBG_FAULT(24)
+ mov r16=cr.isr
+ mov r31=pr
+ ;;
+ cmp4.eq p6,p0=0,r16
+(p6) br.sptk.many dispatch_illegal_op_fault
+ ;;
+ mov r19=24 // fault number
+ br.sptk.many dispatch_to_fault_handler
+END(general_exception)
+
+ .org ia64_ivt+0x5500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
+ENTRY(disabled_fp_reg)
+ DBG_FAULT(25)
+ rsm psr.dfh // ensure we can access fph
+ ;;
+ srlz.d
+ mov r31=pr
+ mov r19=25
+ br.sptk.many dispatch_to_fault_handler
+END(disabled_fp_reg)
+
+ .org ia64_ivt+0x5600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
+ENTRY(nat_consumption)
+ DBG_FAULT(26)
+
+ mov r16=cr.ipsr
+ mov r17=cr.isr
+ mov r31=pr // save PR
+ ;;
+ and r18=0xf,r17 // r18 = cr.ipsr.code{3:0}
+ tbit.z p6,p0=r17,IA64_ISR_NA_BIT
+ ;;
+ cmp.ne.or p6,p0=IA64_ISR_CODE_LFETCH,r18
+ dep r16=-1,r16,IA64_PSR_ED_BIT,1
+(p6) br.cond.spnt 1f // branch if (cr.ispr.na == 0 || cr.ipsr.code{3:0} != LFETCH)
+ ;;
+ mov cr.ipsr=r16 // set cr.ipsr.na
+ mov pr=r31,-1
+ ;;
+ rfi
+
+1: mov pr=r31,-1
+ ;;
+ FAULT(26)
+END(nat_consumption)
+
+ .org ia64_ivt+0x5700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
+ENTRY(speculation_vector)
+ DBG_FAULT(27)
+ /*
+ * A [f]chk.[as] instruction needs to take the branch to the recovery code but
+ * this part of the architecture is not implemented in hardware on some CPUs, such
+ * as Itanium. Thus, in general we need to emulate the behavior. IIM contains
+ * the relative target (not yet sign extended). So after sign extending it we
+ * simply add it to IIP. We also need to reset the EI field of the IPSR to zero,
+ * i.e., the slot to restart into.
+ *
+ * cr.imm contains zero_ext(imm21)
+ */
+ mov r18=cr.iim
+ ;;
+ mov r17=cr.iip
+ shl r18=r18,43 // put sign bit in position (43=64-21)
+ ;;
+
+ mov r16=cr.ipsr
+ shr r18=r18,39 // sign extend (39=43-4)
+ ;;
+
+ add r17=r17,r18 // now add the offset
+ ;;
+ mov cr.iip=r17
+ dep r16=0,r16,41,2 // clear EI
+ ;;
+
+ mov cr.ipsr=r16
+ ;;
+
+ rfi // and go back
+END(speculation_vector)
+
+ .org ia64_ivt+0x5800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5800 Entry 28 (size 16 bundles) Reserved
+ DBG_FAULT(28)
+ FAULT(28)
+
+ .org ia64_ivt+0x5900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
+ENTRY(debug_vector)
+ DBG_FAULT(29)
+ FAULT(29)
+END(debug_vector)
+
+ .org ia64_ivt+0x5a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
+ENTRY(unaligned_access)
+ DBG_FAULT(30)
+ mov r31=pr // prepare to save predicates
+ ;;
+ br.sptk.many dispatch_unaligned_handler
+END(unaligned_access)
+
+ .org ia64_ivt+0x5b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
+ENTRY(unsupported_data_reference)
+ DBG_FAULT(31)
+ FAULT(31)
+END(unsupported_data_reference)
+
+ .org ia64_ivt+0x5c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
+ENTRY(floating_point_fault)
+ DBG_FAULT(32)
+ FAULT(32)
+END(floating_point_fault)
+
+ .org ia64_ivt+0x5d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
+ENTRY(floating_point_trap)
+ DBG_FAULT(33)
+ FAULT(33)
+END(floating_point_trap)
+
+ .org ia64_ivt+0x5e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
+ENTRY(lower_privilege_trap)
+ DBG_FAULT(34)
+ FAULT(34)
+END(lower_privilege_trap)
+
+ .org ia64_ivt+0x5f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
+ENTRY(taken_branch_trap)
+ DBG_FAULT(35)
+ FAULT(35)
+END(taken_branch_trap)
+
+ .org ia64_ivt+0x6000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
+ENTRY(single_step_trap)
+ DBG_FAULT(36)
+ FAULT(36)
+END(single_step_trap)
+
+ .org ia64_ivt+0x6100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6100 Entry 37 (size 16 bundles) Reserved
+ DBG_FAULT(37)
+ FAULT(37)
+
+ .org ia64_ivt+0x6200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6200 Entry 38 (size 16 bundles) Reserved
+ DBG_FAULT(38)
+ FAULT(38)
+
+ .org ia64_ivt+0x6300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6300 Entry 39 (size 16 bundles) Reserved
+ DBG_FAULT(39)
+ FAULT(39)
+
+ .org ia64_ivt+0x6400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6400 Entry 40 (size 16 bundles) Reserved
+ DBG_FAULT(40)
+ FAULT(40)
+
+ .org ia64_ivt+0x6500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6500 Entry 41 (size 16 bundles) Reserved
+ DBG_FAULT(41)
+ FAULT(41)
+
+ .org ia64_ivt+0x6600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6600 Entry 42 (size 16 bundles) Reserved
+ DBG_FAULT(42)
+ FAULT(42)
+
+ .org ia64_ivt+0x6700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6700 Entry 43 (size 16 bundles) Reserved
+ DBG_FAULT(43)
+ FAULT(43)
+
+ .org ia64_ivt+0x6800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6800 Entry 44 (size 16 bundles) Reserved
+ DBG_FAULT(44)
+ FAULT(44)
+
+ .org ia64_ivt+0x6900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
+ENTRY(ia32_exception)
+ DBG_FAULT(45)
+ FAULT(45)
+END(ia32_exception)
+
+ .org ia64_ivt+0x6a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
+ENTRY(ia32_intercept)
+ DBG_FAULT(46)
+#ifdef CONFIG_IA32_SUPPORT
+ mov r31=pr
+ mov r16=cr.isr
+ ;;
+ extr.u r17=r16,16,8 // get ISR.code
+ mov r18=ar.eflag
+ mov r19=cr.iim // old eflag value
+ ;;
+ cmp.ne p6,p0=2,r17
+(p6) br.cond.spnt 1f // not a system flag fault
+ xor r16=r18,r19
+ ;;
+ extr.u r17=r16,18,1 // get the eflags.ac bit
+ ;;
+ cmp.eq p6,p0=0,r17
+(p6) br.cond.spnt 1f // eflags.ac bit didn't change
+ ;;
+ mov pr=r31,-1 // restore predicate registers
+ rfi
+
+1:
+#endif // CONFIG_IA32_SUPPORT
+ FAULT(46)
+END(ia32_intercept)
+
+ .org ia64_ivt+0x6b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74)
+ENTRY(ia32_interrupt)
+ DBG_FAULT(47)
+#ifdef CONFIG_IA32_SUPPORT
+ mov r31=pr
+ br.sptk.many dispatch_to_ia32_handler
+#else
+ FAULT(47)
+#endif
+END(ia32_interrupt)
+
+ .org ia64_ivt+0x6c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6c00 Entry 48 (size 16 bundles) Reserved
+ DBG_FAULT(48)
+ FAULT(48)
+
+ .org ia64_ivt+0x6d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6d00 Entry 49 (size 16 bundles) Reserved
+ DBG_FAULT(49)
+ FAULT(49)
+
+ .org ia64_ivt+0x6e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6e00 Entry 50 (size 16 bundles) Reserved
+ DBG_FAULT(50)
+ FAULT(50)
+
+ .org ia64_ivt+0x6f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6f00 Entry 51 (size 16 bundles) Reserved
+ DBG_FAULT(51)
+ FAULT(51)
+
+ .org ia64_ivt+0x7000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7000 Entry 52 (size 16 bundles) Reserved
+ DBG_FAULT(52)
+ FAULT(52)
+
+ .org ia64_ivt+0x7100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7100 Entry 53 (size 16 bundles) Reserved
+ DBG_FAULT(53)
+ FAULT(53)
+
+ .org ia64_ivt+0x7200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7200 Entry 54 (size 16 bundles) Reserved
+ DBG_FAULT(54)
+ FAULT(54)
+
+ .org ia64_ivt+0x7300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7300 Entry 55 (size 16 bundles) Reserved
+ DBG_FAULT(55)
+ FAULT(55)
+
+ .org ia64_ivt+0x7400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7400 Entry 56 (size 16 bundles) Reserved
+ DBG_FAULT(56)
+ FAULT(56)
+
+ .org ia64_ivt+0x7500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7500 Entry 57 (size 16 bundles) Reserved
+ DBG_FAULT(57)
+ FAULT(57)
+
+ .org ia64_ivt+0x7600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7600 Entry 58 (size 16 bundles) Reserved
+ DBG_FAULT(58)
+ FAULT(58)
+
+ .org ia64_ivt+0x7700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7700 Entry 59 (size 16 bundles) Reserved
+ DBG_FAULT(59)
+ FAULT(59)
+
+ .org ia64_ivt+0x7800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7800 Entry 60 (size 16 bundles) Reserved
+ DBG_FAULT(60)
+ FAULT(60)
+
+ .org ia64_ivt+0x7900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7900 Entry 61 (size 16 bundles) Reserved
+ DBG_FAULT(61)
+ FAULT(61)
+
+ .org ia64_ivt+0x7a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7a00 Entry 62 (size 16 bundles) Reserved
+ DBG_FAULT(62)
+ FAULT(62)
+
+ .org ia64_ivt+0x7b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7b00 Entry 63 (size 16 bundles) Reserved
+ DBG_FAULT(63)
+ FAULT(63)
+
+ .org ia64_ivt+0x7c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7c00 Entry 64 (size 16 bundles) Reserved
+ DBG_FAULT(64)
+ FAULT(64)
+
+ .org ia64_ivt+0x7d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7d00 Entry 65 (size 16 bundles) Reserved
+ DBG_FAULT(65)
+ FAULT(65)
+
+ .org ia64_ivt+0x7e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7e00 Entry 66 (size 16 bundles) Reserved
+ DBG_FAULT(66)
+ FAULT(66)
+
+ .org ia64_ivt+0x7f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7f00 Entry 67 (size 16 bundles) Reserved
+ DBG_FAULT(67)
+ FAULT(67)
+
+#ifdef CONFIG_IA32_SUPPORT
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ */
+
+ // IA32 interrupt entry point
+
+ENTRY(dispatch_to_ia32_handler)
+ SAVE_MIN
+ ;;
+ mov r14=cr.isr
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i
+ adds r3=8,r2 // Base pointer for SAVE_REST
+ ;;
+ SAVE_REST
+ ;;
+ mov r15=0x80
+ shr r14=r14,16 // Get interrupt number
+ ;;
+ cmp.ne p6,p0=r14,r15
+(p6) br.call.dpnt.many b6=non_ia32_syscall
+
+ adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions
+ adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
+ ;;
+ cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
+ ld8 r8=[r14] // get r8
+ ;;
+ st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP)
+ ;;
+ alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
+ ;;
+ ld4 r8=[r14],8 // r8 == eax (syscall number)
+ mov r15=IA32_NR_syscalls
+ ;;
+ cmp.ltu.unc p6,p7=r8,r15
+ ld4 out1=[r14],8 // r9 == ecx
+ ;;
+ ld4 out2=[r14],8 // r10 == edx
+ ;;
+ ld4 out0=[r14] // r11 == ebx
+ adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp
+ ;;
+ ld4 out5=[r14],PT(R14)-PT(R13) // r13 == ebp
+ ;;
+ ld4 out3=[r14],PT(R15)-PT(R14) // r14 == esi
+ adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
+ ;;
+ ld4 out4=[r14] // r15 == edi
+ movl r16=ia32_syscall_table
+ ;;
+(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
+ ld4 r2=[r2] // r2 = current_thread_info()->flags
+ ;;
+ ld8 r16=[r16]
+ and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit
+ ;;
+ mov b6=r16
+ movl r15=ia32_ret_from_syscall
+ cmp.eq p8,p0=r2,r0
+ ;;
+ mov rp=r15
+(p8) br.call.sptk.many b6=b6
+ br.cond.sptk ia32_trace_syscall
+
+non_ia32_syscall:
+ alloc r15=ar.pfs,0,0,2,0
+ mov out0=r14 // interrupt #
+ add out1=16,sp // pointer to pt_regs
+ ;; // avoid WAW on CFM
+ br.call.sptk.many rp=ia32_bad_interrupt
+.ret1: movl r15=ia64_leave_kernel
+ ;;
+ mov rp=r15
+ br.ret.sptk.many rp
+END(dispatch_to_ia32_handler)
+
+#endif /* CONFIG_IA32_SUPPORT */
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt-sfvhpt.in
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt-sfvhpt.in 2006-05-05 10:09:38.000000000 +1000
@@ -0,0 +1,444 @@
+/*
+ * This file is to be processed and inserted into the actual ivt.S
+ *
+ * Any variable $name in ivt.S will be replaced with what is between
+ *__begin_name__ and __end_name__ in this file.
+ *
+ */
+
+//vhpt_miss
+__begin_vhpt_miss_handler__
+ mov r16=cr.ifa // get address that caused the TLB miss
+#ifdef CONFIG_HUGETLB_PAGE
+ movl r18=PAGE_SHIFT
+ mov r25=cr.itir
+#endif
+ ;;
+ rsm psr.dt // use physical addressing for data
+ mov r31=pr // save the predicate registers
+ mov r19=IA64_KR(PT_BASE) // get page table base address
+ shl r21=r16,3 // shift bit 60 into sign bit
+ shr.u r17=r16,61 // get the region number into r17
+ ;;
+ shr.u r22=r21,3
+#ifdef CONFIG_HUGETLB_PAGE
+ extr.u r26=r25,2,6
+ ;;
+ cmp.ne p8,p0=r18,r26
+ sub r27=r26,r18
+ ;;
+(p8) dep r25=r18,r25,2,6
+(p8) shr r22=r22,r27
+#endif
+ ;;
+ cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
+ shr.u r18=r22,PGDIR_SHIFT // get bottom portion of pgd index bit
+ ;;
+(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
+
+ srlz.d
+ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
+
+ .pred.rel "mutex", p6, p7
+(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+ ;;
+(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
+(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
+ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+ shr.u r28=r22,PUD_SHIFT // shift pud index into position
+#else
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+#endif
+ ;;
+ ld8 r17=[r17] // get *pgd (may be 0)
+ ;;
+(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
+#ifdef CONFIG_PGTABLE_4
+ dep r28=r28,r17,3,(PAGE_SHIFT-3) // r28=pud_offset(pgd,addr)
+ ;;
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+(p7) ld8 r29=[r28] // get *pud (may be 0)
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r29,r0 // was pud_present(*pud) == NULL?
+ dep r17=r18,r29,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
+#else
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pgd,addr)
+#endif
+ ;;
+(p7) ld8 r20=[r17] // get *pmd (may be 0)
+ shr.u r19=r22,PAGE_SHIFT // shift pte index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r20,r0 // was pmd_present(*pmd) == NULL?
+ dep r21=r19,r20,3,(PAGE_SHIFT-3) // r21=pte_offset(pmd,addr)
+ ;;
+(p7) ld8 r18=[r21] // read *pte
+ mov r19=cr.isr // cr.isr bit 32 tells us if this is an insn miss
+ ;;
+(p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared?
+ mov r22=cr.iha // get the VHPT address that caused the TLB miss
+ ;; // avoid RAW on p7
+(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss?
+ dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address
+ ;;
+(p10) itc.i r18 // insert the instruction TLB entry
+(p11) itc.d r18 // insert the data TLB entry
+(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
+ mov cr.ifa=r22
+
+#ifdef CONFIG_HUGETLB_PAGE
+(p8) mov cr.itir=r25 // change to default page-size for VHPT
+#endif
+
+ /*
+ * Now compute and insert the TLB entry for the virtual page table. We never
+ * execute in a page table page so there is no need to set the exception deferral
+ * bit.
+ */
+ adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
+ ;;
+(p7) itc.d r24
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ /*
+ * Re-check pagetable entry. If they changed, we may have received a ptc.g
+ * between reading the pagetable and the "itc". If so, flush the entry we
+ * inserted and retry. At this point, we have:
+ *
+ * r28 = equivalent of pud_offset(pgd, ifa)
+ * r17 = equivalent of pmd_offset(pud, ifa)
+ * r21 = equivalent of pte_offset(pmd, ifa)
+ *
+ * r29 = *pud
+ * r20 = *pmd
+ * r18 = *pte
+ */
+ ld8 r25=[r21] // read *pte again
+ ld8 r26=[r17] // read *pmd again
+#ifdef CONFIG_PGTABLE_4
+ ld8 r19=[r28] // read *pud again
+#endif
+ cmp.ne p6,p7=r0,r0
+ ;;
+ cmp.ne.or.andcm p6,p7=r26,r20 // did *pmd change
+#ifdef CONFIG_PGTABLE_4
+ cmp.ne.or.andcm p6,p7=r19,r29 // did *pud change
+#endif
+ mov r27=PAGE_SHIFT<<2
+ ;;
+(p6) ptc.l r22,r27 // purge PTE page translation
+(p7) cmp.ne.or.andcm p6,p7=r25,r18 // did *pte change
+ ;;
+(p6) ptc.l r16,r27 // purge translation
+#endif
+
+ mov pr=r31,-1 // restore predicate registers
+ rfi
+__end_vhpt_miss_handler__
+
+// itlb_miss
+__begin_itlb_miss_handler__
+ mov r16=cr.ifa // get virtual address
+ mov r29=b0 // save b0
+ mov r31=pr // save predicates
+.itlb_fault:
+ mov r17=cr.iha // get virtual address of PTE
+ movl r30=1f // load nested fault continuation point
+ ;;
+1: ld8 r18=[r17] // read *pte
+ ;;
+ mov b0=r29
+ tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
+(p6) br.cond.spnt page_fault
+ ;;
+ itc.i r18
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r19=[r17] // read *pte again and see if same
+ mov r20=PAGE_SHIFT<<2 // setup page size for purge
+ ;;
+ cmp.ne p7,p0=r18,r19
+ ;;
+(p7) ptc.l r16,r20
+#endif
+ mov pr=r31,-1
+ rfi
+__end_itlb_miss_handler__
+
+// dtlb_miss
+__begin_dtlb_miss_handler__
+ mov r16=cr.ifa // get virtual address
+ mov r29=b0 // save b0
+ mov r31=pr // save predicates
+dtlb_fault:
+ mov r17=cr.iha // get virtual address of PTE
+ movl r30=1f // load nested fault continuation point
+ ;;
+1: ld8 r18=[r17] // read *pte
+ ;;
+ mov b0=r29
+ tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
+(p6) br.cond.spnt page_fault
+ ;;
+ itc.d r18
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r19=[r17] // read *pte again and see if same
+ mov r20=PAGE_SHIFT<<2 // setup page size for purge
+ ;;
+ cmp.ne p7,p0=r18,r19
+ ;;
+(p7) ptc.l r16,r20
+#endif
+ mov pr=r31,-1
+ rfi
+__end_dtlb_miss_handler__
+
+// nested_dtlb_miss
+__begin_nested_dtlb_miss_handler__
+ rsm psr.dt // switch to using physical data addressing
+ mov r19=IA64_KR(PT_BASE) // get the page table base address
+ shl r21=r16,3 // shift bit 60 into sign bit
+ mov r18=cr.itir
+ ;;
+ shr.u r17=r16,61 // get the region number into r17
+ extr.u r18=r18,2,6 // get the faulting page size
+ ;;
+ cmp.eq p6,p7=5,r17 // is faulting address in region 5?
+ add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
+ add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
+ ;;
+ shr.u r22=r16,r22
+ shr.u r18=r16,r18
+(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
+
+ srlz.d
+ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
+
+ .pred.rel "mutex", p6, p7
+(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+ ;;
+(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
+(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
+ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+ shr.u r18=r22,PUD_SHIFT // shift pud index into position
+#else
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+#endif
+ ;;
+ ld8 r17=[r17] // get *pgd (may be 0)
+ ;;
+(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=p[u|m]d_offset(pgd,addr)
+ ;;
+#ifdef CONFIG_PGTABLE_4
+(p7) ld8 r17=[r17] // get *pud (may be 0)
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) == NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
+ ;;
+#endif
+(p7) ld8 r17=[r17] // get *pmd (may be 0)
+ shr.u r19=r22,PAGE_SHIFT // shift pte index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) == NULL?
+ dep r17=r19,r17,3,(PAGE_SHIFT-3) // r17=pte_offset(pmd,addr);
+(p6) br.cond.spnt page_fault
+ mov b0=r30
+ br.sptk.many b0 // return to continuation point
+__end_nested_dtlb_miss_handler__
+
+// dirty bit
+__begin_dirty_bit_handler__
+ /*
+ * What we do here is to simply turn on the dirty bit in the PTE. We need to
+ * update both the page-table and the TLB entry. To efficiently access the PTE,
+ * we address it through the virtual page table. Most likely, the TLB entry for
+ * the relevant virtual page table page is still present in the TLB so we can
+ * normally do this without additional TLB misses. In case the necessary virtual
+ * page table TLB entry isn't present, we take a nested TLB miss hit where we look
+ * up the physical address of the L3 PTE and then continue at label 1 below.
+ */
+ mov r16=cr.ifa // get the address that caused the fault
+ movl r30=1f // load continuation point in case of nested fault
+ ;;
+ thash r17=r16 // compute virtual address of L3 PTE
+ mov r29=b0 // save b0 in case of nested fault
+ mov r31=pr // save pr
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only update if page is present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present
+ ;;
+(p6) itc.d r25 // install updated PTE
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+ itc.d r18 // install updated PTE
+#endif
+ mov pr=r31,-1 // restore pr
+ rfi
+__end_dirty_bit_handler__
+
+// iaccess bit
+__begin_iaccess_bit_handler__
+ // Like dirty bit handler, except for instruction access
+ mov r16=cr.ifa // get the address that caused the fault
+ movl r30=1f // load continuation point in case of nested fault
+ mov r31=pr // save predicates
+#ifdef CONFIG_ITANIUM
+ /*
+ * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
+ */
+ mov r17=cr.ipsr
+ ;;
+ mov r18=cr.iip
+ tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set?
+ ;;
+(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa
+#endif /* CONFIG_ITANIUM */
+ ;;
+ thash r17=r16 // compute virtual address of L3 PTE
+ mov r29=b0 // save b0 in case of nested fault)
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+1: ld8 r18=[r17]
+ ;;
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_A,r18 // set the accessed bit
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only if page present
+ ;;
+(p6) itc.i r25 // install updated PTE
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else /* !CONFIG_SMP */
+ ;;
+1: ld8 r18=[r17]
+ ;;
+ or r18=_PAGE_A,r18 // set the accessed bit
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+ itc.i r18 // install updated PTE
+#endif /* !CONFIG_SMP */
+ mov pr=r31,-1
+ rfi
+__end_iaccess_bit_handler__
+
+// daccess bit
+__begin_daccess_bit_handler__
+ // Like dirty bit handler, except for data access
+ mov r16=cr.ifa // get the address that caused the fault
+ movl r30=1f // load continuation point in case of nested fault
+ ;;
+ thash r17=r16 // compute virtual address of L3 PTE
+ mov r31=pr
+ mov r29=b0 // save b0 in case of nested fault)
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_A,r18 // set the dirty bit
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page is present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only if page is present
+ ;;
+(p6) itc.d r25 // install updated PTE
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+ ;;
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) ptc.l r16,r24
+ mov ar.ccv=r28
+#else
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ or r18=_PAGE_A,r18 // set the accessed bit
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+ itc.d r18 // install updated PTE
+#endif
+ mov b0=r29 // restore b0
+ mov pr=r31,-1
+ rfi
+__end_daccess_bit_handler__
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/Makefile
===================================================================
--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/arch/ia64/kernel/Makefile 2006-05-05 10:06:54.000000000 +1000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/Makefile 2006-05-05 10:09:38.000000000 +1000
@@ -59,3 +59,8 @@
# We must build gate.so before we can assemble it.
# Note: kbuild does not track this dependency due to usage of .incbin
$(obj)/gate-data.o: $(obj)/gate.so
+
+# The real ivt.S needs to be built
+AFLAGS_ivt.o += -I$(srctree)/arch/ia64/kernel
+$(obj)/ivt.S: $(src)/ivt.S.in $(src)/ivt-sfvhpt.in
+ $(srctree)/arch/ia64/scripts/merge.py $@ $^
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [RFC 2/6] LVHPT - Create ivt.S dyanamically
From: Ian Wienand @ 2006-05-10 3:42 UTC (permalink / raw)
To: linux-ia64; +Cc: linux-mm, Ian Wienand
In-Reply-To: <20060510034206.17792.82504.sendpatchset@wagner.orchestra.cse.unsw.EDU.AU>
LVHPT ivt break apart
Create a script to dynamically create ivt.S. Pull out code from ivt.S
into a template file. The template(s) are then inserted back into
ivt.S at build time.
This approach avoids
- replicating the entire file
- #including a multitude of smaller files
- using CPP defines (which makes editing assembly hard)
- using assembler macros, which can be confusing as you do not get
context
Signed-Off-By: Ian Wienand <ianw@gelato.unsw.edu.au>
---
kernel/Makefile | 5
kernel/ivt-sfvhpt.in | 444 +++++++++++++++++
kernel/ivt.S.in | 1324 +++++++++++++++++++++++++++++++++++++++++++++++++++
scripts/merge.py | 58 ++
4 files changed, 1831 insertions(+)
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/scripts/merge.py
=================================--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/scripts/merge.py 2006-05-05 10:09:38.000000000 +1000
@@ -0,0 +1,58 @@
+#!/usr/bin/env python2.4
+# nb. requires python2.4 for string templating
+#
+# Usage: merge.py output template code
+#
+# merge the code in 'code' into 'template', writing out to 'output'
+#
+# Anything between lines __begin_name__ and __end_name__ in 'code'
+# gets inserted into $name in 'template'.
+#
+# Ian Wienand <ianw@gelato.unsw.edu.au>
+#
+import os
+import sys
+from string import Template
+
+if len(sys.argv) != 4:
+ print "Usage: %s output template code" % sys.argv[0]
+ sys.exit(2)
+
+print "Merging %s and template %s to %s" % (sys.argv[2], sys.argv[3], sys.argv[1])
+
+# bring the code file into a dictionary
+# anything between lines __begin_name__ and __end_name__ goes into
+# a dictionary entry of name
+template_dictionary = {}
+am_processing = False
+current_template = ""
+current_template_name = ""
+for line in open(sys.argv[3], 'r').readlines():
+
+ if am_processing:
+ # if this line is the end, stop
+ # XXX check this end is actually the name we are processing
+ if line[:6] = "__end_":
+ template_dictionary[current_template_name] = current_template
+ am_processing = False
+ print "... done"
+ continue
+ # otherwise, add this line to the current template
+ current_template += line
+ continue
+ # if we got here, we are not processing
+ if line[:8] = "__begin_":
+ am_processing = True
+ current_template_name = line[8:-3] #newline
+ print "Processing %s" % (current_template_name),
+ current_template = ""
+ continue
+ # this is some random line
+ continue
+
+#now open the file where we put these templates
+template = Template(open(sys.argv[2],'r').read())
+
+#finally, substitute them all in
+output = open(sys.argv[1],'w')
+output.write(template.substitute(template_dictionary))
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt.S.in
=================================--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt.S.in 2006-05-05 10:09:38.000000000 +1000
@@ -0,0 +1,1324 @@
+/*
+ * arch/ia64/kernel/ivt.S
+ *
+ * Copyright (C) 1998-2001, 2003, 2005 Hewlett-Packard Co
+ * Stephane Eranian <eranian@hpl.hp.com>
+ * David Mosberger <davidm@hpl.hp.com>
+ * Copyright (C) 2000, 2002-2003 Intel Co
+ * Asit Mallick <asit.k.mallick@intel.com>
+ * Suresh Siddha <suresh.b.siddha@intel.com>
+ * Kenneth Chen <kenneth.w.chen@intel.com>
+ * Fenghua Yu <fenghua.yu@intel.com>
+ *
+ * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling for SMP
+ * 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB handler now uses virtual PT.
+ */
+/*
+ * This file defines the interruption vector table used by the CPU.
+ * It does not include one entry per possible cause of interruption.
+ *
+ * The first 20 entries of the table contain 64 bundles each while the
+ * remaining 48 entries contain only 16 bundles each.
+ *
+ * The 64 bundles are used to allow inlining the whole handler for critical
+ * interruptions like TLB misses.
+ *
+ * For each entry, the comment is as follows:
+ *
+ * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ * entry offset ----/ / / / /
+ * entry number ---------/ / / /
+ * size of the entry -------------/ / /
+ * vector name -------------------------------------/ /
+ * interruptions triggering this vector ----------------------/
+ *
+ * The table is 32KB in size and must be aligned on 32KB boundary.
+ * (The CPU ignores the 15 lower bits of the address)
+ *
+ * Table is based upon EAS2.6 (Oct 1999)
+ */
+
+#include <linux/config.h>
+
+#include <asm/asmmacro.h>
+#include <asm/break.h>
+#include <asm/ia32.h>
+#include <asm/kregs.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+
+#if 1
+# define PSR_DEFAULT_BITS psr.ac
+#else
+# define PSR_DEFAULT_BITS 0
+#endif
+
+#if 0
+ /*
+ * This lets you track the last eight faults that occurred on the CPU. Make sure ar.k2 isn't
+ * needed for something else before enabling this...
+ */
+# define DBG_FAULT(i) mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16
+#else
+# define DBG_FAULT(i)
+#endif
+
+#include "minstate.h"
+
+#define FAULT(n) \
+ mov r31=pr; \
+ mov r19=n;; /* prepare to save predicates */ \
+ br.sptk.many dispatch_to_fault_handler
+
+ .section .text.ivt,"ax"
+
+ .align 32768 // align on 32KB boundary
+ .global ia64_ivt
+ia64_ivt:
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
+ENTRY(vhpt_miss)
+ DBG_FAULT(0)
+ /*
+ * The VHPT vector is invoked when the TLB entry for the virtual page table
+ * is missing. This happens only as a result of a previous
+ * (the "original") TLB miss, which may either be caused by an instruction
+ * fetch or a data access (or non-access).
+ *
+ * What we do here is normal TLB miss handing for the _original_ miss,
+ * followed by inserting the TLB entry for the virtual page table page
+ * that the VHPT walker was attempting to access. The latter gets
+ * inserted as long as page table entry above pte level have valid
+ * mappings for the faulting address. The TLB entry for the original
+ * miss gets inserted only if the pte entry indicates that the page is
+ * present.
+ *
+ * do_page_fault gets invoked in the following cases:
+ * - the faulting virtual address uses unimplemented address bits
+ * - the faulting virtual address has no valid page table mapping
+ */
+$vhpt_miss_handler
+END(vhpt_miss)
+
+ .org ia64_ivt+0x400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
+ENTRY(itlb_miss)
+ DBG_FAULT(1)
+ /*
+ * The ITLB handler accesses the PTE via the virtually mapped linear
+ * page table. If a nested TLB miss occurs, we switch into physical
+ * mode, walk the page table, and then re-execute the PTE read and
+ * go on normally after that.
+ */
+$itlb_miss_handler
+END(itlb_miss)
+
+ .org ia64_ivt+0x0800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
+ENTRY(dtlb_miss)
+ DBG_FAULT(2)
+ /*
+ * The DTLB handler accesses the PTE via the virtually mapped linear
+ * page table. If a nested TLB miss occurs, we switch into physical
+ * mode, walk the page table, and then re-execute the PTE read and
+ * go on normally after that.
+ */
+$dtlb_miss_handler
+END(dtlb_miss)
+
+ .org ia64_ivt+0x0c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
+ENTRY(alt_itlb_miss)
+ DBG_FAULT(3)
+ mov r16=cr.ifa // get address that caused the TLB miss
+ movl r17=PAGE_KERNEL
+ mov r21=cr.ipsr
+ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+ mov r31=pr
+ ;;
+#ifdef CONFIG_DISABLE_VHPT
+ shr.u r22=r16,61 // get the region number into r21
+ ;;
+ cmp.gt p8,p0=6,r22 // user mode
+ ;;
+(p8) thash r17=r16
+ ;;
+(p8) mov cr.iha=r17
+(p8) mov r29° // save b0
+(p8) br.cond.dptk .itlb_fault
+#endif
+ extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
+ and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
+ shr.u r18=r16,57 // move address bit 61 to bit 4
+ ;;
+ andcm r18=0x10,r18 // bit 4=~address-bit(61)
+ cmp.ne p8,p0=r0,r23 // psr.cpl != 0?
+ or r19=r17,r19 // insert PTE control bits into r19
+ ;;
+ or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
+(p8) br.cond.spnt page_fault
+ ;;
+ itc.i r19 // insert the TLB entry
+ mov pr=r31,-1
+ rfi
+END(alt_itlb_miss)
+
+ .org ia64_ivt+0x1000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
+ENTRY(alt_dtlb_miss)
+ DBG_FAULT(4)
+ mov r16=cr.ifa // get address that caused the TLB miss
+ movl r17=PAGE_KERNEL
+ mov r20=cr.isr
+ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+ mov r21=cr.ipsr
+ mov r31=pr
+ ;;
+#ifdef CONFIG_DISABLE_VHPT
+ shr.u r22=r16,61 // get the region number into r21
+ ;;
+ cmp.gt p8,p0=6,r22 // access to region 0-5
+ ;;
+(p8) thash r17=r16
+ ;;
+(p8) mov cr.iha=r17
+(p8) mov r29° // save b0
+(p8) br.cond.dptk dtlb_fault
+#endif
+ extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
+ and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
+ tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
+ shr.u r18=r16,57 // move address bit 61 to bit 4
+ and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
+ tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
+ ;;
+ andcm r18=0x10,r18 // bit 4=~address-bit(61)
+ cmp.ne p8,p0=r0,r23
+(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
+(p8) br.cond.spnt page_fault
+
+ dep r21=-1,r21,IA64_PSR_ED_BIT,1
+ or r19=r19,r17 // insert PTE control bits into r19
+ ;;
+ or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
+(p6) mov cr.ipsr=r21
+ ;;
+(p7) itc.d r19 // insert the TLB entry
+ mov pr=r31,-1
+ rfi
+END(alt_dtlb_miss)
+
+ .org ia64_ivt+0x1400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
+ENTRY(nested_dtlb_miss)
+ /*
+ * In the absence of kernel bugs, we get here when the virtually mapped linear
+ * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
+ * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page
+ * table is missing, a nested TLB miss fault is triggered and control is
+ * transferred to this point. When this happens, we lookup the pte for the
+ * faulting address by walking the page table in physical mode and return to the
+ * continuation point passed in register r30 (or call page_fault if the address is
+ * not mapped).
+ *
+ * Input: r16: faulting address
+ * r29: saved b0
+ * r30: continuation address
+ * r31: saved pr
+ *
+ * Output: r17: physical address of PTE of faulting address
+ * r29: saved b0
+ * r30: continuation address
+ * r31: saved pr
+ *
+ * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared)
+ */
+$nested_dtlb_miss_handler
+END(nested_dtlb_miss)
+
+ .org ia64_ivt+0x1800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
+ENTRY(ikey_miss)
+ DBG_FAULT(6)
+ FAULT(6)
+END(ikey_miss)
+
+ //-----------------------------------------------------------------------------------
+ // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
+ENTRY(page_fault)
+ ssm psr.dt
+ ;;
+ srlz.i
+ ;;
+ SAVE_MIN_WITH_COVER
+ alloc r15=ar.pfs,0,0,3,0
+ mov out0=cr.ifa
+ mov out1=cr.isr
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collectin is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ movl r14=ia64_leave_kernel
+ ;;
+ SAVE_REST
+ mov rp=r14
+ ;;
+ adds out2\x16,r12 // out2 = pointer to pt_regs
+ br.call.sptk.many b6=ia64_do_page_fault // ignore return address
+END(page_fault)
+
+ .org ia64_ivt+0x1c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ENTRY(dkey_miss)
+ DBG_FAULT(7)
+ FAULT(7)
+END(dkey_miss)
+
+ .org ia64_ivt+0x2000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
+ENTRY(dirty_bit)
+ DBG_FAULT(8)
+$dirty_bit_handler
+END(dirty_bit)
+
+ .org ia64_ivt+0x2400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
+ENTRY(iaccess_bit)
+ DBG_FAULT(9)
+$iaccess_bit_handler
+END(iaccess_bit)
+
+ .org ia64_ivt+0x2800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
+ENTRY(daccess_bit)
+ DBG_FAULT(10)
+$daccess_bit_handler
+END(daccess_bit)
+
+ .org ia64_ivt+0x2c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
+ENTRY(break_fault)
+ /*
+ * The streamlined system call entry/exit paths only save/restore the initial part
+ * of pt_regs. This implies that the callers of system-calls must adhere to the
+ * normal procedure calling conventions.
+ *
+ * Registers to be saved & restored:
+ * CR registers: cr.ipsr, cr.iip, cr.ifs
+ * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr
+ * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15
+ * Registers to be restored only:
+ * r8-r11: output value from the system call.
+ *
+ * During system call exit, scratch registers (including r15) are modified/cleared
+ * to prevent leaking bits from kernel to user level.
+ */
+ DBG_FAULT(11)
+ mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc)
+ mov r29=cr.ipsr // M2 (12 cyc)
+ mov r31=pr // I0 (2 cyc)
+
+ mov r17=cr.iim // M2 (2 cyc)
+ mov.m r27=ar.rsc // M2 (12 cyc)
+ mov r18=__IA64_BREAK_SYSCALL // A
+
+ mov.m ar.rsc=0 // M2
+ mov.m r21=ar.fpsr // M2 (12 cyc)
+ mov r19¶ // I0 (2 cyc)
+ ;;
+ mov.m r23=ar.bspstore // M2 (12 cyc)
+ mov.m r24=ar.rnat // M2 (5 cyc)
+ mov.i r26=ar.pfs // I0 (2 cyc)
+
+ invala // M0|1
+ nop.m 0 // M
+ mov r20=r1 // A save r1
+
+ nop.m 0
+ movl r30=sys_call_table // X
+
+ mov r28=cr.iip // M2 (2 cyc)
+ cmp.eq p0,p7=r18,r17 // I0 is this a system call?
+(p7) br.cond.spnt non_syscall // B no ->
+ //
+ // From this point on, we are definitely on the syscall-path
+ // and we can use (non-banked) scratch registers.
+ //
+///////////////////////////////////////////////////////////////////////
+ mov r1=r16 // A move task-pointer to "addl"-addressable reg
+ mov r2=r16 // A setup r2 for ia64_syscall_setup
+ add r9=TI_FLAGS+IA64_TASK_SIZE,r16 // A r9 = ¤t_thread_info()->flags
+
+ adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16
+ adds r15=-1024,r15 // A subtract 1024 from syscall number
+ mov r3=NR_syscalls - 1
+ ;;
+ ld1.bias r17=[r16] // M0|1 r17 = current->thread.on_ustack flag
+ ld4 r9=[r9] // M0|1 r9 = current_thread_info()->flags
+ extr.u r8=r29,41,2 // I0 extract ei field from cr.ipsr
+
+ shladd r30=r15,3,r30 // A r30 = sys_call_table + 8*(syscall-1024)
+ addl r22=IA64_RBS_OFFSET,r1 // A compute base of RBS
+ cmp.leu p6,p7=r15,r3 // A syscall number in range?
+ ;;
+
+ lfetch.fault.excl.nt1 [r22] // M0|1 prefetch RBS
+(p6) ld8 r30=[r30] // M0|1 load address of syscall entry point
+ tnat.nz.or p7,p0=r15 // I0 is syscall nr a NaT?
+
+ mov.m ar.bspstore=r22 // M2 switch to kernel RBS
+ cmp.eq p8,p9=2,r8 // A isr.ei=2?
+ ;;
+
+(p8) mov r8=0 // A clear ei to 0
+(p7) movl r30=sys_ni_syscall // X
+
+(p8) adds r28\x16,r28 // A switch cr.iip to next bundle
+(p9) adds r8=1,r8 // A increment ei to next slot
+ nop.i 0
+ ;;
+
+ mov.m r25=ar.unat // M2 (5 cyc)
+ dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr
+ adds r15\x1024,r15 // A restore original syscall number
+ //
+ // If any of the above loads miss in L1D, we'll stall here until
+ // the data arrives.
+ //
+///////////////////////////////////////////////////////////////////////
+ st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag
+ mov b6=r30 // I0 setup syscall handler branch reg early
+ cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already?
+
+ and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit
+ mov r18=ar.bsp // M2 (12 cyc)
+(pKStk) br.cond.spnt .break_fixup // B we're already in kernel-mode -- fix up RBS
+ ;;
+.back_from_break_fixup:
+(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A compute base of memory stack
+ cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited?
+ br.call.sptk.many b7=ia64_syscall_setup // B
+1:
+ mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
+ nop 0
+ bsw.1 // B (6 cyc) regs are saved, switch to bank 1
+ ;;
+
+ ssm psr.ic | PSR_DEFAULT_BITS // M2 now it's safe to re-enable intr.-collection
+ movl r3=ia64_ret_from_syscall // X
+ ;;
+
+ srlz.i // M0 ensure interruption collection is on
+ mov rp=r3 // I0 set the real return addr
+(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT
+
+(p15) ssm psr.i // M2 restore psr.i
+(p14) br.call.sptk.many b6¶ // B invoke syscall-handker (ignore return addr)
+ br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic
+ // NOT REACHED
+///////////////////////////////////////////////////////////////////////
+ // On entry, we optimistically assumed that we're coming from user-space.
+ // For the rare cases where a system-call is done from within the kernel,
+ // we fix things up at this point:
+.break_fixup:
+ add r1=-IA64_PT_REGS_SIZE,sp // A allocate space for pt_regs structure
+ mov ar.rnat=r24 // M2 restore kernel's AR.RNAT
+ ;;
+ mov ar.bspstore=r23 // M2 restore kernel's AR.BSPSTORE
+ br.cond.sptk .back_from_break_fixup
+END(break_fault)
+
+ .org ia64_ivt+0x3000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
+ENTRY(interrupt)
+ DBG_FAULT(12)
+ mov r31=pr // prepare to save predicates
+ ;;
+ SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ srlz.i // ensure everybody knows psr.ic is back on
+ ;;
+ SAVE_REST
+ ;;
+ MCA_RECOVER_RANGE(interrupt)
+ alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
+ mov out0=cr.ivr // pass cr.ivr as first arg
+ add out1\x16,sp // pass pointer to pt_regs as second arg
+ ;;
+ srlz.d // make sure we see the effect of cr.ivr
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+ br.call.sptk.many b6=ia64_handle_irq
+END(interrupt)
+
+ .org ia64_ivt+0x3400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3400 Entry 13 (size 64 bundles) Reserved
+ DBG_FAULT(13)
+ FAULT(13)
+
+ .org ia64_ivt+0x3800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3800 Entry 14 (size 64 bundles) Reserved
+ DBG_FAULT(14)
+ FAULT(14)
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ *
+ * ia64_syscall_setup() is a separate subroutine so that it can
+ * allocate stacked registers so it can safely demine any
+ * potential NaT values from the input registers.
+ *
+ * On entry:
+ * - executing on bank 0 or bank 1 register set (doesn't matter)
+ * - r1: stack pointer
+ * - r2: current task pointer
+ * - r3: preserved
+ * - r11: original contents (saved ar.pfs to be saved)
+ * - r12: original contents (sp to be saved)
+ * - r13: original contents (tp to be saved)
+ * - r15: original contents (syscall # to be saved)
+ * - r18: saved bsp (after switching to kernel stack)
+ * - r19: saved b6
+ * - r20: saved r1 (gp)
+ * - r21: saved ar.fpsr
+ * - r22: kernel's register backing store base (krbs_base)
+ * - r23: saved ar.bspstore
+ * - r24: saved ar.rnat
+ * - r25: saved ar.unat
+ * - r26: saved ar.pfs
+ * - r27: saved ar.rsc
+ * - r28: saved cr.iip
+ * - r29: saved cr.ipsr
+ * - r31: saved pr
+ * - b0: original contents (to be saved)
+ * On exit:
+ * - p10: TRUE if syscall is invoked with more than 8 out
+ * registers or r15's Nat is true
+ * - r1: kernel's gp
+ * - r3: preserved (same as on entry)
+ * - r8: -EINVAL if p10 is true
+ * - r12: points to kernel stack
+ * - r13: points to current task
+ * - r14: preserved (same as on entry)
+ * - p13: preserved
+ * - p15: TRUE if interrupts need to be re-enabled
+ * - ar.fpsr: set to kernel settings
+ * - b6: preserved (same as on entry)
+ */
+GLOBAL_ENTRY(ia64_syscall_setup)
+#if PT(B6) != 0
+# error This code assumes that b6 is the first field in pt_regs.
+#endif
+ st8 [r1]=r19 // save b6
+ add r16=PT(CR_IPSR),r1 // initialize first base pointer
+ add r17=PT(R11),r1 // initialize second base pointer
+ ;;
+ alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable
+ st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr
+ tnat.nz p8,p0=in0
+
+ st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11
+ tnat.nz p9,p0=in1
+(pKStk) mov r18=r0 // make sure r18 isn't NaT
+ ;;
+
+ st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs
+ st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip
+ mov r28° // save b0 (2 cyc)
+ ;;
+
+ st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat
+ dep r19=0,r19,38,26 // clear all bits but 0..37 [I0]
+(p8) mov in0=-1
+ ;;
+
+ st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs
+ extr.u r11=r19,7,7 // I0 // get sol of ar.pfs
+ and r8=0x7f,r19 // A // get sof of ar.pfs
+
+ st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc
+ tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0
+(p9) mov in1=-1
+ ;;
+
+(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8
+ tnat.nz p10,p0=in2
+ add r11=8,r11
+ ;;
+(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field
+(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field
+ tnat.nz p11,p0=in3
+ ;;
+(p10) mov in2=-1
+ tnat.nz p12,p0=in4 // [I0]
+(p11) mov in3=-1
+ ;;
+(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat
+(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore
+ shl r18=r18,16 // compute ar.rsc to be used for "loadrs"
+ ;;
+ st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates
+ st8 [r17]=r28,PT(R1)-PT(B0) // save b0
+ tnat.nz p13,p0=in5 // [I0]
+ ;;
+ st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs"
+ st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1
+(p12) mov in4=-1
+ ;;
+
+.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12
+.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13
+(p13) mov in5=-1
+ ;;
+ st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr
+ tnat.nz p13,p0=in6
+ cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8
+ ;;
+ mov r8=1
+(p9) tnat.nz p10,p0=r15
+ adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch)
+
+ st8.spill [r17]=r15 // save r15
+ tnat.nz p8,p0=in7
+ nop.i 0
+
+ mov r13=r2 // establish `current'
+ movl r1=__gp // establish kernel global pointer
+ ;;
+ st8 [r16]=r8 // ensure pt_regs.r8 != 0 (see handle_syscall_error)
+(p13) mov in6=-1
+(p8) mov in7=-1
+
+ cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
+ movl r17=FPSR_DEFAULT
+ ;;
+ mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value
+(p10) mov r8=-EINVAL
+ br.ret.sptk.many b7
+END(ia64_syscall_setup)
+
+ .org ia64_ivt+0x3c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3c00 Entry 15 (size 64 bundles) Reserved
+ DBG_FAULT(15)
+ FAULT(15)
+
+ /*
+ * Squatting in this space ...
+ *
+ * This special case dispatcher for illegal operation faults allows preserved
+ * registers to be modified through a callback function (asm only) that is handed
+ * back from the fault handler in r8. Up to three arguments can be passed to the
+ * callback function by returning an aggregate with the callback as its first
+ * element, followed by the arguments.
+ */
+ENTRY(dispatch_illegal_op_fault)
+ .prologue
+ .body
+ SAVE_MIN_WITH_COVER
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ ;;
+ alloc r14=ar.pfs,0,0,1,0 // must be first in insn group
+ mov out0=ar.ec
+ ;;
+ SAVE_REST
+ PT_REGS_UNWIND_INFO(0)
+ ;;
+ br.call.sptk.many rp=ia64_illegal_op_fault
+.ret0: ;;
+ alloc r14=ar.pfs,0,0,3,0 // must be first in insn group
+ mov out0=r9
+ mov out1=r10
+ mov out2=r11
+ movl r15=ia64_leave_kernel
+ ;;
+ mov rp=r15
+ mov b6=r8
+ ;;
+ cmp.ne p6,p0=0,r8
+(p6) br.call.dpnt.many b6¶ // call returns to ia64_leave_kernel
+ br.sptk.many ia64_leave_kernel
+END(dispatch_illegal_op_fault)
+
+ .org ia64_ivt+0x4000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4000 Entry 16 (size 64 bundles) Reserved
+ DBG_FAULT(16)
+ FAULT(16)
+
+ .org ia64_ivt+0x4400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4400 Entry 17 (size 64 bundles) Reserved
+ DBG_FAULT(17)
+ FAULT(17)
+
+ENTRY(non_syscall)
+ mov ar.rsc=r27 // restore ar.rsc before SAVE_MIN_WITH_COVER
+ ;;
+ SAVE_MIN_WITH_COVER
+
+ // There is no particular reason for this code to be here, other than that
+ // there happens to be space here that would go unused otherwise. If this
+ // fault ever gets "unreserved", simply moved the following code to a more
+ // suitable spot...
+
+ alloc r14=ar.pfs,0,0,2,0
+ mov out0=cr.iim
+ add out1\x16,sp
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ movl r15=ia64_leave_kernel
+ ;;
+ SAVE_REST
+ mov rp=r15
+ ;;
+ br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr
+END(non_syscall)
+
+ .org ia64_ivt+0x4800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4800 Entry 18 (size 64 bundles) Reserved
+ DBG_FAULT(18)
+ FAULT(18)
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ */
+
+ENTRY(dispatch_unaligned_handler)
+ SAVE_MIN_WITH_COVER
+ ;;
+ alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
+ mov out0=cr.ifa
+ adds out1\x16,sp
+
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ SAVE_REST
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+ br.sptk.many ia64_prepare_handle_unaligned
+END(dispatch_unaligned_handler)
+
+ .org ia64_ivt+0x4c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4c00 Entry 19 (size 64 bundles) Reserved
+ DBG_FAULT(19)
+ FAULT(19)
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ */
+
+ENTRY(dispatch_to_fault_handler)
+ /*
+ * Input:
+ * psr.ic: off
+ * r19: fault vector number (e.g., 24 for General Exception)
+ * r31: contains saved predicates (pr)
+ */
+ SAVE_MIN_WITH_COVER_R19
+ alloc r14=ar.pfs,0,0,5,0
+ mov out0=r15
+ mov out1=cr.isr
+ mov out2=cr.ifa
+ mov out3=cr.iim
+ mov out4=cr.itir
+ ;;
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ ;;
+ SAVE_REST
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+ br.call.sptk.many b6=ia64_fault
+END(dispatch_to_fault_handler)
+
+//
+// --- End of long entries, Beginning of short entries
+//
+
+ .org ia64_ivt+0x5000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
+ENTRY(page_not_present)
+ DBG_FAULT(20)
+ mov r16=cr.ifa
+ rsm psr.dt
+ /*
+ * The Linux page fault handler doesn't expect non-present pages to be in
+ * the TLB. Flush the existing entry now, so we meet that expectation.
+ */
+ mov r17=PAGE_SHIFT<<2
+ ;;
+ ptc.l r16,r17
+ ;;
+ mov r31=pr
+ srlz.d
+ br.sptk.many page_fault
+END(page_not_present)
+
+ .org ia64_ivt+0x5100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
+ENTRY(key_permission)
+ DBG_FAULT(21)
+ mov r16=cr.ifa
+ rsm psr.dt
+ mov r31=pr
+ ;;
+ srlz.d
+ br.sptk.many page_fault
+END(key_permission)
+
+ .org ia64_ivt+0x5200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
+ENTRY(iaccess_rights)
+ DBG_FAULT(22)
+ mov r16=cr.ifa
+ rsm psr.dt
+ mov r31=pr
+ ;;
+ srlz.d
+ br.sptk.many page_fault
+END(iaccess_rights)
+
+ .org ia64_ivt+0x5300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
+ENTRY(daccess_rights)
+ DBG_FAULT(23)
+ mov r16=cr.ifa
+ rsm psr.dt
+ mov r31=pr
+ ;;
+ srlz.d
+ br.sptk.many page_fault
+END(daccess_rights)
+
+ .org ia64_ivt+0x5400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
+ENTRY(general_exception)
+ DBG_FAULT(24)
+ mov r16=cr.isr
+ mov r31=pr
+ ;;
+ cmp4.eq p6,p0=0,r16
+(p6) br.sptk.many dispatch_illegal_op_fault
+ ;;
+ mov r19$ // fault number
+ br.sptk.many dispatch_to_fault_handler
+END(general_exception)
+
+ .org ia64_ivt+0x5500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
+ENTRY(disabled_fp_reg)
+ DBG_FAULT(25)
+ rsm psr.dfh // ensure we can access fph
+ ;;
+ srlz.d
+ mov r31=pr
+ mov r19%
+ br.sptk.many dispatch_to_fault_handler
+END(disabled_fp_reg)
+
+ .org ia64_ivt+0x5600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
+ENTRY(nat_consumption)
+ DBG_FAULT(26)
+
+ mov r16=cr.ipsr
+ mov r17=cr.isr
+ mov r31=pr // save PR
+ ;;
+ and r18=0xf,r17 // r18 = cr.ipsr.code{3:0}
+ tbit.z p6,p0=r17,IA64_ISR_NA_BIT
+ ;;
+ cmp.ne.or p6,p0=IA64_ISR_CODE_LFETCH,r18
+ dep r16=-1,r16,IA64_PSR_ED_BIT,1
+(p6) br.cond.spnt 1f // branch if (cr.ispr.na = 0 || cr.ipsr.code{3:0} != LFETCH)
+ ;;
+ mov cr.ipsr=r16 // set cr.ipsr.na
+ mov pr=r31,-1
+ ;;
+ rfi
+
+1: mov pr=r31,-1
+ ;;
+ FAULT(26)
+END(nat_consumption)
+
+ .org ia64_ivt+0x5700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
+ENTRY(speculation_vector)
+ DBG_FAULT(27)
+ /*
+ * A [f]chk.[as] instruction needs to take the branch to the recovery code but
+ * this part of the architecture is not implemented in hardware on some CPUs, such
+ * as Itanium. Thus, in general we need to emulate the behavior. IIM contains
+ * the relative target (not yet sign extended). So after sign extending it we
+ * simply add it to IIP. We also need to reset the EI field of the IPSR to zero,
+ * i.e., the slot to restart into.
+ *
+ * cr.imm contains zero_ext(imm21)
+ */
+ mov r18=cr.iim
+ ;;
+ mov r17=cr.iip
+ shl r18=r18,43 // put sign bit in position (43d-21)
+ ;;
+
+ mov r16=cr.ipsr
+ shr r18=r18,39 // sign extend (39C-4)
+ ;;
+
+ add r17=r17,r18 // now add the offset
+ ;;
+ mov cr.iip=r17
+ dep r16=0,r16,41,2 // clear EI
+ ;;
+
+ mov cr.ipsr=r16
+ ;;
+
+ rfi // and go back
+END(speculation_vector)
+
+ .org ia64_ivt+0x5800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5800 Entry 28 (size 16 bundles) Reserved
+ DBG_FAULT(28)
+ FAULT(28)
+
+ .org ia64_ivt+0x5900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
+ENTRY(debug_vector)
+ DBG_FAULT(29)
+ FAULT(29)
+END(debug_vector)
+
+ .org ia64_ivt+0x5a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
+ENTRY(unaligned_access)
+ DBG_FAULT(30)
+ mov r31=pr // prepare to save predicates
+ ;;
+ br.sptk.many dispatch_unaligned_handler
+END(unaligned_access)
+
+ .org ia64_ivt+0x5b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
+ENTRY(unsupported_data_reference)
+ DBG_FAULT(31)
+ FAULT(31)
+END(unsupported_data_reference)
+
+ .org ia64_ivt+0x5c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
+ENTRY(floating_point_fault)
+ DBG_FAULT(32)
+ FAULT(32)
+END(floating_point_fault)
+
+ .org ia64_ivt+0x5d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
+ENTRY(floating_point_trap)
+ DBG_FAULT(33)
+ FAULT(33)
+END(floating_point_trap)
+
+ .org ia64_ivt+0x5e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
+ENTRY(lower_privilege_trap)
+ DBG_FAULT(34)
+ FAULT(34)
+END(lower_privilege_trap)
+
+ .org ia64_ivt+0x5f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
+ENTRY(taken_branch_trap)
+ DBG_FAULT(35)
+ FAULT(35)
+END(taken_branch_trap)
+
+ .org ia64_ivt+0x6000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
+ENTRY(single_step_trap)
+ DBG_FAULT(36)
+ FAULT(36)
+END(single_step_trap)
+
+ .org ia64_ivt+0x6100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6100 Entry 37 (size 16 bundles) Reserved
+ DBG_FAULT(37)
+ FAULT(37)
+
+ .org ia64_ivt+0x6200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6200 Entry 38 (size 16 bundles) Reserved
+ DBG_FAULT(38)
+ FAULT(38)
+
+ .org ia64_ivt+0x6300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6300 Entry 39 (size 16 bundles) Reserved
+ DBG_FAULT(39)
+ FAULT(39)
+
+ .org ia64_ivt+0x6400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6400 Entry 40 (size 16 bundles) Reserved
+ DBG_FAULT(40)
+ FAULT(40)
+
+ .org ia64_ivt+0x6500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6500 Entry 41 (size 16 bundles) Reserved
+ DBG_FAULT(41)
+ FAULT(41)
+
+ .org ia64_ivt+0x6600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6600 Entry 42 (size 16 bundles) Reserved
+ DBG_FAULT(42)
+ FAULT(42)
+
+ .org ia64_ivt+0x6700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6700 Entry 43 (size 16 bundles) Reserved
+ DBG_FAULT(43)
+ FAULT(43)
+
+ .org ia64_ivt+0x6800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6800 Entry 44 (size 16 bundles) Reserved
+ DBG_FAULT(44)
+ FAULT(44)
+
+ .org ia64_ivt+0x6900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
+ENTRY(ia32_exception)
+ DBG_FAULT(45)
+ FAULT(45)
+END(ia32_exception)
+
+ .org ia64_ivt+0x6a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
+ENTRY(ia32_intercept)
+ DBG_FAULT(46)
+#ifdef CONFIG_IA32_SUPPORT
+ mov r31=pr
+ mov r16=cr.isr
+ ;;
+ extr.u r17=r16,16,8 // get ISR.code
+ mov r18=ar.eflag
+ mov r19=cr.iim // old eflag value
+ ;;
+ cmp.ne p6,p0=2,r17
+(p6) br.cond.spnt 1f // not a system flag fault
+ xor r16=r18,r19
+ ;;
+ extr.u r17=r16,18,1 // get the eflags.ac bit
+ ;;
+ cmp.eq p6,p0=0,r17
+(p6) br.cond.spnt 1f // eflags.ac bit didn't change
+ ;;
+ mov pr=r31,-1 // restore predicate registers
+ rfi
+
+1:
+#endif // CONFIG_IA32_SUPPORT
+ FAULT(46)
+END(ia32_intercept)
+
+ .org ia64_ivt+0x6b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74)
+ENTRY(ia32_interrupt)
+ DBG_FAULT(47)
+#ifdef CONFIG_IA32_SUPPORT
+ mov r31=pr
+ br.sptk.many dispatch_to_ia32_handler
+#else
+ FAULT(47)
+#endif
+END(ia32_interrupt)
+
+ .org ia64_ivt+0x6c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6c00 Entry 48 (size 16 bundles) Reserved
+ DBG_FAULT(48)
+ FAULT(48)
+
+ .org ia64_ivt+0x6d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6d00 Entry 49 (size 16 bundles) Reserved
+ DBG_FAULT(49)
+ FAULT(49)
+
+ .org ia64_ivt+0x6e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6e00 Entry 50 (size 16 bundles) Reserved
+ DBG_FAULT(50)
+ FAULT(50)
+
+ .org ia64_ivt+0x6f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6f00 Entry 51 (size 16 bundles) Reserved
+ DBG_FAULT(51)
+ FAULT(51)
+
+ .org ia64_ivt+0x7000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7000 Entry 52 (size 16 bundles) Reserved
+ DBG_FAULT(52)
+ FAULT(52)
+
+ .org ia64_ivt+0x7100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7100 Entry 53 (size 16 bundles) Reserved
+ DBG_FAULT(53)
+ FAULT(53)
+
+ .org ia64_ivt+0x7200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7200 Entry 54 (size 16 bundles) Reserved
+ DBG_FAULT(54)
+ FAULT(54)
+
+ .org ia64_ivt+0x7300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7300 Entry 55 (size 16 bundles) Reserved
+ DBG_FAULT(55)
+ FAULT(55)
+
+ .org ia64_ivt+0x7400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7400 Entry 56 (size 16 bundles) Reserved
+ DBG_FAULT(56)
+ FAULT(56)
+
+ .org ia64_ivt+0x7500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7500 Entry 57 (size 16 bundles) Reserved
+ DBG_FAULT(57)
+ FAULT(57)
+
+ .org ia64_ivt+0x7600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7600 Entry 58 (size 16 bundles) Reserved
+ DBG_FAULT(58)
+ FAULT(58)
+
+ .org ia64_ivt+0x7700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7700 Entry 59 (size 16 bundles) Reserved
+ DBG_FAULT(59)
+ FAULT(59)
+
+ .org ia64_ivt+0x7800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7800 Entry 60 (size 16 bundles) Reserved
+ DBG_FAULT(60)
+ FAULT(60)
+
+ .org ia64_ivt+0x7900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7900 Entry 61 (size 16 bundles) Reserved
+ DBG_FAULT(61)
+ FAULT(61)
+
+ .org ia64_ivt+0x7a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7a00 Entry 62 (size 16 bundles) Reserved
+ DBG_FAULT(62)
+ FAULT(62)
+
+ .org ia64_ivt+0x7b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7b00 Entry 63 (size 16 bundles) Reserved
+ DBG_FAULT(63)
+ FAULT(63)
+
+ .org ia64_ivt+0x7c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7c00 Entry 64 (size 16 bundles) Reserved
+ DBG_FAULT(64)
+ FAULT(64)
+
+ .org ia64_ivt+0x7d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7d00 Entry 65 (size 16 bundles) Reserved
+ DBG_FAULT(65)
+ FAULT(65)
+
+ .org ia64_ivt+0x7e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7e00 Entry 66 (size 16 bundles) Reserved
+ DBG_FAULT(66)
+ FAULT(66)
+
+ .org ia64_ivt+0x7f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7f00 Entry 67 (size 16 bundles) Reserved
+ DBG_FAULT(67)
+ FAULT(67)
+
+#ifdef CONFIG_IA32_SUPPORT
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ */
+
+ // IA32 interrupt entry point
+
+ENTRY(dispatch_to_ia32_handler)
+ SAVE_MIN
+ ;;
+ mov r14=cr.isr
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i
+ adds r3=8,r2 // Base pointer for SAVE_REST
+ ;;
+ SAVE_REST
+ ;;
+ mov r15=0x80
+ shr r14=r14,16 // Get interrupt number
+ ;;
+ cmp.ne p6,p0=r14,r15
+(p6) br.call.dpnt.many b6=non_ia32_syscall
+
+ adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions
+ adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
+ ;;
+ cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
+ ld8 r8=[r14] // get r8
+ ;;
+ st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP)
+ ;;
+ alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
+ ;;
+ ld4 r8=[r14],8 // r8 = eax (syscall number)
+ mov r15=IA32_NR_syscalls
+ ;;
+ cmp.ltu.unc p6,p7=r8,r15
+ ld4 out1=[r14],8 // r9 = ecx
+ ;;
+ ld4 out2=[r14],8 // r10 = edx
+ ;;
+ ld4 out0=[r14] // r11 = ebx
+ adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp
+ ;;
+ ld4 out5=[r14],PT(R14)-PT(R13) // r13 = ebp
+ ;;
+ ld4 out3=[r14],PT(R15)-PT(R14) // r14 = esi
+ adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
+ ;;
+ ld4 out4=[r14] // r15 = edi
+ movl r16=ia32_syscall_table
+ ;;
+(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
+ ld4 r2=[r2] // r2 = current_thread_info()->flags
+ ;;
+ ld8 r16=[r16]
+ and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit
+ ;;
+ mov b6=r16
+ movl r15=ia32_ret_from_syscall
+ cmp.eq p8,p0=r2,r0
+ ;;
+ mov rp=r15
+(p8) br.call.sptk.many b6¶
+ br.cond.sptk ia32_trace_syscall
+
+non_ia32_syscall:
+ alloc r15=ar.pfs,0,0,2,0
+ mov out0=r14 // interrupt #
+ add out1\x16,sp // pointer to pt_regs
+ ;; // avoid WAW on CFM
+ br.call.sptk.many rp=ia32_bad_interrupt
+.ret1: movl r15=ia64_leave_kernel
+ ;;
+ mov rp=r15
+ br.ret.sptk.many rp
+END(dispatch_to_ia32_handler)
+
+#endif /* CONFIG_IA32_SUPPORT */
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt-sfvhpt.in
=================================--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt-sfvhpt.in 2006-05-05 10:09:38.000000000 +1000
@@ -0,0 +1,444 @@
+/*
+ * This file is to be processed and inserted into the actual ivt.S
+ *
+ * Any variable $name in ivt.S will be replaced with what is between
+ *__begin_name__ and __end_name__ in this file.
+ *
+ */
+
+//vhpt_miss
+__begin_vhpt_miss_handler__
+ mov r16=cr.ifa // get address that caused the TLB miss
+#ifdef CONFIG_HUGETLB_PAGE
+ movl r18=PAGE_SHIFT
+ mov r25=cr.itir
+#endif
+ ;;
+ rsm psr.dt // use physical addressing for data
+ mov r31=pr // save the predicate registers
+ mov r19=IA64_KR(PT_BASE) // get page table base address
+ shl r21=r16,3 // shift bit 60 into sign bit
+ shr.u r17=r16,61 // get the region number into r17
+ ;;
+ shr.u r22=r21,3
+#ifdef CONFIG_HUGETLB_PAGE
+ extr.u r26=r25,2,6
+ ;;
+ cmp.ne p8,p0=r18,r26
+ sub r27=r26,r18
+ ;;
+(p8) dep r25=r18,r25,2,6
+(p8) shr r22=r22,r27
+#endif
+ ;;
+ cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
+ shr.u r18=r22,PGDIR_SHIFT // get bottom portion of pgd index bit
+ ;;
+(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
+
+ srlz.d
+ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
+
+ .pred.rel "mutex", p6, p7
+(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+ ;;
+(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
+(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
+ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+ shr.u r28=r22,PUD_SHIFT // shift pud index into position
+#else
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+#endif
+ ;;
+ ld8 r17=[r17] // get *pgd (may be 0)
+ ;;
+(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) = NULL?
+#ifdef CONFIG_PGTABLE_4
+ dep r28=r28,r17,3,(PAGE_SHIFT-3) // r28=pud_offset(pgd,addr)
+ ;;
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+(p7) ld8 r29=[r28] // get *pud (may be 0)
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r29,r0 // was pud_present(*pud) = NULL?
+ dep r17=r18,r29,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
+#else
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pgd,addr)
+#endif
+ ;;
+(p7) ld8 r20=[r17] // get *pmd (may be 0)
+ shr.u r19=r22,PAGE_SHIFT // shift pte index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r20,r0 // was pmd_present(*pmd) = NULL?
+ dep r21=r19,r20,3,(PAGE_SHIFT-3) // r21=pte_offset(pmd,addr)
+ ;;
+(p7) ld8 r18=[r21] // read *pte
+ mov r19=cr.isr // cr.isr bit 32 tells us if this is an insn miss
+ ;;
+(p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared?
+ mov r22=cr.iha // get the VHPT address that caused the TLB miss
+ ;; // avoid RAW on p7
+(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss?
+ dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address
+ ;;
+(p10) itc.i r18 // insert the instruction TLB entry
+(p11) itc.d r18 // insert the data TLB entry
+(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
+ mov cr.ifa=r22
+
+#ifdef CONFIG_HUGETLB_PAGE
+(p8) mov cr.itir=r25 // change to default page-size for VHPT
+#endif
+
+ /*
+ * Now compute and insert the TLB entry for the virtual page table. We never
+ * execute in a page table page so there is no need to set the exception deferral
+ * bit.
+ */
+ adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
+ ;;
+(p7) itc.d r24
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ /*
+ * Re-check pagetable entry. If they changed, we may have received a ptc.g
+ * between reading the pagetable and the "itc". If so, flush the entry we
+ * inserted and retry. At this point, we have:
+ *
+ * r28 = equivalent of pud_offset(pgd, ifa)
+ * r17 = equivalent of pmd_offset(pud, ifa)
+ * r21 = equivalent of pte_offset(pmd, ifa)
+ *
+ * r29 = *pud
+ * r20 = *pmd
+ * r18 = *pte
+ */
+ ld8 r25=[r21] // read *pte again
+ ld8 r26=[r17] // read *pmd again
+#ifdef CONFIG_PGTABLE_4
+ ld8 r19=[r28] // read *pud again
+#endif
+ cmp.ne p6,p7=r0,r0
+ ;;
+ cmp.ne.or.andcm p6,p7=r26,r20 // did *pmd change
+#ifdef CONFIG_PGTABLE_4
+ cmp.ne.or.andcm p6,p7=r19,r29 // did *pud change
+#endif
+ mov r27=PAGE_SHIFT<<2
+ ;;
+(p6) ptc.l r22,r27 // purge PTE page translation
+(p7) cmp.ne.or.andcm p6,p7=r25,r18 // did *pte change
+ ;;
+(p6) ptc.l r16,r27 // purge translation
+#endif
+
+ mov pr=r31,-1 // restore predicate registers
+ rfi
+__end_vhpt_miss_handler__
+
+// itlb_miss
+__begin_itlb_miss_handler__
+ mov r16=cr.ifa // get virtual address
+ mov r29° // save b0
+ mov r31=pr // save predicates
+.itlb_fault:
+ mov r17=cr.iha // get virtual address of PTE
+ movl r30\x1f // load nested fault continuation point
+ ;;
+1: ld8 r18=[r17] // read *pte
+ ;;
+ mov b0=r29
+ tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
+(p6) br.cond.spnt page_fault
+ ;;
+ itc.i r18
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r19=[r17] // read *pte again and see if same
+ mov r20=PAGE_SHIFT<<2 // setup page size for purge
+ ;;
+ cmp.ne p7,p0=r18,r19
+ ;;
+(p7) ptc.l r16,r20
+#endif
+ mov pr=r31,-1
+ rfi
+__end_itlb_miss_handler__
+
+// dtlb_miss
+__begin_dtlb_miss_handler__
+ mov r16=cr.ifa // get virtual address
+ mov r29° // save b0
+ mov r31=pr // save predicates
+dtlb_fault:
+ mov r17=cr.iha // get virtual address of PTE
+ movl r30\x1f // load nested fault continuation point
+ ;;
+1: ld8 r18=[r17] // read *pte
+ ;;
+ mov b0=r29
+ tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
+(p6) br.cond.spnt page_fault
+ ;;
+ itc.d r18
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r19=[r17] // read *pte again and see if same
+ mov r20=PAGE_SHIFT<<2 // setup page size for purge
+ ;;
+ cmp.ne p7,p0=r18,r19
+ ;;
+(p7) ptc.l r16,r20
+#endif
+ mov pr=r31,-1
+ rfi
+__end_dtlb_miss_handler__
+
+// nested_dtlb_miss
+__begin_nested_dtlb_miss_handler__
+ rsm psr.dt // switch to using physical data addressing
+ mov r19=IA64_KR(PT_BASE) // get the page table base address
+ shl r21=r16,3 // shift bit 60 into sign bit
+ mov r18=cr.itir
+ ;;
+ shr.u r17=r16,61 // get the region number into r17
+ extr.u r18=r18,2,6 // get the faulting page size
+ ;;
+ cmp.eq p6,p7=5,r17 // is faulting address in region 5?
+ add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
+ add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
+ ;;
+ shr.u r22=r16,r22
+ shr.u r18=r16,r18
+(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
+
+ srlz.d
+ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
+
+ .pred.rel "mutex", p6, p7
+(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+ ;;
+(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
+(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
+ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+ shr.u r18=r22,PUD_SHIFT // shift pud index into position
+#else
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+#endif
+ ;;
+ ld8 r17=[r17] // get *pgd (may be 0)
+ ;;
+(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) = NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=p[u|m]d_offset(pgd,addr)
+ ;;
+#ifdef CONFIG_PGTABLE_4
+(p7) ld8 r17=[r17] // get *pud (may be 0)
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) = NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
+ ;;
+#endif
+(p7) ld8 r17=[r17] // get *pmd (may be 0)
+ shr.u r19=r22,PAGE_SHIFT // shift pte index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) = NULL?
+ dep r17=r19,r17,3,(PAGE_SHIFT-3) // r17=pte_offset(pmd,addr);
+(p6) br.cond.spnt page_fault
+ mov b0=r30
+ br.sptk.many b0 // return to continuation point
+__end_nested_dtlb_miss_handler__
+
+// dirty bit
+__begin_dirty_bit_handler__
+ /*
+ * What we do here is to simply turn on the dirty bit in the PTE. We need to
+ * update both the page-table and the TLB entry. To efficiently access the PTE,
+ * we address it through the virtual page table. Most likely, the TLB entry for
+ * the relevant virtual page table page is still present in the TLB so we can
+ * normally do this without additional TLB misses. In case the necessary virtual
+ * page table TLB entry isn't present, we take a nested TLB miss hit where we look
+ * up the physical address of the L3 PTE and then continue at label 1 below.
+ */
+ mov r16=cr.ifa // get the address that caused the fault
+ movl r30\x1f // load continuation point in case of nested fault
+ ;;
+ thash r17=r16 // compute virtual address of L3 PTE
+ mov r29° // save b0 in case of nested fault
+ mov r31=pr // save pr
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only update if page is present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present
+ ;;
+(p6) itc.d r25 // install updated PTE
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+ itc.d r18 // install updated PTE
+#endif
+ mov pr=r31,-1 // restore pr
+ rfi
+__end_dirty_bit_handler__
+
+// iaccess bit
+__begin_iaccess_bit_handler__
+ // Like dirty bit handler, except for instruction access
+ mov r16=cr.ifa // get the address that caused the fault
+ movl r30\x1f // load continuation point in case of nested fault
+ mov r31=pr // save predicates
+#ifdef CONFIG_ITANIUM
+ /*
+ * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
+ */
+ mov r17=cr.ipsr
+ ;;
+ mov r18=cr.iip
+ tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set?
+ ;;
+(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa
+#endif /* CONFIG_ITANIUM */
+ ;;
+ thash r17=r16 // compute virtual address of L3 PTE
+ mov r29° // save b0 in case of nested fault)
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+1: ld8 r18=[r17]
+ ;;
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_A,r18 // set the accessed bit
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only if page present
+ ;;
+(p6) itc.i r25 // install updated PTE
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else /* !CONFIG_SMP */
+ ;;
+1: ld8 r18=[r17]
+ ;;
+ or r18=_PAGE_A,r18 // set the accessed bit
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+ itc.i r18 // install updated PTE
+#endif /* !CONFIG_SMP */
+ mov pr=r31,-1
+ rfi
+__end_iaccess_bit_handler__
+
+// daccess bit
+__begin_daccess_bit_handler__
+ // Like dirty bit handler, except for data access
+ mov r16=cr.ifa // get the address that caused the fault
+ movl r30\x1f // load continuation point in case of nested fault
+ ;;
+ thash r17=r16 // compute virtual address of L3 PTE
+ mov r31=pr
+ mov r29° // save b0 in case of nested fault)
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_A,r18 // set the dirty bit
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page is present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only if page is present
+ ;;
+(p6) itc.d r25 // install updated PTE
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+ ;;
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) ptc.l r16,r24
+ mov ar.ccv=r28
+#else
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ or r18=_PAGE_A,r18 // set the accessed bit
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+ itc.d r18 // install updated PTE
+#endif
+ mov b0=r29 // restore b0
+ mov pr=r31,-1
+ rfi
+__end_daccess_bit_handler__
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/Makefile
=================================--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/arch/ia64/kernel/Makefile 2006-05-05 10:06:54.000000000 +1000
+++ linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/Makefile 2006-05-05 10:09:38.000000000 +1000
@@ -59,3 +59,8 @@
# We must build gate.so before we can assemble it.
# Note: kbuild does not track this dependency due to usage of .incbin
$(obj)/gate-data.o: $(obj)/gate.so
+
+# The real ivt.S needs to be built
+AFLAGS_ivt.o += -I$(srctree)/arch/ia64/kernel
+$(obj)/ivt.S: $(src)/ivt.S.in $(src)/ivt-sfvhpt.in
+ $(srctree)/arch/ia64/scripts/merge.py $@ $^
^ permalink raw reply
* [RFC 1/6] LVHPT - Remove static ivt.S
From: Ian Wienand @ 2006-05-10 3:42 UTC (permalink / raw)
To: linux-ia64; +Cc: linux-mm, Ian Wienand
In-Reply-To: <20060510034206.17792.82504.sendpatchset@wagner.orchestra.cse.unsw.EDU.AU>
LVHPT remove ivt.S
Remove ivt.S; it is dynamically generated.
Signed-Off-By: Ian Wienand <ianw@gelato.unsw.edu.au>
---
ivt.S | 1726 ------------------------------------------------------------------
1 file changed, 1726 deletions(-)
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt.S
===================================================================
--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/arch/ia64/kernel/ivt.S 2006-05-05 10:06:54.000000000 +1000
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,1726 +0,0 @@
-/*
- * arch/ia64/kernel/ivt.S
- *
- * Copyright (C) 1998-2001, 2003, 2005 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- * David Mosberger <davidm@hpl.hp.com>
- * Copyright (C) 2000, 2002-2003 Intel Co
- * Asit Mallick <asit.k.mallick@intel.com>
- * Suresh Siddha <suresh.b.siddha@intel.com>
- * Kenneth Chen <kenneth.w.chen@intel.com>
- * Fenghua Yu <fenghua.yu@intel.com>
- *
- * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling for SMP
- * 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB handler now uses virtual PT.
- */
-/*
- * This file defines the interruption vector table used by the CPU.
- * It does not include one entry per possible cause of interruption.
- *
- * The first 20 entries of the table contain 64 bundles each while the
- * remaining 48 entries contain only 16 bundles each.
- *
- * The 64 bundles are used to allow inlining the whole handler for critical
- * interruptions like TLB misses.
- *
- * For each entry, the comment is as follows:
- *
- * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
- * entry offset ----/ / / / /
- * entry number ---------/ / / /
- * size of the entry -------------/ / /
- * vector name -------------------------------------/ /
- * interruptions triggering this vector ----------------------/
- *
- * The table is 32KB in size and must be aligned on 32KB boundary.
- * (The CPU ignores the 15 lower bits of the address)
- *
- * Table is based upon EAS2.6 (Oct 1999)
- */
-
-#include <linux/config.h>
-
-#include <asm/asmmacro.h>
-#include <asm/break.h>
-#include <asm/ia32.h>
-#include <asm/kregs.h>
-#include <asm/asm-offsets.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/system.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/errno.h>
-
-#if 1
-# define PSR_DEFAULT_BITS psr.ac
-#else
-# define PSR_DEFAULT_BITS 0
-#endif
-
-#if 0
- /*
- * This lets you track the last eight faults that occurred on the CPU. Make sure ar.k2 isn't
- * needed for something else before enabling this...
- */
-# define DBG_FAULT(i) mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16
-#else
-# define DBG_FAULT(i)
-#endif
-
-#include "minstate.h"
-
-#define FAULT(n) \
- mov r31=pr; \
- mov r19=n;; /* prepare to save predicates */ \
- br.sptk.many dispatch_to_fault_handler
-
- .section .text.ivt,"ax"
-
- .align 32768 // align on 32KB boundary
- .global ia64_ivt
-ia64_ivt:
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
-ENTRY(vhpt_miss)
- DBG_FAULT(0)
- /*
- * The VHPT vector is invoked when the TLB entry for the virtual page table
- * is missing. This happens only as a result of a previous
- * (the "original") TLB miss, which may either be caused by an instruction
- * fetch or a data access (or non-access).
- *
- * What we do here is normal TLB miss handing for the _original_ miss,
- * followed by inserting the TLB entry for the virtual page table page
- * that the VHPT walker was attempting to access. The latter gets
- * inserted as long as page table entry above pte level have valid
- * mappings for the faulting address. The TLB entry for the original
- * miss gets inserted only if the pte entry indicates that the page is
- * present.
- *
- * do_page_fault gets invoked in the following cases:
- * - the faulting virtual address uses unimplemented address bits
- * - the faulting virtual address has no valid page table mapping
- */
- mov r16=cr.ifa // get address that caused the TLB miss
-#ifdef CONFIG_HUGETLB_PAGE
- movl r18=PAGE_SHIFT
- mov r25=cr.itir
-#endif
- ;;
- rsm psr.dt // use physical addressing for data
- mov r31=pr // save the predicate registers
- mov r19=IA64_KR(PT_BASE) // get page table base address
- shl r21=r16,3 // shift bit 60 into sign bit
- shr.u r17=r16,61 // get the region number into r17
- ;;
- shr.u r22=r21,3
-#ifdef CONFIG_HUGETLB_PAGE
- extr.u r26=r25,2,6
- ;;
- cmp.ne p8,p0=r18,r26
- sub r27=r26,r18
- ;;
-(p8) dep r25=r18,r25,2,6
-(p8) shr r22=r22,r27
-#endif
- ;;
- cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
- shr.u r18=r22,PGDIR_SHIFT // get bottom portion of pgd index bit
- ;;
-(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
-
- srlz.d
- LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
-
- .pred.rel "mutex", p6, p7
-(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
-(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
- ;;
-(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
-(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
- cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
-#ifdef CONFIG_PGTABLE_4
- shr.u r28=r22,PUD_SHIFT // shift pud index into position
-#else
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
-#endif
- ;;
- ld8 r17=[r17] // get *pgd (may be 0)
- ;;
-(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
-#ifdef CONFIG_PGTABLE_4
- dep r28=r28,r17,3,(PAGE_SHIFT-3) // r28=pud_offset(pgd,addr)
- ;;
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
-(p7) ld8 r29=[r28] // get *pud (may be 0)
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r29,r0 // was pud_present(*pud) == NULL?
- dep r17=r18,r29,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
-#else
- dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pgd,addr)
-#endif
- ;;
-(p7) ld8 r20=[r17] // get *pmd (may be 0)
- shr.u r19=r22,PAGE_SHIFT // shift pte index into position
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r20,r0 // was pmd_present(*pmd) == NULL?
- dep r21=r19,r20,3,(PAGE_SHIFT-3) // r21=pte_offset(pmd,addr)
- ;;
-(p7) ld8 r18=[r21] // read *pte
- mov r19=cr.isr // cr.isr bit 32 tells us if this is an insn miss
- ;;
-(p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared?
- mov r22=cr.iha // get the VHPT address that caused the TLB miss
- ;; // avoid RAW on p7
-(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss?
- dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address
- ;;
-(p10) itc.i r18 // insert the instruction TLB entry
-(p11) itc.d r18 // insert the data TLB entry
-(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
- mov cr.ifa=r22
-
-#ifdef CONFIG_HUGETLB_PAGE
-(p8) mov cr.itir=r25 // change to default page-size for VHPT
-#endif
-
- /*
- * Now compute and insert the TLB entry for the virtual page table. We never
- * execute in a page table page so there is no need to set the exception deferral
- * bit.
- */
- adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
- ;;
-(p7) itc.d r24
- ;;
-#ifdef CONFIG_SMP
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- /*
- * Re-check pagetable entry. If they changed, we may have received a ptc.g
- * between reading the pagetable and the "itc". If so, flush the entry we
- * inserted and retry. At this point, we have:
- *
- * r28 = equivalent of pud_offset(pgd, ifa)
- * r17 = equivalent of pmd_offset(pud, ifa)
- * r21 = equivalent of pte_offset(pmd, ifa)
- *
- * r29 = *pud
- * r20 = *pmd
- * r18 = *pte
- */
- ld8 r25=[r21] // read *pte again
- ld8 r26=[r17] // read *pmd again
-#ifdef CONFIG_PGTABLE_4
- ld8 r19=[r28] // read *pud again
-#endif
- cmp.ne p6,p7=r0,r0
- ;;
- cmp.ne.or.andcm p6,p7=r26,r20 // did *pmd change
-#ifdef CONFIG_PGTABLE_4
- cmp.ne.or.andcm p6,p7=r19,r29 // did *pud change
-#endif
- mov r27=PAGE_SHIFT<<2
- ;;
-(p6) ptc.l r22,r27 // purge PTE page translation
-(p7) cmp.ne.or.andcm p6,p7=r25,r18 // did *pte change
- ;;
-(p6) ptc.l r16,r27 // purge translation
-#endif
-
- mov pr=r31,-1 // restore predicate registers
- rfi
-END(vhpt_miss)
-
- .org ia64_ivt+0x400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
-ENTRY(itlb_miss)
- DBG_FAULT(1)
- /*
- * The ITLB handler accesses the PTE via the virtually mapped linear
- * page table. If a nested TLB miss occurs, we switch into physical
- * mode, walk the page table, and then re-execute the PTE read and
- * go on normally after that.
- */
- mov r16=cr.ifa // get virtual address
- mov r29=b0 // save b0
- mov r31=pr // save predicates
-.itlb_fault:
- mov r17=cr.iha // get virtual address of PTE
- movl r30=1f // load nested fault continuation point
- ;;
-1: ld8 r18=[r17] // read *pte
- ;;
- mov b0=r29
- tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.cond.spnt page_fault
- ;;
- itc.i r18
- ;;
-#ifdef CONFIG_SMP
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r19=[r17] // read *pte again and see if same
- mov r20=PAGE_SHIFT<<2 // setup page size for purge
- ;;
- cmp.ne p7,p0=r18,r19
- ;;
-(p7) ptc.l r16,r20
-#endif
- mov pr=r31,-1
- rfi
-END(itlb_miss)
-
- .org ia64_ivt+0x0800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
-ENTRY(dtlb_miss)
- DBG_FAULT(2)
- /*
- * The DTLB handler accesses the PTE via the virtually mapped linear
- * page table. If a nested TLB miss occurs, we switch into physical
- * mode, walk the page table, and then re-execute the PTE read and
- * go on normally after that.
- */
- mov r16=cr.ifa // get virtual address
- mov r29=b0 // save b0
- mov r31=pr // save predicates
-dtlb_fault:
- mov r17=cr.iha // get virtual address of PTE
- movl r30=1f // load nested fault continuation point
- ;;
-1: ld8 r18=[r17] // read *pte
- ;;
- mov b0=r29
- tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.cond.spnt page_fault
- ;;
- itc.d r18
- ;;
-#ifdef CONFIG_SMP
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r19=[r17] // read *pte again and see if same
- mov r20=PAGE_SHIFT<<2 // setup page size for purge
- ;;
- cmp.ne p7,p0=r18,r19
- ;;
-(p7) ptc.l r16,r20
-#endif
- mov pr=r31,-1
- rfi
-END(dtlb_miss)
-
- .org ia64_ivt+0x0c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
-ENTRY(alt_itlb_miss)
- DBG_FAULT(3)
- mov r16=cr.ifa // get address that caused the TLB miss
- movl r17=PAGE_KERNEL
- mov r21=cr.ipsr
- movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
- mov r31=pr
- ;;
-#ifdef CONFIG_DISABLE_VHPT
- shr.u r22=r16,61 // get the region number into r21
- ;;
- cmp.gt p8,p0=6,r22 // user mode
- ;;
-(p8) thash r17=r16
- ;;
-(p8) mov cr.iha=r17
-(p8) mov r29=b0 // save b0
-(p8) br.cond.dptk .itlb_fault
-#endif
- extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
- and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
- shr.u r18=r16,57 // move address bit 61 to bit 4
- ;;
- andcm r18=0x10,r18 // bit 4=~address-bit(61)
- cmp.ne p8,p0=r0,r23 // psr.cpl != 0?
- or r19=r17,r19 // insert PTE control bits into r19
- ;;
- or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
-(p8) br.cond.spnt page_fault
- ;;
- itc.i r19 // insert the TLB entry
- mov pr=r31,-1
- rfi
-END(alt_itlb_miss)
-
- .org ia64_ivt+0x1000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
-ENTRY(alt_dtlb_miss)
- DBG_FAULT(4)
- mov r16=cr.ifa // get address that caused the TLB miss
- movl r17=PAGE_KERNEL
- mov r20=cr.isr
- movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
- mov r21=cr.ipsr
- mov r31=pr
- ;;
-#ifdef CONFIG_DISABLE_VHPT
- shr.u r22=r16,61 // get the region number into r21
- ;;
- cmp.gt p8,p0=6,r22 // access to region 0-5
- ;;
-(p8) thash r17=r16
- ;;
-(p8) mov cr.iha=r17
-(p8) mov r29=b0 // save b0
-(p8) br.cond.dptk dtlb_fault
-#endif
- extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
- and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
- tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
- shr.u r18=r16,57 // move address bit 61 to bit 4
- and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
- tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
- ;;
- andcm r18=0x10,r18 // bit 4=~address-bit(61)
- cmp.ne p8,p0=r0,r23
-(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
-(p8) br.cond.spnt page_fault
-
- dep r21=-1,r21,IA64_PSR_ED_BIT,1
- or r19=r19,r17 // insert PTE control bits into r19
- ;;
- or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
-(p6) mov cr.ipsr=r21
- ;;
-(p7) itc.d r19 // insert the TLB entry
- mov pr=r31,-1
- rfi
-END(alt_dtlb_miss)
-
- .org ia64_ivt+0x1400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
-ENTRY(nested_dtlb_miss)
- /*
- * In the absence of kernel bugs, we get here when the virtually mapped linear
- * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
- * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page
- * table is missing, a nested TLB miss fault is triggered and control is
- * transferred to this point. When this happens, we lookup the pte for the
- * faulting address by walking the page table in physical mode and return to the
- * continuation point passed in register r30 (or call page_fault if the address is
- * not mapped).
- *
- * Input: r16: faulting address
- * r29: saved b0
- * r30: continuation address
- * r31: saved pr
- *
- * Output: r17: physical address of PTE of faulting address
- * r29: saved b0
- * r30: continuation address
- * r31: saved pr
- *
- * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared)
- */
- rsm psr.dt // switch to using physical data addressing
- mov r19=IA64_KR(PT_BASE) // get the page table base address
- shl r21=r16,3 // shift bit 60 into sign bit
- mov r18=cr.itir
- ;;
- shr.u r17=r16,61 // get the region number into r17
- extr.u r18=r18,2,6 // get the faulting page size
- ;;
- cmp.eq p6,p7=5,r17 // is faulting address in region 5?
- add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
- add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
- ;;
- shr.u r22=r16,r22
- shr.u r18=r16,r18
-(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
-
- srlz.d
- LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
-
- .pred.rel "mutex", p6, p7
-(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
-(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
- ;;
-(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
-(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
- cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
-#ifdef CONFIG_PGTABLE_4
- shr.u r18=r22,PUD_SHIFT // shift pud index into position
-#else
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
-#endif
- ;;
- ld8 r17=[r17] // get *pgd (may be 0)
- ;;
-(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
- dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=p[u|m]d_offset(pgd,addr)
- ;;
-#ifdef CONFIG_PGTABLE_4
-(p7) ld8 r17=[r17] // get *pud (may be 0)
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) == NULL?
- dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
- ;;
-#endif
-(p7) ld8 r17=[r17] // get *pmd (may be 0)
- shr.u r19=r22,PAGE_SHIFT // shift pte index into position
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) == NULL?
- dep r17=r19,r17,3,(PAGE_SHIFT-3) // r17=pte_offset(pmd,addr);
-(p6) br.cond.spnt page_fault
- mov b0=r30
- br.sptk.many b0 // return to continuation point
-END(nested_dtlb_miss)
-
- .org ia64_ivt+0x1800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
-ENTRY(ikey_miss)
- DBG_FAULT(6)
- FAULT(6)
-END(ikey_miss)
-
- //-----------------------------------------------------------------------------------
- // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
-ENTRY(page_fault)
- ssm psr.dt
- ;;
- srlz.i
- ;;
- SAVE_MIN_WITH_COVER
- alloc r15=ar.pfs,0,0,3,0
- mov out0=cr.ifa
- mov out1=cr.isr
- adds r3=8,r2 // set up second base pointer
- ;;
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collectin is on
- ;;
-(p15) ssm psr.i // restore psr.i
- movl r14=ia64_leave_kernel
- ;;
- SAVE_REST
- mov rp=r14
- ;;
- adds out2=16,r12 // out2 = pointer to pt_regs
- br.call.sptk.many b6=ia64_do_page_fault // ignore return address
-END(page_fault)
-
- .org ia64_ivt+0x1c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
-ENTRY(dkey_miss)
- DBG_FAULT(7)
- FAULT(7)
-END(dkey_miss)
-
- .org ia64_ivt+0x2000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
-ENTRY(dirty_bit)
- DBG_FAULT(8)
- /*
- * What we do here is to simply turn on the dirty bit in the PTE. We need to
- * update both the page-table and the TLB entry. To efficiently access the PTE,
- * we address it through the virtual page table. Most likely, the TLB entry for
- * the relevant virtual page table page is still present in the TLB so we can
- * normally do this without additional TLB misses. In case the necessary virtual
- * page table TLB entry isn't present, we take a nested TLB miss hit where we look
- * up the physical address of the L3 PTE and then continue at label 1 below.
- */
- mov r16=cr.ifa // get the address that caused the fault
- movl r30=1f // load continuation point in case of nested fault
- ;;
- thash r17=r16 // compute virtual address of L3 PTE
- mov r29=b0 // save b0 in case of nested fault
- mov r31=pr // save pr
-#ifdef CONFIG_SMP
- mov r28=ar.ccv // save ar.ccv
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- mov ar.ccv=r18 // set compare value for cmpxchg
- or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
- tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
- ;;
-(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only update if page is present
- mov r24=PAGE_SHIFT<<2
- ;;
-(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present
- ;;
-(p6) itc.d r25 // install updated PTE
- ;;
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r18=[r17] // read PTE again
- ;;
- cmp.eq p6,p7=r18,r25 // is it same as the newly installed
- ;;
-(p7) ptc.l r16,r24
- mov b0=r29 // restore b0
- mov ar.ccv=r28
-#else
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
- mov b0=r29 // restore b0
- ;;
- st8 [r17]=r18 // store back updated PTE
- itc.d r18 // install updated PTE
-#endif
- mov pr=r31,-1 // restore pr
- rfi
-END(dirty_bit)
-
- .org ia64_ivt+0x2400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
-ENTRY(iaccess_bit)
- DBG_FAULT(9)
- // Like Entry 8, except for instruction access
- mov r16=cr.ifa // get the address that caused the fault
- movl r30=1f // load continuation point in case of nested fault
- mov r31=pr // save predicates
-#ifdef CONFIG_ITANIUM
- /*
- * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
- */
- mov r17=cr.ipsr
- ;;
- mov r18=cr.iip
- tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set?
- ;;
-(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa
-#endif /* CONFIG_ITANIUM */
- ;;
- thash r17=r16 // compute virtual address of L3 PTE
- mov r29=b0 // save b0 in case of nested fault)
-#ifdef CONFIG_SMP
- mov r28=ar.ccv // save ar.ccv
- ;;
-1: ld8 r18=[r17]
- ;;
- mov ar.ccv=r18 // set compare value for cmpxchg
- or r25=_PAGE_A,r18 // set the accessed bit
- tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
- ;;
-(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present
- mov r24=PAGE_SHIFT<<2
- ;;
-(p6) cmp.eq p6,p7=r26,r18 // Only if page present
- ;;
-(p6) itc.i r25 // install updated PTE
- ;;
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r18=[r17] // read PTE again
- ;;
- cmp.eq p6,p7=r18,r25 // is it same as the newly installed
- ;;
-(p7) ptc.l r16,r24
- mov b0=r29 // restore b0
- mov ar.ccv=r28
-#else /* !CONFIG_SMP */
- ;;
-1: ld8 r18=[r17]
- ;;
- or r18=_PAGE_A,r18 // set the accessed bit
- mov b0=r29 // restore b0
- ;;
- st8 [r17]=r18 // store back updated PTE
- itc.i r18 // install updated PTE
-#endif /* !CONFIG_SMP */
- mov pr=r31,-1
- rfi
-END(iaccess_bit)
-
- .org ia64_ivt+0x2800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
-ENTRY(daccess_bit)
- DBG_FAULT(10)
- // Like Entry 8, except for data access
- mov r16=cr.ifa // get the address that caused the fault
- movl r30=1f // load continuation point in case of nested fault
- ;;
- thash r17=r16 // compute virtual address of L3 PTE
- mov r31=pr
- mov r29=b0 // save b0 in case of nested fault)
-#ifdef CONFIG_SMP
- mov r28=ar.ccv // save ar.ccv
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- mov ar.ccv=r18 // set compare value for cmpxchg
- or r25=_PAGE_A,r18 // set the dirty bit
- tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
- ;;
-(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page is present
- mov r24=PAGE_SHIFT<<2
- ;;
-(p6) cmp.eq p6,p7=r26,r18 // Only if page is present
- ;;
-(p6) itc.d r25 // install updated PTE
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
- ;;
- ld8 r18=[r17] // read PTE again
- ;;
- cmp.eq p6,p7=r18,r25 // is it same as the newly installed
- ;;
-(p7) ptc.l r16,r24
- mov ar.ccv=r28
-#else
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- or r18=_PAGE_A,r18 // set the accessed bit
- ;;
- st8 [r17]=r18 // store back updated PTE
- itc.d r18 // install updated PTE
-#endif
- mov b0=r29 // restore b0
- mov pr=r31,-1
- rfi
-END(daccess_bit)
-
- .org ia64_ivt+0x2c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
-ENTRY(break_fault)
- /*
- * The streamlined system call entry/exit paths only save/restore the initial part
- * of pt_regs. This implies that the callers of system-calls must adhere to the
- * normal procedure calling conventions.
- *
- * Registers to be saved & restored:
- * CR registers: cr.ipsr, cr.iip, cr.ifs
- * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr
- * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15
- * Registers to be restored only:
- * r8-r11: output value from the system call.
- *
- * During system call exit, scratch registers (including r15) are modified/cleared
- * to prevent leaking bits from kernel to user level.
- */
- DBG_FAULT(11)
- mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc)
- mov r29=cr.ipsr // M2 (12 cyc)
- mov r31=pr // I0 (2 cyc)
-
- mov r17=cr.iim // M2 (2 cyc)
- mov.m r27=ar.rsc // M2 (12 cyc)
- mov r18=__IA64_BREAK_SYSCALL // A
-
- mov.m ar.rsc=0 // M2
- mov.m r21=ar.fpsr // M2 (12 cyc)
- mov r19=b6 // I0 (2 cyc)
- ;;
- mov.m r23=ar.bspstore // M2 (12 cyc)
- mov.m r24=ar.rnat // M2 (5 cyc)
- mov.i r26=ar.pfs // I0 (2 cyc)
-
- invala // M0|1
- nop.m 0 // M
- mov r20=r1 // A save r1
-
- nop.m 0
- movl r30=sys_call_table // X
-
- mov r28=cr.iip // M2 (2 cyc)
- cmp.eq p0,p7=r18,r17 // I0 is this a system call?
-(p7) br.cond.spnt non_syscall // B no ->
- //
- // From this point on, we are definitely on the syscall-path
- // and we can use (non-banked) scratch registers.
- //
-///////////////////////////////////////////////////////////////////////
- mov r1=r16 // A move task-pointer to "addl"-addressable reg
- mov r2=r16 // A setup r2 for ia64_syscall_setup
- add r9=TI_FLAGS+IA64_TASK_SIZE,r16 // A r9 = ¤t_thread_info()->flags
-
- adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16
- adds r15=-1024,r15 // A subtract 1024 from syscall number
- mov r3=NR_syscalls - 1
- ;;
- ld1.bias r17=[r16] // M0|1 r17 = current->thread.on_ustack flag
- ld4 r9=[r9] // M0|1 r9 = current_thread_info()->flags
- extr.u r8=r29,41,2 // I0 extract ei field from cr.ipsr
-
- shladd r30=r15,3,r30 // A r30 = sys_call_table + 8*(syscall-1024)
- addl r22=IA64_RBS_OFFSET,r1 // A compute base of RBS
- cmp.leu p6,p7=r15,r3 // A syscall number in range?
- ;;
-
- lfetch.fault.excl.nt1 [r22] // M0|1 prefetch RBS
-(p6) ld8 r30=[r30] // M0|1 load address of syscall entry point
- tnat.nz.or p7,p0=r15 // I0 is syscall nr a NaT?
-
- mov.m ar.bspstore=r22 // M2 switch to kernel RBS
- cmp.eq p8,p9=2,r8 // A isr.ei==2?
- ;;
-
-(p8) mov r8=0 // A clear ei to 0
-(p7) movl r30=sys_ni_syscall // X
-
-(p8) adds r28=16,r28 // A switch cr.iip to next bundle
-(p9) adds r8=1,r8 // A increment ei to next slot
- nop.i 0
- ;;
-
- mov.m r25=ar.unat // M2 (5 cyc)
- dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr
- adds r15=1024,r15 // A restore original syscall number
- //
- // If any of the above loads miss in L1D, we'll stall here until
- // the data arrives.
- //
-///////////////////////////////////////////////////////////////////////
- st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag
- mov b6=r30 // I0 setup syscall handler branch reg early
- cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already?
-
- and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit
- mov r18=ar.bsp // M2 (12 cyc)
-(pKStk) br.cond.spnt .break_fixup // B we're already in kernel-mode -- fix up RBS
- ;;
-.back_from_break_fixup:
-(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A compute base of memory stack
- cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited?
- br.call.sptk.many b7=ia64_syscall_setup // B
-1:
- mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
- nop 0
- bsw.1 // B (6 cyc) regs are saved, switch to bank 1
- ;;
-
- ssm psr.ic | PSR_DEFAULT_BITS // M2 now it's safe to re-enable intr.-collection
- movl r3=ia64_ret_from_syscall // X
- ;;
-
- srlz.i // M0 ensure interruption collection is on
- mov rp=r3 // I0 set the real return addr
-(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT
-
-(p15) ssm psr.i // M2 restore psr.i
-(p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr)
- br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic
- // NOT REACHED
-///////////////////////////////////////////////////////////////////////
- // On entry, we optimistically assumed that we're coming from user-space.
- // For the rare cases where a system-call is done from within the kernel,
- // we fix things up at this point:
-.break_fixup:
- add r1=-IA64_PT_REGS_SIZE,sp // A allocate space for pt_regs structure
- mov ar.rnat=r24 // M2 restore kernel's AR.RNAT
- ;;
- mov ar.bspstore=r23 // M2 restore kernel's AR.BSPSTORE
- br.cond.sptk .back_from_break_fixup
-END(break_fault)
-
- .org ia64_ivt+0x3000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
-ENTRY(interrupt)
- DBG_FAULT(12)
- mov r31=pr // prepare to save predicates
- ;;
- SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- adds r3=8,r2 // set up second base pointer for SAVE_REST
- srlz.i // ensure everybody knows psr.ic is back on
- ;;
- SAVE_REST
- ;;
- MCA_RECOVER_RANGE(interrupt)
- alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
- mov out0=cr.ivr // pass cr.ivr as first arg
- add out1=16,sp // pass pointer to pt_regs as second arg
- ;;
- srlz.d // make sure we see the effect of cr.ivr
- movl r14=ia64_leave_kernel
- ;;
- mov rp=r14
- br.call.sptk.many b6=ia64_handle_irq
-END(interrupt)
-
- .org ia64_ivt+0x3400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3400 Entry 13 (size 64 bundles) Reserved
- DBG_FAULT(13)
- FAULT(13)
-
- .org ia64_ivt+0x3800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3800 Entry 14 (size 64 bundles) Reserved
- DBG_FAULT(14)
- FAULT(14)
-
- /*
- * There is no particular reason for this code to be here, other than that
- * there happens to be space here that would go unused otherwise. If this
- * fault ever gets "unreserved", simply moved the following code to a more
- * suitable spot...
- *
- * ia64_syscall_setup() is a separate subroutine so that it can
- * allocate stacked registers so it can safely demine any
- * potential NaT values from the input registers.
- *
- * On entry:
- * - executing on bank 0 or bank 1 register set (doesn't matter)
- * - r1: stack pointer
- * - r2: current task pointer
- * - r3: preserved
- * - r11: original contents (saved ar.pfs to be saved)
- * - r12: original contents (sp to be saved)
- * - r13: original contents (tp to be saved)
- * - r15: original contents (syscall # to be saved)
- * - r18: saved bsp (after switching to kernel stack)
- * - r19: saved b6
- * - r20: saved r1 (gp)
- * - r21: saved ar.fpsr
- * - r22: kernel's register backing store base (krbs_base)
- * - r23: saved ar.bspstore
- * - r24: saved ar.rnat
- * - r25: saved ar.unat
- * - r26: saved ar.pfs
- * - r27: saved ar.rsc
- * - r28: saved cr.iip
- * - r29: saved cr.ipsr
- * - r31: saved pr
- * - b0: original contents (to be saved)
- * On exit:
- * - p10: TRUE if syscall is invoked with more than 8 out
- * registers or r15's Nat is true
- * - r1: kernel's gp
- * - r3: preserved (same as on entry)
- * - r8: -EINVAL if p10 is true
- * - r12: points to kernel stack
- * - r13: points to current task
- * - r14: preserved (same as on entry)
- * - p13: preserved
- * - p15: TRUE if interrupts need to be re-enabled
- * - ar.fpsr: set to kernel settings
- * - b6: preserved (same as on entry)
- */
-GLOBAL_ENTRY(ia64_syscall_setup)
-#if PT(B6) != 0
-# error This code assumes that b6 is the first field in pt_regs.
-#endif
- st8 [r1]=r19 // save b6
- add r16=PT(CR_IPSR),r1 // initialize first base pointer
- add r17=PT(R11),r1 // initialize second base pointer
- ;;
- alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable
- st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr
- tnat.nz p8,p0=in0
-
- st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11
- tnat.nz p9,p0=in1
-(pKStk) mov r18=r0 // make sure r18 isn't NaT
- ;;
-
- st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs
- st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip
- mov r28=b0 // save b0 (2 cyc)
- ;;
-
- st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat
- dep r19=0,r19,38,26 // clear all bits but 0..37 [I0]
-(p8) mov in0=-1
- ;;
-
- st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs
- extr.u r11=r19,7,7 // I0 // get sol of ar.pfs
- and r8=0x7f,r19 // A // get sof of ar.pfs
-
- st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc
- tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0
-(p9) mov in1=-1
- ;;
-
-(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8
- tnat.nz p10,p0=in2
- add r11=8,r11
- ;;
-(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field
-(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field
- tnat.nz p11,p0=in3
- ;;
-(p10) mov in2=-1
- tnat.nz p12,p0=in4 // [I0]
-(p11) mov in3=-1
- ;;
-(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat
-(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore
- shl r18=r18,16 // compute ar.rsc to be used for "loadrs"
- ;;
- st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates
- st8 [r17]=r28,PT(R1)-PT(B0) // save b0
- tnat.nz p13,p0=in5 // [I0]
- ;;
- st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs"
- st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1
-(p12) mov in4=-1
- ;;
-
-.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12
-.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13
-(p13) mov in5=-1
- ;;
- st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr
- tnat.nz p13,p0=in6
- cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8
- ;;
- mov r8=1
-(p9) tnat.nz p10,p0=r15
- adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch)
-
- st8.spill [r17]=r15 // save r15
- tnat.nz p8,p0=in7
- nop.i 0
-
- mov r13=r2 // establish `current'
- movl r1=__gp // establish kernel global pointer
- ;;
- st8 [r16]=r8 // ensure pt_regs.r8 != 0 (see handle_syscall_error)
-(p13) mov in6=-1
-(p8) mov in7=-1
-
- cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
- movl r17=FPSR_DEFAULT
- ;;
- mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value
-(p10) mov r8=-EINVAL
- br.ret.sptk.many b7
-END(ia64_syscall_setup)
-
- .org ia64_ivt+0x3c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3c00 Entry 15 (size 64 bundles) Reserved
- DBG_FAULT(15)
- FAULT(15)
-
- /*
- * Squatting in this space ...
- *
- * This special case dispatcher for illegal operation faults allows preserved
- * registers to be modified through a callback function (asm only) that is handed
- * back from the fault handler in r8. Up to three arguments can be passed to the
- * callback function by returning an aggregate with the callback as its first
- * element, followed by the arguments.
- */
-ENTRY(dispatch_illegal_op_fault)
- .prologue
- .body
- SAVE_MIN_WITH_COVER
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
-(p15) ssm psr.i // restore psr.i
- adds r3=8,r2 // set up second base pointer for SAVE_REST
- ;;
- alloc r14=ar.pfs,0,0,1,0 // must be first in insn group
- mov out0=ar.ec
- ;;
- SAVE_REST
- PT_REGS_UNWIND_INFO(0)
- ;;
- br.call.sptk.many rp=ia64_illegal_op_fault
-.ret0: ;;
- alloc r14=ar.pfs,0,0,3,0 // must be first in insn group
- mov out0=r9
- mov out1=r10
- mov out2=r11
- movl r15=ia64_leave_kernel
- ;;
- mov rp=r15
- mov b6=r8
- ;;
- cmp.ne p6,p0=0,r8
-(p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel
- br.sptk.many ia64_leave_kernel
-END(dispatch_illegal_op_fault)
-
- .org ia64_ivt+0x4000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4000 Entry 16 (size 64 bundles) Reserved
- DBG_FAULT(16)
- FAULT(16)
-
- .org ia64_ivt+0x4400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4400 Entry 17 (size 64 bundles) Reserved
- DBG_FAULT(17)
- FAULT(17)
-
-ENTRY(non_syscall)
- mov ar.rsc=r27 // restore ar.rsc before SAVE_MIN_WITH_COVER
- ;;
- SAVE_MIN_WITH_COVER
-
- // There is no particular reason for this code to be here, other than that
- // there happens to be space here that would go unused otherwise. If this
- // fault ever gets "unreserved", simply moved the following code to a more
- // suitable spot...
-
- alloc r14=ar.pfs,0,0,2,0
- mov out0=cr.iim
- add out1=16,sp
- adds r3=8,r2 // set up second base pointer for SAVE_REST
-
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
-(p15) ssm psr.i // restore psr.i
- movl r15=ia64_leave_kernel
- ;;
- SAVE_REST
- mov rp=r15
- ;;
- br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr
-END(non_syscall)
-
- .org ia64_ivt+0x4800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4800 Entry 18 (size 64 bundles) Reserved
- DBG_FAULT(18)
- FAULT(18)
-
- /*
- * There is no particular reason for this code to be here, other than that
- * there happens to be space here that would go unused otherwise. If this
- * fault ever gets "unreserved", simply moved the following code to a more
- * suitable spot...
- */
-
-ENTRY(dispatch_unaligned_handler)
- SAVE_MIN_WITH_COVER
- ;;
- alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
- mov out0=cr.ifa
- adds out1=16,sp
-
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
-(p15) ssm psr.i // restore psr.i
- adds r3=8,r2 // set up second base pointer
- ;;
- SAVE_REST
- movl r14=ia64_leave_kernel
- ;;
- mov rp=r14
- br.sptk.many ia64_prepare_handle_unaligned
-END(dispatch_unaligned_handler)
-
- .org ia64_ivt+0x4c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4c00 Entry 19 (size 64 bundles) Reserved
- DBG_FAULT(19)
- FAULT(19)
-
- /*
- * There is no particular reason for this code to be here, other than that
- * there happens to be space here that would go unused otherwise. If this
- * fault ever gets "unreserved", simply moved the following code to a more
- * suitable spot...
- */
-
-ENTRY(dispatch_to_fault_handler)
- /*
- * Input:
- * psr.ic: off
- * r19: fault vector number (e.g., 24 for General Exception)
- * r31: contains saved predicates (pr)
- */
- SAVE_MIN_WITH_COVER_R19
- alloc r14=ar.pfs,0,0,5,0
- mov out0=r15
- mov out1=cr.isr
- mov out2=cr.ifa
- mov out3=cr.iim
- mov out4=cr.itir
- ;;
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
-(p15) ssm psr.i // restore psr.i
- adds r3=8,r2 // set up second base pointer for SAVE_REST
- ;;
- SAVE_REST
- movl r14=ia64_leave_kernel
- ;;
- mov rp=r14
- br.call.sptk.many b6=ia64_fault
-END(dispatch_to_fault_handler)
-
-//
-// --- End of long entries, Beginning of short entries
-//
-
- .org ia64_ivt+0x5000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
-ENTRY(page_not_present)
- DBG_FAULT(20)
- mov r16=cr.ifa
- rsm psr.dt
- /*
- * The Linux page fault handler doesn't expect non-present pages to be in
- * the TLB. Flush the existing entry now, so we meet that expectation.
- */
- mov r17=PAGE_SHIFT<<2
- ;;
- ptc.l r16,r17
- ;;
- mov r31=pr
- srlz.d
- br.sptk.many page_fault
-END(page_not_present)
-
- .org ia64_ivt+0x5100
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
-ENTRY(key_permission)
- DBG_FAULT(21)
- mov r16=cr.ifa
- rsm psr.dt
- mov r31=pr
- ;;
- srlz.d
- br.sptk.many page_fault
-END(key_permission)
-
- .org ia64_ivt+0x5200
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
-ENTRY(iaccess_rights)
- DBG_FAULT(22)
- mov r16=cr.ifa
- rsm psr.dt
- mov r31=pr
- ;;
- srlz.d
- br.sptk.many page_fault
-END(iaccess_rights)
-
- .org ia64_ivt+0x5300
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
-ENTRY(daccess_rights)
- DBG_FAULT(23)
- mov r16=cr.ifa
- rsm psr.dt
- mov r31=pr
- ;;
- srlz.d
- br.sptk.many page_fault
-END(daccess_rights)
-
- .org ia64_ivt+0x5400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
-ENTRY(general_exception)
- DBG_FAULT(24)
- mov r16=cr.isr
- mov r31=pr
- ;;
- cmp4.eq p6,p0=0,r16
-(p6) br.sptk.many dispatch_illegal_op_fault
- ;;
- mov r19=24 // fault number
- br.sptk.many dispatch_to_fault_handler
-END(general_exception)
-
- .org ia64_ivt+0x5500
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
-ENTRY(disabled_fp_reg)
- DBG_FAULT(25)
- rsm psr.dfh // ensure we can access fph
- ;;
- srlz.d
- mov r31=pr
- mov r19=25
- br.sptk.many dispatch_to_fault_handler
-END(disabled_fp_reg)
-
- .org ia64_ivt+0x5600
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
-ENTRY(nat_consumption)
- DBG_FAULT(26)
-
- mov r16=cr.ipsr
- mov r17=cr.isr
- mov r31=pr // save PR
- ;;
- and r18=0xf,r17 // r18 = cr.ipsr.code{3:0}
- tbit.z p6,p0=r17,IA64_ISR_NA_BIT
- ;;
- cmp.ne.or p6,p0=IA64_ISR_CODE_LFETCH,r18
- dep r16=-1,r16,IA64_PSR_ED_BIT,1
-(p6) br.cond.spnt 1f // branch if (cr.ispr.na == 0 || cr.ipsr.code{3:0} != LFETCH)
- ;;
- mov cr.ipsr=r16 // set cr.ipsr.na
- mov pr=r31,-1
- ;;
- rfi
-
-1: mov pr=r31,-1
- ;;
- FAULT(26)
-END(nat_consumption)
-
- .org ia64_ivt+0x5700
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
-ENTRY(speculation_vector)
- DBG_FAULT(27)
- /*
- * A [f]chk.[as] instruction needs to take the branch to the recovery code but
- * this part of the architecture is not implemented in hardware on some CPUs, such
- * as Itanium. Thus, in general we need to emulate the behavior. IIM contains
- * the relative target (not yet sign extended). So after sign extending it we
- * simply add it to IIP. We also need to reset the EI field of the IPSR to zero,
- * i.e., the slot to restart into.
- *
- * cr.imm contains zero_ext(imm21)
- */
- mov r18=cr.iim
- ;;
- mov r17=cr.iip
- shl r18=r18,43 // put sign bit in position (43=64-21)
- ;;
-
- mov r16=cr.ipsr
- shr r18=r18,39 // sign extend (39=43-4)
- ;;
-
- add r17=r17,r18 // now add the offset
- ;;
- mov cr.iip=r17
- dep r16=0,r16,41,2 // clear EI
- ;;
-
- mov cr.ipsr=r16
- ;;
-
- rfi // and go back
-END(speculation_vector)
-
- .org ia64_ivt+0x5800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5800 Entry 28 (size 16 bundles) Reserved
- DBG_FAULT(28)
- FAULT(28)
-
- .org ia64_ivt+0x5900
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
-ENTRY(debug_vector)
- DBG_FAULT(29)
- FAULT(29)
-END(debug_vector)
-
- .org ia64_ivt+0x5a00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
-ENTRY(unaligned_access)
- DBG_FAULT(30)
- mov r31=pr // prepare to save predicates
- ;;
- br.sptk.many dispatch_unaligned_handler
-END(unaligned_access)
-
- .org ia64_ivt+0x5b00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
-ENTRY(unsupported_data_reference)
- DBG_FAULT(31)
- FAULT(31)
-END(unsupported_data_reference)
-
- .org ia64_ivt+0x5c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
-ENTRY(floating_point_fault)
- DBG_FAULT(32)
- FAULT(32)
-END(floating_point_fault)
-
- .org ia64_ivt+0x5d00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
-ENTRY(floating_point_trap)
- DBG_FAULT(33)
- FAULT(33)
-END(floating_point_trap)
-
- .org ia64_ivt+0x5e00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
-ENTRY(lower_privilege_trap)
- DBG_FAULT(34)
- FAULT(34)
-END(lower_privilege_trap)
-
- .org ia64_ivt+0x5f00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
-ENTRY(taken_branch_trap)
- DBG_FAULT(35)
- FAULT(35)
-END(taken_branch_trap)
-
- .org ia64_ivt+0x6000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
-ENTRY(single_step_trap)
- DBG_FAULT(36)
- FAULT(36)
-END(single_step_trap)
-
- .org ia64_ivt+0x6100
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6100 Entry 37 (size 16 bundles) Reserved
- DBG_FAULT(37)
- FAULT(37)
-
- .org ia64_ivt+0x6200
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6200 Entry 38 (size 16 bundles) Reserved
- DBG_FAULT(38)
- FAULT(38)
-
- .org ia64_ivt+0x6300
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6300 Entry 39 (size 16 bundles) Reserved
- DBG_FAULT(39)
- FAULT(39)
-
- .org ia64_ivt+0x6400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6400 Entry 40 (size 16 bundles) Reserved
- DBG_FAULT(40)
- FAULT(40)
-
- .org ia64_ivt+0x6500
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6500 Entry 41 (size 16 bundles) Reserved
- DBG_FAULT(41)
- FAULT(41)
-
- .org ia64_ivt+0x6600
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6600 Entry 42 (size 16 bundles) Reserved
- DBG_FAULT(42)
- FAULT(42)
-
- .org ia64_ivt+0x6700
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6700 Entry 43 (size 16 bundles) Reserved
- DBG_FAULT(43)
- FAULT(43)
-
- .org ia64_ivt+0x6800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6800 Entry 44 (size 16 bundles) Reserved
- DBG_FAULT(44)
- FAULT(44)
-
- .org ia64_ivt+0x6900
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
-ENTRY(ia32_exception)
- DBG_FAULT(45)
- FAULT(45)
-END(ia32_exception)
-
- .org ia64_ivt+0x6a00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
-ENTRY(ia32_intercept)
- DBG_FAULT(46)
-#ifdef CONFIG_IA32_SUPPORT
- mov r31=pr
- mov r16=cr.isr
- ;;
- extr.u r17=r16,16,8 // get ISR.code
- mov r18=ar.eflag
- mov r19=cr.iim // old eflag value
- ;;
- cmp.ne p6,p0=2,r17
-(p6) br.cond.spnt 1f // not a system flag fault
- xor r16=r18,r19
- ;;
- extr.u r17=r16,18,1 // get the eflags.ac bit
- ;;
- cmp.eq p6,p0=0,r17
-(p6) br.cond.spnt 1f // eflags.ac bit didn't change
- ;;
- mov pr=r31,-1 // restore predicate registers
- rfi
-
-1:
-#endif // CONFIG_IA32_SUPPORT
- FAULT(46)
-END(ia32_intercept)
-
- .org ia64_ivt+0x6b00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74)
-ENTRY(ia32_interrupt)
- DBG_FAULT(47)
-#ifdef CONFIG_IA32_SUPPORT
- mov r31=pr
- br.sptk.many dispatch_to_ia32_handler
-#else
- FAULT(47)
-#endif
-END(ia32_interrupt)
-
- .org ia64_ivt+0x6c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6c00 Entry 48 (size 16 bundles) Reserved
- DBG_FAULT(48)
- FAULT(48)
-
- .org ia64_ivt+0x6d00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6d00 Entry 49 (size 16 bundles) Reserved
- DBG_FAULT(49)
- FAULT(49)
-
- .org ia64_ivt+0x6e00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6e00 Entry 50 (size 16 bundles) Reserved
- DBG_FAULT(50)
- FAULT(50)
-
- .org ia64_ivt+0x6f00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6f00 Entry 51 (size 16 bundles) Reserved
- DBG_FAULT(51)
- FAULT(51)
-
- .org ia64_ivt+0x7000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7000 Entry 52 (size 16 bundles) Reserved
- DBG_FAULT(52)
- FAULT(52)
-
- .org ia64_ivt+0x7100
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7100 Entry 53 (size 16 bundles) Reserved
- DBG_FAULT(53)
- FAULT(53)
-
- .org ia64_ivt+0x7200
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7200 Entry 54 (size 16 bundles) Reserved
- DBG_FAULT(54)
- FAULT(54)
-
- .org ia64_ivt+0x7300
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7300 Entry 55 (size 16 bundles) Reserved
- DBG_FAULT(55)
- FAULT(55)
-
- .org ia64_ivt+0x7400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7400 Entry 56 (size 16 bundles) Reserved
- DBG_FAULT(56)
- FAULT(56)
-
- .org ia64_ivt+0x7500
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7500 Entry 57 (size 16 bundles) Reserved
- DBG_FAULT(57)
- FAULT(57)
-
- .org ia64_ivt+0x7600
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7600 Entry 58 (size 16 bundles) Reserved
- DBG_FAULT(58)
- FAULT(58)
-
- .org ia64_ivt+0x7700
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7700 Entry 59 (size 16 bundles) Reserved
- DBG_FAULT(59)
- FAULT(59)
-
- .org ia64_ivt+0x7800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7800 Entry 60 (size 16 bundles) Reserved
- DBG_FAULT(60)
- FAULT(60)
-
- .org ia64_ivt+0x7900
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7900 Entry 61 (size 16 bundles) Reserved
- DBG_FAULT(61)
- FAULT(61)
-
- .org ia64_ivt+0x7a00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7a00 Entry 62 (size 16 bundles) Reserved
- DBG_FAULT(62)
- FAULT(62)
-
- .org ia64_ivt+0x7b00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7b00 Entry 63 (size 16 bundles) Reserved
- DBG_FAULT(63)
- FAULT(63)
-
- .org ia64_ivt+0x7c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7c00 Entry 64 (size 16 bundles) Reserved
- DBG_FAULT(64)
- FAULT(64)
-
- .org ia64_ivt+0x7d00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7d00 Entry 65 (size 16 bundles) Reserved
- DBG_FAULT(65)
- FAULT(65)
-
- .org ia64_ivt+0x7e00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7e00 Entry 66 (size 16 bundles) Reserved
- DBG_FAULT(66)
- FAULT(66)
-
- .org ia64_ivt+0x7f00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7f00 Entry 67 (size 16 bundles) Reserved
- DBG_FAULT(67)
- FAULT(67)
-
-#ifdef CONFIG_IA32_SUPPORT
-
- /*
- * There is no particular reason for this code to be here, other than that
- * there happens to be space here that would go unused otherwise. If this
- * fault ever gets "unreserved", simply moved the following code to a more
- * suitable spot...
- */
-
- // IA32 interrupt entry point
-
-ENTRY(dispatch_to_ia32_handler)
- SAVE_MIN
- ;;
- mov r14=cr.isr
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
-(p15) ssm psr.i
- adds r3=8,r2 // Base pointer for SAVE_REST
- ;;
- SAVE_REST
- ;;
- mov r15=0x80
- shr r14=r14,16 // Get interrupt number
- ;;
- cmp.ne p6,p0=r14,r15
-(p6) br.call.dpnt.many b6=non_ia32_syscall
-
- adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions
- adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
- ;;
- cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
- ld8 r8=[r14] // get r8
- ;;
- st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP)
- ;;
- alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
- ;;
- ld4 r8=[r14],8 // r8 == eax (syscall number)
- mov r15=IA32_NR_syscalls
- ;;
- cmp.ltu.unc p6,p7=r8,r15
- ld4 out1=[r14],8 // r9 == ecx
- ;;
- ld4 out2=[r14],8 // r10 == edx
- ;;
- ld4 out0=[r14] // r11 == ebx
- adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp
- ;;
- ld4 out5=[r14],PT(R14)-PT(R13) // r13 == ebp
- ;;
- ld4 out3=[r14],PT(R15)-PT(R14) // r14 == esi
- adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
- ;;
- ld4 out4=[r14] // r15 == edi
- movl r16=ia32_syscall_table
- ;;
-(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
- ld4 r2=[r2] // r2 = current_thread_info()->flags
- ;;
- ld8 r16=[r16]
- and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit
- ;;
- mov b6=r16
- movl r15=ia32_ret_from_syscall
- cmp.eq p8,p0=r2,r0
- ;;
- mov rp=r15
-(p8) br.call.sptk.many b6=b6
- br.cond.sptk ia32_trace_syscall
-
-non_ia32_syscall:
- alloc r15=ar.pfs,0,0,2,0
- mov out0=r14 // interrupt #
- add out1=16,sp // pointer to pt_regs
- ;; // avoid WAW on CFM
- br.call.sptk.many rp=ia32_bad_interrupt
-.ret1: movl r15=ia64_leave_kernel
- ;;
- mov rp=r15
- br.ret.sptk.many rp
-END(dispatch_to_ia32_handler)
-
-#endif /* CONFIG_IA32_SUPPORT */
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [RFC 1/6] LVHPT - Remove static ivt.S
From: Ian Wienand @ 2006-05-10 3:42 UTC (permalink / raw)
To: linux-ia64; +Cc: linux-mm, Ian Wienand
In-Reply-To: <20060510034206.17792.82504.sendpatchset@wagner.orchestra.cse.unsw.EDU.AU>
LVHPT remove ivt.S
Remove ivt.S; it is dynamically generated.
Signed-Off-By: Ian Wienand <ianw@gelato.unsw.edu.au>
---
ivt.S | 1726 ------------------------------------------------------------------
1 file changed, 1726 deletions(-)
Index: linux-2.6.17-rc3-lvhpt-v2-fresh/arch/ia64/kernel/ivt.S
=================================--- linux-2.6.17-rc3-lvhpt-v2-fresh.orig/arch/ia64/kernel/ivt.S 2006-05-05 10:06:54.000000000 +1000
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,1726 +0,0 @@
-/*
- * arch/ia64/kernel/ivt.S
- *
- * Copyright (C) 1998-2001, 2003, 2005 Hewlett-Packard Co
- * Stephane Eranian <eranian@hpl.hp.com>
- * David Mosberger <davidm@hpl.hp.com>
- * Copyright (C) 2000, 2002-2003 Intel Co
- * Asit Mallick <asit.k.mallick@intel.com>
- * Suresh Siddha <suresh.b.siddha@intel.com>
- * Kenneth Chen <kenneth.w.chen@intel.com>
- * Fenghua Yu <fenghua.yu@intel.com>
- *
- * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling for SMP
- * 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB handler now uses virtual PT.
- */
-/*
- * This file defines the interruption vector table used by the CPU.
- * It does not include one entry per possible cause of interruption.
- *
- * The first 20 entries of the table contain 64 bundles each while the
- * remaining 48 entries contain only 16 bundles each.
- *
- * The 64 bundles are used to allow inlining the whole handler for critical
- * interruptions like TLB misses.
- *
- * For each entry, the comment is as follows:
- *
- * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
- * entry offset ----/ / / / /
- * entry number ---------/ / / /
- * size of the entry -------------/ / /
- * vector name -------------------------------------/ /
- * interruptions triggering this vector ----------------------/
- *
- * The table is 32KB in size and must be aligned on 32KB boundary.
- * (The CPU ignores the 15 lower bits of the address)
- *
- * Table is based upon EAS2.6 (Oct 1999)
- */
-
-#include <linux/config.h>
-
-#include <asm/asmmacro.h>
-#include <asm/break.h>
-#include <asm/ia32.h>
-#include <asm/kregs.h>
-#include <asm/asm-offsets.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/system.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/errno.h>
-
-#if 1
-# define PSR_DEFAULT_BITS psr.ac
-#else
-# define PSR_DEFAULT_BITS 0
-#endif
-
-#if 0
- /*
- * This lets you track the last eight faults that occurred on the CPU. Make sure ar.k2 isn't
- * needed for something else before enabling this...
- */
-# define DBG_FAULT(i) mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16
-#else
-# define DBG_FAULT(i)
-#endif
-
-#include "minstate.h"
-
-#define FAULT(n) \
- mov r31=pr; \
- mov r19=n;; /* prepare to save predicates */ \
- br.sptk.many dispatch_to_fault_handler
-
- .section .text.ivt,"ax"
-
- .align 32768 // align on 32KB boundary
- .global ia64_ivt
-ia64_ivt:
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
-ENTRY(vhpt_miss)
- DBG_FAULT(0)
- /*
- * The VHPT vector is invoked when the TLB entry for the virtual page table
- * is missing. This happens only as a result of a previous
- * (the "original") TLB miss, which may either be caused by an instruction
- * fetch or a data access (or non-access).
- *
- * What we do here is normal TLB miss handing for the _original_ miss,
- * followed by inserting the TLB entry for the virtual page table page
- * that the VHPT walker was attempting to access. The latter gets
- * inserted as long as page table entry above pte level have valid
- * mappings for the faulting address. The TLB entry for the original
- * miss gets inserted only if the pte entry indicates that the page is
- * present.
- *
- * do_page_fault gets invoked in the following cases:
- * - the faulting virtual address uses unimplemented address bits
- * - the faulting virtual address has no valid page table mapping
- */
- mov r16=cr.ifa // get address that caused the TLB miss
-#ifdef CONFIG_HUGETLB_PAGE
- movl r18=PAGE_SHIFT
- mov r25=cr.itir
-#endif
- ;;
- rsm psr.dt // use physical addressing for data
- mov r31=pr // save the predicate registers
- mov r19=IA64_KR(PT_BASE) // get page table base address
- shl r21=r16,3 // shift bit 60 into sign bit
- shr.u r17=r16,61 // get the region number into r17
- ;;
- shr.u r22=r21,3
-#ifdef CONFIG_HUGETLB_PAGE
- extr.u r26=r25,2,6
- ;;
- cmp.ne p8,p0=r18,r26
- sub r27=r26,r18
- ;;
-(p8) dep r25=r18,r25,2,6
-(p8) shr r22=r22,r27
-#endif
- ;;
- cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
- shr.u r18=r22,PGDIR_SHIFT // get bottom portion of pgd index bit
- ;;
-(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
-
- srlz.d
- LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
-
- .pred.rel "mutex", p6, p7
-(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
-(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
- ;;
-(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
-(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
- cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
-#ifdef CONFIG_PGTABLE_4
- shr.u r28=r22,PUD_SHIFT // shift pud index into position
-#else
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
-#endif
- ;;
- ld8 r17=[r17] // get *pgd (may be 0)
- ;;
-(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) = NULL?
-#ifdef CONFIG_PGTABLE_4
- dep r28=r28,r17,3,(PAGE_SHIFT-3) // r28=pud_offset(pgd,addr)
- ;;
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
-(p7) ld8 r29=[r28] // get *pud (may be 0)
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r29,r0 // was pud_present(*pud) = NULL?
- dep r17=r18,r29,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
-#else
- dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pgd,addr)
-#endif
- ;;
-(p7) ld8 r20=[r17] // get *pmd (may be 0)
- shr.u r19=r22,PAGE_SHIFT // shift pte index into position
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r20,r0 // was pmd_present(*pmd) = NULL?
- dep r21=r19,r20,3,(PAGE_SHIFT-3) // r21=pte_offset(pmd,addr)
- ;;
-(p7) ld8 r18=[r21] // read *pte
- mov r19=cr.isr // cr.isr bit 32 tells us if this is an insn miss
- ;;
-(p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared?
- mov r22=cr.iha // get the VHPT address that caused the TLB miss
- ;; // avoid RAW on p7
-(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss?
- dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address
- ;;
-(p10) itc.i r18 // insert the instruction TLB entry
-(p11) itc.d r18 // insert the data TLB entry
-(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
- mov cr.ifa=r22
-
-#ifdef CONFIG_HUGETLB_PAGE
-(p8) mov cr.itir=r25 // change to default page-size for VHPT
-#endif
-
- /*
- * Now compute and insert the TLB entry for the virtual page table. We never
- * execute in a page table page so there is no need to set the exception deferral
- * bit.
- */
- adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
- ;;
-(p7) itc.d r24
- ;;
-#ifdef CONFIG_SMP
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- /*
- * Re-check pagetable entry. If they changed, we may have received a ptc.g
- * between reading the pagetable and the "itc". If so, flush the entry we
- * inserted and retry. At this point, we have:
- *
- * r28 = equivalent of pud_offset(pgd, ifa)
- * r17 = equivalent of pmd_offset(pud, ifa)
- * r21 = equivalent of pte_offset(pmd, ifa)
- *
- * r29 = *pud
- * r20 = *pmd
- * r18 = *pte
- */
- ld8 r25=[r21] // read *pte again
- ld8 r26=[r17] // read *pmd again
-#ifdef CONFIG_PGTABLE_4
- ld8 r19=[r28] // read *pud again
-#endif
- cmp.ne p6,p7=r0,r0
- ;;
- cmp.ne.or.andcm p6,p7=r26,r20 // did *pmd change
-#ifdef CONFIG_PGTABLE_4
- cmp.ne.or.andcm p6,p7=r19,r29 // did *pud change
-#endif
- mov r27=PAGE_SHIFT<<2
- ;;
-(p6) ptc.l r22,r27 // purge PTE page translation
-(p7) cmp.ne.or.andcm p6,p7=r25,r18 // did *pte change
- ;;
-(p6) ptc.l r16,r27 // purge translation
-#endif
-
- mov pr=r31,-1 // restore predicate registers
- rfi
-END(vhpt_miss)
-
- .org ia64_ivt+0x400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
-ENTRY(itlb_miss)
- DBG_FAULT(1)
- /*
- * The ITLB handler accesses the PTE via the virtually mapped linear
- * page table. If a nested TLB miss occurs, we switch into physical
- * mode, walk the page table, and then re-execute the PTE read and
- * go on normally after that.
- */
- mov r16=cr.ifa // get virtual address
- mov r29° // save b0
- mov r31=pr // save predicates
-.itlb_fault:
- mov r17=cr.iha // get virtual address of PTE
- movl r30\x1f // load nested fault continuation point
- ;;
-1: ld8 r18=[r17] // read *pte
- ;;
- mov b0=r29
- tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.cond.spnt page_fault
- ;;
- itc.i r18
- ;;
-#ifdef CONFIG_SMP
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r19=[r17] // read *pte again and see if same
- mov r20=PAGE_SHIFT<<2 // setup page size for purge
- ;;
- cmp.ne p7,p0=r18,r19
- ;;
-(p7) ptc.l r16,r20
-#endif
- mov pr=r31,-1
- rfi
-END(itlb_miss)
-
- .org ia64_ivt+0x0800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
-ENTRY(dtlb_miss)
- DBG_FAULT(2)
- /*
- * The DTLB handler accesses the PTE via the virtually mapped linear
- * page table. If a nested TLB miss occurs, we switch into physical
- * mode, walk the page table, and then re-execute the PTE read and
- * go on normally after that.
- */
- mov r16=cr.ifa // get virtual address
- mov r29° // save b0
- mov r31=pr // save predicates
-dtlb_fault:
- mov r17=cr.iha // get virtual address of PTE
- movl r30\x1f // load nested fault continuation point
- ;;
-1: ld8 r18=[r17] // read *pte
- ;;
- mov b0=r29
- tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.cond.spnt page_fault
- ;;
- itc.d r18
- ;;
-#ifdef CONFIG_SMP
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r19=[r17] // read *pte again and see if same
- mov r20=PAGE_SHIFT<<2 // setup page size for purge
- ;;
- cmp.ne p7,p0=r18,r19
- ;;
-(p7) ptc.l r16,r20
-#endif
- mov pr=r31,-1
- rfi
-END(dtlb_miss)
-
- .org ia64_ivt+0x0c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
-ENTRY(alt_itlb_miss)
- DBG_FAULT(3)
- mov r16=cr.ifa // get address that caused the TLB miss
- movl r17=PAGE_KERNEL
- mov r21=cr.ipsr
- movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
- mov r31=pr
- ;;
-#ifdef CONFIG_DISABLE_VHPT
- shr.u r22=r16,61 // get the region number into r21
- ;;
- cmp.gt p8,p0=6,r22 // user mode
- ;;
-(p8) thash r17=r16
- ;;
-(p8) mov cr.iha=r17
-(p8) mov r29° // save b0
-(p8) br.cond.dptk .itlb_fault
-#endif
- extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
- and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
- shr.u r18=r16,57 // move address bit 61 to bit 4
- ;;
- andcm r18=0x10,r18 // bit 4=~address-bit(61)
- cmp.ne p8,p0=r0,r23 // psr.cpl != 0?
- or r19=r17,r19 // insert PTE control bits into r19
- ;;
- or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
-(p8) br.cond.spnt page_fault
- ;;
- itc.i r19 // insert the TLB entry
- mov pr=r31,-1
- rfi
-END(alt_itlb_miss)
-
- .org ia64_ivt+0x1000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
-ENTRY(alt_dtlb_miss)
- DBG_FAULT(4)
- mov r16=cr.ifa // get address that caused the TLB miss
- movl r17=PAGE_KERNEL
- mov r20=cr.isr
- movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
- mov r21=cr.ipsr
- mov r31=pr
- ;;
-#ifdef CONFIG_DISABLE_VHPT
- shr.u r22=r16,61 // get the region number into r21
- ;;
- cmp.gt p8,p0=6,r22 // access to region 0-5
- ;;
-(p8) thash r17=r16
- ;;
-(p8) mov cr.iha=r17
-(p8) mov r29° // save b0
-(p8) br.cond.dptk dtlb_fault
-#endif
- extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
- and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
- tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
- shr.u r18=r16,57 // move address bit 61 to bit 4
- and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
- tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
- ;;
- andcm r18=0x10,r18 // bit 4=~address-bit(61)
- cmp.ne p8,p0=r0,r23
-(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
-(p8) br.cond.spnt page_fault
-
- dep r21=-1,r21,IA64_PSR_ED_BIT,1
- or r19=r19,r17 // insert PTE control bits into r19
- ;;
- or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
-(p6) mov cr.ipsr=r21
- ;;
-(p7) itc.d r19 // insert the TLB entry
- mov pr=r31,-1
- rfi
-END(alt_dtlb_miss)
-
- .org ia64_ivt+0x1400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
-ENTRY(nested_dtlb_miss)
- /*
- * In the absence of kernel bugs, we get here when the virtually mapped linear
- * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
- * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page
- * table is missing, a nested TLB miss fault is triggered and control is
- * transferred to this point. When this happens, we lookup the pte for the
- * faulting address by walking the page table in physical mode and return to the
- * continuation point passed in register r30 (or call page_fault if the address is
- * not mapped).
- *
- * Input: r16: faulting address
- * r29: saved b0
- * r30: continuation address
- * r31: saved pr
- *
- * Output: r17: physical address of PTE of faulting address
- * r29: saved b0
- * r30: continuation address
- * r31: saved pr
- *
- * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared)
- */
- rsm psr.dt // switch to using physical data addressing
- mov r19=IA64_KR(PT_BASE) // get the page table base address
- shl r21=r16,3 // shift bit 60 into sign bit
- mov r18=cr.itir
- ;;
- shr.u r17=r16,61 // get the region number into r17
- extr.u r18=r18,2,6 // get the faulting page size
- ;;
- cmp.eq p6,p7=5,r17 // is faulting address in region 5?
- add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
- add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
- ;;
- shr.u r22=r16,r22
- shr.u r18=r16,r18
-(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
-
- srlz.d
- LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
-
- .pred.rel "mutex", p6, p7
-(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
-(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
- ;;
-(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
-(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
- cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
-#ifdef CONFIG_PGTABLE_4
- shr.u r18=r22,PUD_SHIFT // shift pud index into position
-#else
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
-#endif
- ;;
- ld8 r17=[r17] // get *pgd (may be 0)
- ;;
-(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) = NULL?
- dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=p[u|m]d_offset(pgd,addr)
- ;;
-#ifdef CONFIG_PGTABLE_4
-(p7) ld8 r17=[r17] // get *pud (may be 0)
- shr.u r18=r22,PMD_SHIFT // shift pmd index into position
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) = NULL?
- dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
- ;;
-#endif
-(p7) ld8 r17=[r17] // get *pmd (may be 0)
- shr.u r19=r22,PAGE_SHIFT // shift pte index into position
- ;;
-(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) = NULL?
- dep r17=r19,r17,3,(PAGE_SHIFT-3) // r17=pte_offset(pmd,addr);
-(p6) br.cond.spnt page_fault
- mov b0=r30
- br.sptk.many b0 // return to continuation point
-END(nested_dtlb_miss)
-
- .org ia64_ivt+0x1800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
-ENTRY(ikey_miss)
- DBG_FAULT(6)
- FAULT(6)
-END(ikey_miss)
-
- //-----------------------------------------------------------------------------------
- // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
-ENTRY(page_fault)
- ssm psr.dt
- ;;
- srlz.i
- ;;
- SAVE_MIN_WITH_COVER
- alloc r15=ar.pfs,0,0,3,0
- mov out0=cr.ifa
- mov out1=cr.isr
- adds r3=8,r2 // set up second base pointer
- ;;
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collectin is on
- ;;
-(p15) ssm psr.i // restore psr.i
- movl r14=ia64_leave_kernel
- ;;
- SAVE_REST
- mov rp=r14
- ;;
- adds out2\x16,r12 // out2 = pointer to pt_regs
- br.call.sptk.many b6=ia64_do_page_fault // ignore return address
-END(page_fault)
-
- .org ia64_ivt+0x1c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
-ENTRY(dkey_miss)
- DBG_FAULT(7)
- FAULT(7)
-END(dkey_miss)
-
- .org ia64_ivt+0x2000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
-ENTRY(dirty_bit)
- DBG_FAULT(8)
- /*
- * What we do here is to simply turn on the dirty bit in the PTE. We need to
- * update both the page-table and the TLB entry. To efficiently access the PTE,
- * we address it through the virtual page table. Most likely, the TLB entry for
- * the relevant virtual page table page is still present in the TLB so we can
- * normally do this without additional TLB misses. In case the necessary virtual
- * page table TLB entry isn't present, we take a nested TLB miss hit where we look
- * up the physical address of the L3 PTE and then continue at label 1 below.
- */
- mov r16=cr.ifa // get the address that caused the fault
- movl r30\x1f // load continuation point in case of nested fault
- ;;
- thash r17=r16 // compute virtual address of L3 PTE
- mov r29° // save b0 in case of nested fault
- mov r31=pr // save pr
-#ifdef CONFIG_SMP
- mov r28=ar.ccv // save ar.ccv
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- mov ar.ccv=r18 // set compare value for cmpxchg
- or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
- tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
- ;;
-(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only update if page is present
- mov r24=PAGE_SHIFT<<2
- ;;
-(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present
- ;;
-(p6) itc.d r25 // install updated PTE
- ;;
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r18=[r17] // read PTE again
- ;;
- cmp.eq p6,p7=r18,r25 // is it same as the newly installed
- ;;
-(p7) ptc.l r16,r24
- mov b0=r29 // restore b0
- mov ar.ccv=r28
-#else
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
- mov b0=r29 // restore b0
- ;;
- st8 [r17]=r18 // store back updated PTE
- itc.d r18 // install updated PTE
-#endif
- mov pr=r31,-1 // restore pr
- rfi
-END(dirty_bit)
-
- .org ia64_ivt+0x2400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
-ENTRY(iaccess_bit)
- DBG_FAULT(9)
- // Like Entry 8, except for instruction access
- mov r16=cr.ifa // get the address that caused the fault
- movl r30\x1f // load continuation point in case of nested fault
- mov r31=pr // save predicates
-#ifdef CONFIG_ITANIUM
- /*
- * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
- */
- mov r17=cr.ipsr
- ;;
- mov r18=cr.iip
- tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set?
- ;;
-(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa
-#endif /* CONFIG_ITANIUM */
- ;;
- thash r17=r16 // compute virtual address of L3 PTE
- mov r29° // save b0 in case of nested fault)
-#ifdef CONFIG_SMP
- mov r28=ar.ccv // save ar.ccv
- ;;
-1: ld8 r18=[r17]
- ;;
- mov ar.ccv=r18 // set compare value for cmpxchg
- or r25=_PAGE_A,r18 // set the accessed bit
- tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
- ;;
-(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present
- mov r24=PAGE_SHIFT<<2
- ;;
-(p6) cmp.eq p6,p7=r26,r18 // Only if page present
- ;;
-(p6) itc.i r25 // install updated PTE
- ;;
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
-
- ld8 r18=[r17] // read PTE again
- ;;
- cmp.eq p6,p7=r18,r25 // is it same as the newly installed
- ;;
-(p7) ptc.l r16,r24
- mov b0=r29 // restore b0
- mov ar.ccv=r28
-#else /* !CONFIG_SMP */
- ;;
-1: ld8 r18=[r17]
- ;;
- or r18=_PAGE_A,r18 // set the accessed bit
- mov b0=r29 // restore b0
- ;;
- st8 [r17]=r18 // store back updated PTE
- itc.i r18 // install updated PTE
-#endif /* !CONFIG_SMP */
- mov pr=r31,-1
- rfi
-END(iaccess_bit)
-
- .org ia64_ivt+0x2800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
-ENTRY(daccess_bit)
- DBG_FAULT(10)
- // Like Entry 8, except for data access
- mov r16=cr.ifa // get the address that caused the fault
- movl r30\x1f // load continuation point in case of nested fault
- ;;
- thash r17=r16 // compute virtual address of L3 PTE
- mov r31=pr
- mov r29° // save b0 in case of nested fault)
-#ifdef CONFIG_SMP
- mov r28=ar.ccv // save ar.ccv
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- mov ar.ccv=r18 // set compare value for cmpxchg
- or r25=_PAGE_A,r18 // set the dirty bit
- tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
- ;;
-(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page is present
- mov r24=PAGE_SHIFT<<2
- ;;
-(p6) cmp.eq p6,p7=r26,r18 // Only if page is present
- ;;
-(p6) itc.d r25 // install updated PTE
- /*
- * Tell the assemblers dependency-violation checker that the above "itc" instructions
- * cannot possibly affect the following loads:
- */
- dv_serialize_data
- ;;
- ld8 r18=[r17] // read PTE again
- ;;
- cmp.eq p6,p7=r18,r25 // is it same as the newly installed
- ;;
-(p7) ptc.l r16,r24
- mov ar.ccv=r28
-#else
- ;;
-1: ld8 r18=[r17]
- ;; // avoid RAW on r18
- or r18=_PAGE_A,r18 // set the accessed bit
- ;;
- st8 [r17]=r18 // store back updated PTE
- itc.d r18 // install updated PTE
-#endif
- mov b0=r29 // restore b0
- mov pr=r31,-1
- rfi
-END(daccess_bit)
-
- .org ia64_ivt+0x2c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
-ENTRY(break_fault)
- /*
- * The streamlined system call entry/exit paths only save/restore the initial part
- * of pt_regs. This implies that the callers of system-calls must adhere to the
- * normal procedure calling conventions.
- *
- * Registers to be saved & restored:
- * CR registers: cr.ipsr, cr.iip, cr.ifs
- * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr
- * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15
- * Registers to be restored only:
- * r8-r11: output value from the system call.
- *
- * During system call exit, scratch registers (including r15) are modified/cleared
- * to prevent leaking bits from kernel to user level.
- */
- DBG_FAULT(11)
- mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc)
- mov r29=cr.ipsr // M2 (12 cyc)
- mov r31=pr // I0 (2 cyc)
-
- mov r17=cr.iim // M2 (2 cyc)
- mov.m r27=ar.rsc // M2 (12 cyc)
- mov r18=__IA64_BREAK_SYSCALL // A
-
- mov.m ar.rsc=0 // M2
- mov.m r21=ar.fpsr // M2 (12 cyc)
- mov r19¶ // I0 (2 cyc)
- ;;
- mov.m r23=ar.bspstore // M2 (12 cyc)
- mov.m r24=ar.rnat // M2 (5 cyc)
- mov.i r26=ar.pfs // I0 (2 cyc)
-
- invala // M0|1
- nop.m 0 // M
- mov r20=r1 // A save r1
-
- nop.m 0
- movl r30=sys_call_table // X
-
- mov r28=cr.iip // M2 (2 cyc)
- cmp.eq p0,p7=r18,r17 // I0 is this a system call?
-(p7) br.cond.spnt non_syscall // B no ->
- //
- // From this point on, we are definitely on the syscall-path
- // and we can use (non-banked) scratch registers.
- //
-///////////////////////////////////////////////////////////////////////
- mov r1=r16 // A move task-pointer to "addl"-addressable reg
- mov r2=r16 // A setup r2 for ia64_syscall_setup
- add r9=TI_FLAGS+IA64_TASK_SIZE,r16 // A r9 = ¤t_thread_info()->flags
-
- adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16
- adds r15=-1024,r15 // A subtract 1024 from syscall number
- mov r3=NR_syscalls - 1
- ;;
- ld1.bias r17=[r16] // M0|1 r17 = current->thread.on_ustack flag
- ld4 r9=[r9] // M0|1 r9 = current_thread_info()->flags
- extr.u r8=r29,41,2 // I0 extract ei field from cr.ipsr
-
- shladd r30=r15,3,r30 // A r30 = sys_call_table + 8*(syscall-1024)
- addl r22=IA64_RBS_OFFSET,r1 // A compute base of RBS
- cmp.leu p6,p7=r15,r3 // A syscall number in range?
- ;;
-
- lfetch.fault.excl.nt1 [r22] // M0|1 prefetch RBS
-(p6) ld8 r30=[r30] // M0|1 load address of syscall entry point
- tnat.nz.or p7,p0=r15 // I0 is syscall nr a NaT?
-
- mov.m ar.bspstore=r22 // M2 switch to kernel RBS
- cmp.eq p8,p9=2,r8 // A isr.ei=2?
- ;;
-
-(p8) mov r8=0 // A clear ei to 0
-(p7) movl r30=sys_ni_syscall // X
-
-(p8) adds r28\x16,r28 // A switch cr.iip to next bundle
-(p9) adds r8=1,r8 // A increment ei to next slot
- nop.i 0
- ;;
-
- mov.m r25=ar.unat // M2 (5 cyc)
- dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr
- adds r15\x1024,r15 // A restore original syscall number
- //
- // If any of the above loads miss in L1D, we'll stall here until
- // the data arrives.
- //
-///////////////////////////////////////////////////////////////////////
- st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag
- mov b6=r30 // I0 setup syscall handler branch reg early
- cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already?
-
- and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit
- mov r18=ar.bsp // M2 (12 cyc)
-(pKStk) br.cond.spnt .break_fixup // B we're already in kernel-mode -- fix up RBS
- ;;
-.back_from_break_fixup:
-(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A compute base of memory stack
- cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited?
- br.call.sptk.many b7=ia64_syscall_setup // B
-1:
- mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
- nop 0
- bsw.1 // B (6 cyc) regs are saved, switch to bank 1
- ;;
-
- ssm psr.ic | PSR_DEFAULT_BITS // M2 now it's safe to re-enable intr.-collection
- movl r3=ia64_ret_from_syscall // X
- ;;
-
- srlz.i // M0 ensure interruption collection is on
- mov rp=r3 // I0 set the real return addr
-(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT
-
-(p15) ssm psr.i // M2 restore psr.i
-(p14) br.call.sptk.many b6¶ // B invoke syscall-handker (ignore return addr)
- br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic
- // NOT REACHED
-///////////////////////////////////////////////////////////////////////
- // On entry, we optimistically assumed that we're coming from user-space.
- // For the rare cases where a system-call is done from within the kernel,
- // we fix things up at this point:
-.break_fixup:
- add r1=-IA64_PT_REGS_SIZE,sp // A allocate space for pt_regs structure
- mov ar.rnat=r24 // M2 restore kernel's AR.RNAT
- ;;
- mov ar.bspstore=r23 // M2 restore kernel's AR.BSPSTORE
- br.cond.sptk .back_from_break_fixup
-END(break_fault)
-
- .org ia64_ivt+0x3000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
-ENTRY(interrupt)
- DBG_FAULT(12)
- mov r31=pr // prepare to save predicates
- ;;
- SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- adds r3=8,r2 // set up second base pointer for SAVE_REST
- srlz.i // ensure everybody knows psr.ic is back on
- ;;
- SAVE_REST
- ;;
- MCA_RECOVER_RANGE(interrupt)
- alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
- mov out0=cr.ivr // pass cr.ivr as first arg
- add out1\x16,sp // pass pointer to pt_regs as second arg
- ;;
- srlz.d // make sure we see the effect of cr.ivr
- movl r14=ia64_leave_kernel
- ;;
- mov rp=r14
- br.call.sptk.many b6=ia64_handle_irq
-END(interrupt)
-
- .org ia64_ivt+0x3400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3400 Entry 13 (size 64 bundles) Reserved
- DBG_FAULT(13)
- FAULT(13)
-
- .org ia64_ivt+0x3800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3800 Entry 14 (size 64 bundles) Reserved
- DBG_FAULT(14)
- FAULT(14)
-
- /*
- * There is no particular reason for this code to be here, other than that
- * there happens to be space here that would go unused otherwise. If this
- * fault ever gets "unreserved", simply moved the following code to a more
- * suitable spot...
- *
- * ia64_syscall_setup() is a separate subroutine so that it can
- * allocate stacked registers so it can safely demine any
- * potential NaT values from the input registers.
- *
- * On entry:
- * - executing on bank 0 or bank 1 register set (doesn't matter)
- * - r1: stack pointer
- * - r2: current task pointer
- * - r3: preserved
- * - r11: original contents (saved ar.pfs to be saved)
- * - r12: original contents (sp to be saved)
- * - r13: original contents (tp to be saved)
- * - r15: original contents (syscall # to be saved)
- * - r18: saved bsp (after switching to kernel stack)
- * - r19: saved b6
- * - r20: saved r1 (gp)
- * - r21: saved ar.fpsr
- * - r22: kernel's register backing store base (krbs_base)
- * - r23: saved ar.bspstore
- * - r24: saved ar.rnat
- * - r25: saved ar.unat
- * - r26: saved ar.pfs
- * - r27: saved ar.rsc
- * - r28: saved cr.iip
- * - r29: saved cr.ipsr
- * - r31: saved pr
- * - b0: original contents (to be saved)
- * On exit:
- * - p10: TRUE if syscall is invoked with more than 8 out
- * registers or r15's Nat is true
- * - r1: kernel's gp
- * - r3: preserved (same as on entry)
- * - r8: -EINVAL if p10 is true
- * - r12: points to kernel stack
- * - r13: points to current task
- * - r14: preserved (same as on entry)
- * - p13: preserved
- * - p15: TRUE if interrupts need to be re-enabled
- * - ar.fpsr: set to kernel settings
- * - b6: preserved (same as on entry)
- */
-GLOBAL_ENTRY(ia64_syscall_setup)
-#if PT(B6) != 0
-# error This code assumes that b6 is the first field in pt_regs.
-#endif
- st8 [r1]=r19 // save b6
- add r16=PT(CR_IPSR),r1 // initialize first base pointer
- add r17=PT(R11),r1 // initialize second base pointer
- ;;
- alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable
- st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr
- tnat.nz p8,p0=in0
-
- st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11
- tnat.nz p9,p0=in1
-(pKStk) mov r18=r0 // make sure r18 isn't NaT
- ;;
-
- st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs
- st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip
- mov r28° // save b0 (2 cyc)
- ;;
-
- st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat
- dep r19=0,r19,38,26 // clear all bits but 0..37 [I0]
-(p8) mov in0=-1
- ;;
-
- st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs
- extr.u r11=r19,7,7 // I0 // get sol of ar.pfs
- and r8=0x7f,r19 // A // get sof of ar.pfs
-
- st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc
- tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0
-(p9) mov in1=-1
- ;;
-
-(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8
- tnat.nz p10,p0=in2
- add r11=8,r11
- ;;
-(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field
-(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field
- tnat.nz p11,p0=in3
- ;;
-(p10) mov in2=-1
- tnat.nz p12,p0=in4 // [I0]
-(p11) mov in3=-1
- ;;
-(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat
-(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore
- shl r18=r18,16 // compute ar.rsc to be used for "loadrs"
- ;;
- st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates
- st8 [r17]=r28,PT(R1)-PT(B0) // save b0
- tnat.nz p13,p0=in5 // [I0]
- ;;
- st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs"
- st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1
-(p12) mov in4=-1
- ;;
-
-.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12
-.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13
-(p13) mov in5=-1
- ;;
- st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr
- tnat.nz p13,p0=in6
- cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8
- ;;
- mov r8=1
-(p9) tnat.nz p10,p0=r15
- adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch)
-
- st8.spill [r17]=r15 // save r15
- tnat.nz p8,p0=in7
- nop.i 0
-
- mov r13=r2 // establish `current'
- movl r1=__gp // establish kernel global pointer
- ;;
- st8 [r16]=r8 // ensure pt_regs.r8 != 0 (see handle_syscall_error)
-(p13) mov in6=-1
-(p8) mov in7=-1
-
- cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
- movl r17=FPSR_DEFAULT
- ;;
- mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value
-(p10) mov r8=-EINVAL
- br.ret.sptk.many b7
-END(ia64_syscall_setup)
-
- .org ia64_ivt+0x3c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x3c00 Entry 15 (size 64 bundles) Reserved
- DBG_FAULT(15)
- FAULT(15)
-
- /*
- * Squatting in this space ...
- *
- * This special case dispatcher for illegal operation faults allows preserved
- * registers to be modified through a callback function (asm only) that is handed
- * back from the fault handler in r8. Up to three arguments can be passed to the
- * callback function by returning an aggregate with the callback as its first
- * element, followed by the arguments.
- */
-ENTRY(dispatch_illegal_op_fault)
- .prologue
- .body
- SAVE_MIN_WITH_COVER
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
-(p15) ssm psr.i // restore psr.i
- adds r3=8,r2 // set up second base pointer for SAVE_REST
- ;;
- alloc r14=ar.pfs,0,0,1,0 // must be first in insn group
- mov out0=ar.ec
- ;;
- SAVE_REST
- PT_REGS_UNWIND_INFO(0)
- ;;
- br.call.sptk.many rp=ia64_illegal_op_fault
-.ret0: ;;
- alloc r14=ar.pfs,0,0,3,0 // must be first in insn group
- mov out0=r9
- mov out1=r10
- mov out2=r11
- movl r15=ia64_leave_kernel
- ;;
- mov rp=r15
- mov b6=r8
- ;;
- cmp.ne p6,p0=0,r8
-(p6) br.call.dpnt.many b6¶ // call returns to ia64_leave_kernel
- br.sptk.many ia64_leave_kernel
-END(dispatch_illegal_op_fault)
-
- .org ia64_ivt+0x4000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4000 Entry 16 (size 64 bundles) Reserved
- DBG_FAULT(16)
- FAULT(16)
-
- .org ia64_ivt+0x4400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4400 Entry 17 (size 64 bundles) Reserved
- DBG_FAULT(17)
- FAULT(17)
-
-ENTRY(non_syscall)
- mov ar.rsc=r27 // restore ar.rsc before SAVE_MIN_WITH_COVER
- ;;
- SAVE_MIN_WITH_COVER
-
- // There is no particular reason for this code to be here, other than that
- // there happens to be space here that would go unused otherwise. If this
- // fault ever gets "unreserved", simply moved the following code to a more
- // suitable spot...
-
- alloc r14=ar.pfs,0,0,2,0
- mov out0=cr.iim
- add out1\x16,sp
- adds r3=8,r2 // set up second base pointer for SAVE_REST
-
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
-(p15) ssm psr.i // restore psr.i
- movl r15=ia64_leave_kernel
- ;;
- SAVE_REST
- mov rp=r15
- ;;
- br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr
-END(non_syscall)
-
- .org ia64_ivt+0x4800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4800 Entry 18 (size 64 bundles) Reserved
- DBG_FAULT(18)
- FAULT(18)
-
- /*
- * There is no particular reason for this code to be here, other than that
- * there happens to be space here that would go unused otherwise. If this
- * fault ever gets "unreserved", simply moved the following code to a more
- * suitable spot...
- */
-
-ENTRY(dispatch_unaligned_handler)
- SAVE_MIN_WITH_COVER
- ;;
- alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
- mov out0=cr.ifa
- adds out1\x16,sp
-
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
-(p15) ssm psr.i // restore psr.i
- adds r3=8,r2 // set up second base pointer
- ;;
- SAVE_REST
- movl r14=ia64_leave_kernel
- ;;
- mov rp=r14
- br.sptk.many ia64_prepare_handle_unaligned
-END(dispatch_unaligned_handler)
-
- .org ia64_ivt+0x4c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x4c00 Entry 19 (size 64 bundles) Reserved
- DBG_FAULT(19)
- FAULT(19)
-
- /*
- * There is no particular reason for this code to be here, other than that
- * there happens to be space here that would go unused otherwise. If this
- * fault ever gets "unreserved", simply moved the following code to a more
- * suitable spot...
- */
-
-ENTRY(dispatch_to_fault_handler)
- /*
- * Input:
- * psr.ic: off
- * r19: fault vector number (e.g., 24 for General Exception)
- * r31: contains saved predicates (pr)
- */
- SAVE_MIN_WITH_COVER_R19
- alloc r14=ar.pfs,0,0,5,0
- mov out0=r15
- mov out1=cr.isr
- mov out2=cr.ifa
- mov out3=cr.iim
- mov out4=cr.itir
- ;;
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
-(p15) ssm psr.i // restore psr.i
- adds r3=8,r2 // set up second base pointer for SAVE_REST
- ;;
- SAVE_REST
- movl r14=ia64_leave_kernel
- ;;
- mov rp=r14
- br.call.sptk.many b6=ia64_fault
-END(dispatch_to_fault_handler)
-
-//
-// --- End of long entries, Beginning of short entries
-//
-
- .org ia64_ivt+0x5000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
-ENTRY(page_not_present)
- DBG_FAULT(20)
- mov r16=cr.ifa
- rsm psr.dt
- /*
- * The Linux page fault handler doesn't expect non-present pages to be in
- * the TLB. Flush the existing entry now, so we meet that expectation.
- */
- mov r17=PAGE_SHIFT<<2
- ;;
- ptc.l r16,r17
- ;;
- mov r31=pr
- srlz.d
- br.sptk.many page_fault
-END(page_not_present)
-
- .org ia64_ivt+0x5100
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
-ENTRY(key_permission)
- DBG_FAULT(21)
- mov r16=cr.ifa
- rsm psr.dt
- mov r31=pr
- ;;
- srlz.d
- br.sptk.many page_fault
-END(key_permission)
-
- .org ia64_ivt+0x5200
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
-ENTRY(iaccess_rights)
- DBG_FAULT(22)
- mov r16=cr.ifa
- rsm psr.dt
- mov r31=pr
- ;;
- srlz.d
- br.sptk.many page_fault
-END(iaccess_rights)
-
- .org ia64_ivt+0x5300
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
-ENTRY(daccess_rights)
- DBG_FAULT(23)
- mov r16=cr.ifa
- rsm psr.dt
- mov r31=pr
- ;;
- srlz.d
- br.sptk.many page_fault
-END(daccess_rights)
-
- .org ia64_ivt+0x5400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
-ENTRY(general_exception)
- DBG_FAULT(24)
- mov r16=cr.isr
- mov r31=pr
- ;;
- cmp4.eq p6,p0=0,r16
-(p6) br.sptk.many dispatch_illegal_op_fault
- ;;
- mov r19$ // fault number
- br.sptk.many dispatch_to_fault_handler
-END(general_exception)
-
- .org ia64_ivt+0x5500
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
-ENTRY(disabled_fp_reg)
- DBG_FAULT(25)
- rsm psr.dfh // ensure we can access fph
- ;;
- srlz.d
- mov r31=pr
- mov r19%
- br.sptk.many dispatch_to_fault_handler
-END(disabled_fp_reg)
-
- .org ia64_ivt+0x5600
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
-ENTRY(nat_consumption)
- DBG_FAULT(26)
-
- mov r16=cr.ipsr
- mov r17=cr.isr
- mov r31=pr // save PR
- ;;
- and r18=0xf,r17 // r18 = cr.ipsr.code{3:0}
- tbit.z p6,p0=r17,IA64_ISR_NA_BIT
- ;;
- cmp.ne.or p6,p0=IA64_ISR_CODE_LFETCH,r18
- dep r16=-1,r16,IA64_PSR_ED_BIT,1
-(p6) br.cond.spnt 1f // branch if (cr.ispr.na = 0 || cr.ipsr.code{3:0} != LFETCH)
- ;;
- mov cr.ipsr=r16 // set cr.ipsr.na
- mov pr=r31,-1
- ;;
- rfi
-
-1: mov pr=r31,-1
- ;;
- FAULT(26)
-END(nat_consumption)
-
- .org ia64_ivt+0x5700
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
-ENTRY(speculation_vector)
- DBG_FAULT(27)
- /*
- * A [f]chk.[as] instruction needs to take the branch to the recovery code but
- * this part of the architecture is not implemented in hardware on some CPUs, such
- * as Itanium. Thus, in general we need to emulate the behavior. IIM contains
- * the relative target (not yet sign extended). So after sign extending it we
- * simply add it to IIP. We also need to reset the EI field of the IPSR to zero,
- * i.e., the slot to restart into.
- *
- * cr.imm contains zero_ext(imm21)
- */
- mov r18=cr.iim
- ;;
- mov r17=cr.iip
- shl r18=r18,43 // put sign bit in position (43d-21)
- ;;
-
- mov r16=cr.ipsr
- shr r18=r18,39 // sign extend (39C-4)
- ;;
-
- add r17=r17,r18 // now add the offset
- ;;
- mov cr.iip=r17
- dep r16=0,r16,41,2 // clear EI
- ;;
-
- mov cr.ipsr=r16
- ;;
-
- rfi // and go back
-END(speculation_vector)
-
- .org ia64_ivt+0x5800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5800 Entry 28 (size 16 bundles) Reserved
- DBG_FAULT(28)
- FAULT(28)
-
- .org ia64_ivt+0x5900
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
-ENTRY(debug_vector)
- DBG_FAULT(29)
- FAULT(29)
-END(debug_vector)
-
- .org ia64_ivt+0x5a00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
-ENTRY(unaligned_access)
- DBG_FAULT(30)
- mov r31=pr // prepare to save predicates
- ;;
- br.sptk.many dispatch_unaligned_handler
-END(unaligned_access)
-
- .org ia64_ivt+0x5b00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
-ENTRY(unsupported_data_reference)
- DBG_FAULT(31)
- FAULT(31)
-END(unsupported_data_reference)
-
- .org ia64_ivt+0x5c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
-ENTRY(floating_point_fault)
- DBG_FAULT(32)
- FAULT(32)
-END(floating_point_fault)
-
- .org ia64_ivt+0x5d00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
-ENTRY(floating_point_trap)
- DBG_FAULT(33)
- FAULT(33)
-END(floating_point_trap)
-
- .org ia64_ivt+0x5e00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
-ENTRY(lower_privilege_trap)
- DBG_FAULT(34)
- FAULT(34)
-END(lower_privilege_trap)
-
- .org ia64_ivt+0x5f00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
-ENTRY(taken_branch_trap)
- DBG_FAULT(35)
- FAULT(35)
-END(taken_branch_trap)
-
- .org ia64_ivt+0x6000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
-ENTRY(single_step_trap)
- DBG_FAULT(36)
- FAULT(36)
-END(single_step_trap)
-
- .org ia64_ivt+0x6100
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6100 Entry 37 (size 16 bundles) Reserved
- DBG_FAULT(37)
- FAULT(37)
-
- .org ia64_ivt+0x6200
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6200 Entry 38 (size 16 bundles) Reserved
- DBG_FAULT(38)
- FAULT(38)
-
- .org ia64_ivt+0x6300
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6300 Entry 39 (size 16 bundles) Reserved
- DBG_FAULT(39)
- FAULT(39)
-
- .org ia64_ivt+0x6400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6400 Entry 40 (size 16 bundles) Reserved
- DBG_FAULT(40)
- FAULT(40)
-
- .org ia64_ivt+0x6500
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6500 Entry 41 (size 16 bundles) Reserved
- DBG_FAULT(41)
- FAULT(41)
-
- .org ia64_ivt+0x6600
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6600 Entry 42 (size 16 bundles) Reserved
- DBG_FAULT(42)
- FAULT(42)
-
- .org ia64_ivt+0x6700
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6700 Entry 43 (size 16 bundles) Reserved
- DBG_FAULT(43)
- FAULT(43)
-
- .org ia64_ivt+0x6800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6800 Entry 44 (size 16 bundles) Reserved
- DBG_FAULT(44)
- FAULT(44)
-
- .org ia64_ivt+0x6900
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
-ENTRY(ia32_exception)
- DBG_FAULT(45)
- FAULT(45)
-END(ia32_exception)
-
- .org ia64_ivt+0x6a00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
-ENTRY(ia32_intercept)
- DBG_FAULT(46)
-#ifdef CONFIG_IA32_SUPPORT
- mov r31=pr
- mov r16=cr.isr
- ;;
- extr.u r17=r16,16,8 // get ISR.code
- mov r18=ar.eflag
- mov r19=cr.iim // old eflag value
- ;;
- cmp.ne p6,p0=2,r17
-(p6) br.cond.spnt 1f // not a system flag fault
- xor r16=r18,r19
- ;;
- extr.u r17=r16,18,1 // get the eflags.ac bit
- ;;
- cmp.eq p6,p0=0,r17
-(p6) br.cond.spnt 1f // eflags.ac bit didn't change
- ;;
- mov pr=r31,-1 // restore predicate registers
- rfi
-
-1:
-#endif // CONFIG_IA32_SUPPORT
- FAULT(46)
-END(ia32_intercept)
-
- .org ia64_ivt+0x6b00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74)
-ENTRY(ia32_interrupt)
- DBG_FAULT(47)
-#ifdef CONFIG_IA32_SUPPORT
- mov r31=pr
- br.sptk.many dispatch_to_ia32_handler
-#else
- FAULT(47)
-#endif
-END(ia32_interrupt)
-
- .org ia64_ivt+0x6c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6c00 Entry 48 (size 16 bundles) Reserved
- DBG_FAULT(48)
- FAULT(48)
-
- .org ia64_ivt+0x6d00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6d00 Entry 49 (size 16 bundles) Reserved
- DBG_FAULT(49)
- FAULT(49)
-
- .org ia64_ivt+0x6e00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6e00 Entry 50 (size 16 bundles) Reserved
- DBG_FAULT(50)
- FAULT(50)
-
- .org ia64_ivt+0x6f00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x6f00 Entry 51 (size 16 bundles) Reserved
- DBG_FAULT(51)
- FAULT(51)
-
- .org ia64_ivt+0x7000
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7000 Entry 52 (size 16 bundles) Reserved
- DBG_FAULT(52)
- FAULT(52)
-
- .org ia64_ivt+0x7100
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7100 Entry 53 (size 16 bundles) Reserved
- DBG_FAULT(53)
- FAULT(53)
-
- .org ia64_ivt+0x7200
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7200 Entry 54 (size 16 bundles) Reserved
- DBG_FAULT(54)
- FAULT(54)
-
- .org ia64_ivt+0x7300
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7300 Entry 55 (size 16 bundles) Reserved
- DBG_FAULT(55)
- FAULT(55)
-
- .org ia64_ivt+0x7400
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7400 Entry 56 (size 16 bundles) Reserved
- DBG_FAULT(56)
- FAULT(56)
-
- .org ia64_ivt+0x7500
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7500 Entry 57 (size 16 bundles) Reserved
- DBG_FAULT(57)
- FAULT(57)
-
- .org ia64_ivt+0x7600
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7600 Entry 58 (size 16 bundles) Reserved
- DBG_FAULT(58)
- FAULT(58)
-
- .org ia64_ivt+0x7700
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7700 Entry 59 (size 16 bundles) Reserved
- DBG_FAULT(59)
- FAULT(59)
-
- .org ia64_ivt+0x7800
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7800 Entry 60 (size 16 bundles) Reserved
- DBG_FAULT(60)
- FAULT(60)
-
- .org ia64_ivt+0x7900
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7900 Entry 61 (size 16 bundles) Reserved
- DBG_FAULT(61)
- FAULT(61)
-
- .org ia64_ivt+0x7a00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7a00 Entry 62 (size 16 bundles) Reserved
- DBG_FAULT(62)
- FAULT(62)
-
- .org ia64_ivt+0x7b00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7b00 Entry 63 (size 16 bundles) Reserved
- DBG_FAULT(63)
- FAULT(63)
-
- .org ia64_ivt+0x7c00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7c00 Entry 64 (size 16 bundles) Reserved
- DBG_FAULT(64)
- FAULT(64)
-
- .org ia64_ivt+0x7d00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7d00 Entry 65 (size 16 bundles) Reserved
- DBG_FAULT(65)
- FAULT(65)
-
- .org ia64_ivt+0x7e00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7e00 Entry 66 (size 16 bundles) Reserved
- DBG_FAULT(66)
- FAULT(66)
-
- .org ia64_ivt+0x7f00
-/////////////////////////////////////////////////////////////////////////////////////////
-// 0x7f00 Entry 67 (size 16 bundles) Reserved
- DBG_FAULT(67)
- FAULT(67)
-
-#ifdef CONFIG_IA32_SUPPORT
-
- /*
- * There is no particular reason for this code to be here, other than that
- * there happens to be space here that would go unused otherwise. If this
- * fault ever gets "unreserved", simply moved the following code to a more
- * suitable spot...
- */
-
- // IA32 interrupt entry point
-
-ENTRY(dispatch_to_ia32_handler)
- SAVE_MIN
- ;;
- mov r14=cr.isr
- ssm psr.ic | PSR_DEFAULT_BITS
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
-(p15) ssm psr.i
- adds r3=8,r2 // Base pointer for SAVE_REST
- ;;
- SAVE_REST
- ;;
- mov r15=0x80
- shr r14=r14,16 // Get interrupt number
- ;;
- cmp.ne p6,p0=r14,r15
-(p6) br.call.dpnt.many b6=non_ia32_syscall
-
- adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions
- adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
- ;;
- cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
- ld8 r8=[r14] // get r8
- ;;
- st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP)
- ;;
- alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
- ;;
- ld4 r8=[r14],8 // r8 = eax (syscall number)
- mov r15=IA32_NR_syscalls
- ;;
- cmp.ltu.unc p6,p7=r8,r15
- ld4 out1=[r14],8 // r9 = ecx
- ;;
- ld4 out2=[r14],8 // r10 = edx
- ;;
- ld4 out0=[r14] // r11 = ebx
- adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp
- ;;
- ld4 out5=[r14],PT(R14)-PT(R13) // r13 = ebp
- ;;
- ld4 out3=[r14],PT(R15)-PT(R14) // r14 = esi
- adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
- ;;
- ld4 out4=[r14] // r15 = edi
- movl r16=ia32_syscall_table
- ;;
-(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
- ld4 r2=[r2] // r2 = current_thread_info()->flags
- ;;
- ld8 r16=[r16]
- and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit
- ;;
- mov b6=r16
- movl r15=ia32_ret_from_syscall
- cmp.eq p8,p0=r2,r0
- ;;
- mov rp=r15
-(p8) br.call.sptk.many b6¶
- br.cond.sptk ia32_trace_syscall
-
-non_ia32_syscall:
- alloc r15=ar.pfs,0,0,2,0
- mov out0=r14 // interrupt #
- add out1\x16,sp // pointer to pt_regs
- ;; // avoid WAW on CFM
- br.call.sptk.many rp=ia32_bad_interrupt
-.ret1: movl r15=ia64_leave_kernel
- ;;
- mov rp=r15
- br.ret.sptk.many rp
-END(dispatch_to_ia32_handler)
-
-#endif /* CONFIG_IA32_SUPPORT */
^ permalink raw reply
* [RFC 0/6] IA64 Long Format VHPT support v2
From: Ian Wienand @ 2006-05-10 3:42 UTC (permalink / raw)
To: linux-ia64; +Cc: linux-mm, Ian Wienand
Hi,
Following from this message are patches to enable the Long Format VHPT
on IA64, version 2, which I am posting in the hope of community
review. They are against 2.6.17-rc3
The major changes
* Create ivt.S dynamically from include files
* Re-jig Kconfig text
* Split into more patches
* Split out most functions into lvhpt.c/lvhpt.h
* Split find_largest_page into separate patch
I think overall, this version should be clearer. I still have TODO's
related to mca handlers, but I would appreciate comments on this
updated version.
-i
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [RFC 0/6] IA64 Long Format VHPT support v2
From: Ian Wienand @ 2006-05-10 3:42 UTC (permalink / raw)
To: linux-ia64; +Cc: linux-mm, Ian Wienand
Hi,
Following from this message are patches to enable the Long Format VHPT
on IA64, version 2, which I am posting in the hope of community
review. They are against 2.6.17-rc3
The major changes
* Create ivt.S dynamically from include files
* Re-jig Kconfig text
* Split into more patches
* Split out most functions into lvhpt.c/lvhpt.h
* Split find_largest_page into separate patch
I think overall, this version should be clearer. I still have TODO's
related to mca handlers, but I would appreciate comments on this
updated version.
-i
^ permalink raw reply
* [PATCH] Allow for per-cpu data being in .tdata and .tbss sections
From: Paul Mackerras @ 2006-05-10 3:32 UTC (permalink / raw)
To: akpm, linux-kernel; +Cc: linux-arch, rusty
This lays the groundwork for using __thread for per-cpu variables.
The toolchain will put initialized __thread variables into a .tdata
section, and uninitialized __thread variables into a .tbss section.
Thus the module loader needs to cope with two per-cpu sections, of
which one is initialized and the other must be zeroed.
With this patch, the module loader looks for .tdata and .tbss, and if
it finds neither, falls back to the .data.percpu section that we
currently use. This patch extends the various percpu_modcopy
implementations to take two size parameters: the first is the amount
to initialize and the second is the amount to zero following that.
At the moment all percpu_modcopy implementations simply check that
the amount to zero is zero.
I have a following patch that makes 64-bit powerpc use __thread for
per-cpu variables.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index 3a30cfc..88790f4 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -944,9 +944,11 @@ module_arch_cleanup (struct module *mod)
#ifdef CONFIG_SMP
void
-percpu_modcopy (void *pcpudst, const void *src, unsigned long size)
+percpu_modcopy (void *pcpudst, const void *src, unsigned long size,
+ unsigned long zero_size)
{
unsigned int i;
+ BUG_ON(zero_size != 0);
for_each_possible_cpu(i) {
memcpy(pcpudst + __per_cpu_offset[i], src, size);
}
diff --git a/include/asm-ia64/percpu.h b/include/asm-ia64/percpu.h
index 4bfbeb4..f0a679e 100644
--- a/include/asm-ia64/percpu.h
+++ b/include/asm-ia64/percpu.h
@@ -45,7 +45,8 @@ #define per_cpu(var, cpu) (*RELOC_HIDE(
#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __ia64_per_cpu_var(local_per_cpu_offset)))
#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __ia64_per_cpu_var(local_per_cpu_offset)))
-extern void percpu_modcopy(void *pcpudst, const void *src, unsigned long size);
+extern void percpu_modcopy(void *pcpudst, const void *src,
+ unsigned long init_sz, unsigned long zero_sz);
extern void setup_per_cpu_areas (void);
extern void *per_cpu_init(void);
diff --git a/include/asm-powerpc/percpu.h b/include/asm-powerpc/percpu.h
index faa1fc7..5d603ff 100644
--- a/include/asm-powerpc/percpu.h
+++ b/include/asm-powerpc/percpu.h
@@ -25,9 +25,10 @@ #define __get_cpu_var(var) (*RELOC_HIDE(
#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
/* A macro to avoid #include hell... */
-#define percpu_modcopy(pcpudst, src, size) \
+#define percpu_modcopy(pcpudst, src, size, zero_size) \
do { \
unsigned int __i; \
+ BUG_ON(zero_size != 0); \
for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset(__i), \
(src), (size)); \
diff --git a/include/asm-s390/percpu.h b/include/asm-s390/percpu.h
index d9a8cca..c443986 100644
--- a/include/asm-s390/percpu.h
+++ b/include/asm-s390/percpu.h
@@ -44,9 +44,10 @@ #define __raw_get_cpu_var(var) __reloc_h
#define per_cpu(var,cpu) __reloc_hide(var,__per_cpu_offset[cpu])
/* A macro to avoid #include hell... */
-#define percpu_modcopy(pcpudst, src, size) \
+#define percpu_modcopy(pcpudst, src, size, zero_size) \
do { \
unsigned int __i; \
+ BUG_ON(zero_size != 0); \
for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset[__i], \
(src), (size)); \
diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
index a6ece06..21f9b01 100644
--- a/include/asm-sparc64/percpu.h
+++ b/include/asm-sparc64/percpu.h
@@ -24,9 +24,10 @@ #define __get_cpu_var(var) (*RELOC_HIDE(
#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __local_per_cpu_offset))
/* A macro to avoid #include hell... */
-#define percpu_modcopy(pcpudst, src, size) \
+#define percpu_modcopy(pcpudst, src, size, zero_size) \
do { \
unsigned int __i; \
+ BUG_ON(zero_size != 0); \
for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset(__i), \
(src), (size)); \
diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h
index 549eb92..0e6ffde 100644
--- a/include/asm-x86_64/percpu.h
+++ b/include/asm-x86_64/percpu.h
@@ -24,9 +24,10 @@ #define __get_cpu_var(var) (*RELOC_HIDE(
#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
/* A macro to avoid #include hell... */
-#define percpu_modcopy(pcpudst, src, size) \
+#define percpu_modcopy(pcpudst, src, size, zero_size) \
do { \
unsigned int __i; \
+ BUG_ON(zero_size != 0); \
for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset(__i), \
(src), (size)); \
diff --git a/kernel/module.c b/kernel/module.c
index d24deb0..4986e06 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -354,11 +354,28 @@ static void percpu_modfree(void *freeme)
}
}
-static unsigned int find_pcpusec(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- const char *secstrings)
-{
- return find_sec(hdr, sechdrs, secstrings, ".data.percpu");
+static void find_pcpusecs(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ const char *secstrings,
+ unsigned int pcpuindex[2])
+{
+ /*
+ * Some architectures use __thread for per-cpu variables,
+ * and that generates .tdata and .tbss sections.
+ */
+ pcpuindex[0] = find_sec(hdr, sechdrs, secstrings, ".tdata");
+ pcpuindex[1] = find_sec(hdr, sechdrs, secstrings, ".tbss");
+ if (pcpuindex[0])
+ return;
+ if (pcpuindex[1] && !pcpuindex[0]) {
+ /* move .tbss to pcpuindex[0], it makes things easier later */
+ pcpuindex[0] = pcpuindex[1];
+ pcpuindex[1] = 0;
+ return;
+ }
+
+ /* look for the generic .data.percpu if no .tdata */
+ pcpuindex[0] = find_sec(hdr, sechdrs, secstrings, ".data.percpu");
}
static int percpu_modinit(void)
@@ -389,17 +406,20 @@ static inline void percpu_modfree(void *
{
BUG();
}
-static inline unsigned int find_pcpusec(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- const char *secstrings)
+static inline void find_pcpusecs(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ const char *secstrings,
+ unsigned int pcpuindex[2])
{
- return 0;
+ pcpuindex[0] = 0;
+ pcpuindex[1] = 0;
}
static inline void percpu_modcopy(void *pcpudst, const void *src,
- unsigned long size)
+ unsigned long init_sz, unsigned long zero_sz)
{
- /* pcpusec should be 0, and size of that section should be 0. */
- BUG_ON(size != 0);
+ /* there should be no per-cpu data to copy or clear */
+ BUG_ON(init_sz != 0);
+ BUG_ON(zero_sz != 0);
}
#endif /* CONFIG_SMP */
@@ -1121,7 +1141,7 @@ static int simplify_symbols(Elf_Shdr *se
unsigned int symindex,
const char *strtab,
unsigned int versindex,
- unsigned int pcpuindex,
+ unsigned int pcpuindex[2],
struct module *mod)
{
Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
@@ -1165,9 +1185,13 @@ static int simplify_symbols(Elf_Shdr *se
default:
/* Divert to percpu allocation if a percpu var. */
- if (sym[i].st_shndx == pcpuindex)
+ if (sym[i].st_shndx == pcpuindex[0])
secbase = (unsigned long)mod->percpu;
- else
+ else if (sym[i].st_shndx == pcpuindex[1]) {
+ /* .tbss follows .tdata */
+ secbase = (unsigned long)mod->percpu
+ + sechdrs[pcpuindex[0]].sh_size;
+ } else
secbase = sechdrs[sym[i].st_shndx].sh_addr;
sym[i].st_value += secbase;
break;
@@ -1411,8 +1435,9 @@ static struct module *load_module(void _
char *secstrings, *args, *modmagic, *strtab = NULL;
unsigned int i, symindex = 0, strindex = 0, setupindex, exindex,
exportindex, modindex, obsparmindex, infoindex, gplindex,
- crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex,
+ crcindex, gplcrcindex, versindex, pcpuindex[2], gplfutureindex,
gplfuturecrcindex;
+ unsigned int pcpusize = 0, pcpuinitsize = 0;
struct module *mod;
long err = 0;
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -1501,7 +1526,7 @@ #endif
obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");
- pcpuindex = find_pcpusec(hdr, sechdrs, secstrings);
+ find_pcpusecs(hdr, sechdrs, secstrings, pcpuindex);
/* Don't keep modinfo section */
sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
@@ -1548,17 +1573,33 @@ #endif
err = module_frob_arch_sections(hdr, sechdrs, secstrings, mod);
if (err < 0)
goto free_mod;
+
+ if (pcpuindex[0]) {
+ /* We have a special allocation for these sections. */
+ unsigned int align = 0;
+ int i, j;
- if (pcpuindex) {
- /* We have a special allocation for this section. */
- percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size,
- sechdrs[pcpuindex].sh_addralign,
- mod->name);
+ i = pcpuindex[0];
+ pcpusize = sechdrs[i].sh_size;
+ align = sechdrs[i].sh_addralign;
+ sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
+ if (sechdrs[i].sh_type != SHT_NOBITS)
+ pcpuinitsize = pcpusize;
+ if (pcpuindex[1]) {
+ /* have both .tdata and .tbss */
+ j = pcpuindex[1];
+ pcpusize = ALIGN(pcpusize, sechdrs[j].sh_addralign);
+ sechdrs[i].sh_size = pcpusize;
+ if (sechdrs[j].sh_addralign > align)
+ align = sechdrs[j].sh_addralign;
+ pcpusize += sechdrs[j].sh_size;
+ sechdrs[j].sh_flags &= ~(unsigned long)SHF_ALLOC;
+ }
+ percpu = percpu_modalloc(pcpusize, align, mod->name);
if (!percpu) {
err = -ENOMEM;
goto free_mod;
}
- sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
mod->percpu = percpu;
}
@@ -1687,8 +1728,8 @@ #endif
sort_extable(extable, extable + mod->num_exentries);
/* Finally, copy percpu area over. */
- percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
- sechdrs[pcpuindex].sh_size);
+ percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex[0]].sh_addr,
+ pcpuinitsize, pcpusize - pcpuinitsize);
add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
^ permalink raw reply related
* Re: [BUG] mtd redboot (also gcc 4.1 warning fix)
From: Daniel Walker @ 2006-05-10 3:31 UTC (permalink / raw)
To: Olof Johansson; +Cc: Matheus Izvekov, linux-kernel
In-Reply-To: <20060510032912.GC1794@lixom.net>
On Tue, 2006-05-09 at 22:29 -0500, Olof Johansson wrote:
> On Wed, May 10, 2006 at 12:14:45AM -0300, Matheus Izvekov wrote:
> > On 5/9/06, Daniel Walker <dwalker@mvista.com> wrote:
> > >unsigned long may not always be 32 bits, right ? This patch fixes the
> > Incorrect, its defined as 32bits for every standard C compiler
>
> Wrong. The only environment I'm aware of that has only P64 is Win64.
>
> Still, that's a bad patch, since it removes the warning without fixing
> the bug. It's a valid warning, the underlying problem should be fixed
> instead. It's better to keep the warning around until that's been done.
I never claimed to fix it ..
Daniel
^ permalink raw reply
* [PATCH] Define __raw_get_cpu_var and use it
From: Paul Mackerras @ 2006-05-10 3:30 UTC (permalink / raw)
To: akpm, linux-kernel; +Cc: linux-arch
There are several instances of per_cpu(foo, raw_smp_processor_id()),
which is semantically equivalent to __get_cpu_var(foo) but without the
warning that smp_processor_id() can give if CONFIG_DEBUG_PREEMPT is
enabled. For those architectures with optimized per-cpu
implementations, namely ia64, powerpc, s390, sparc64 and x86_64,
per_cpu() turns into more and slower code than __get_cpu_var(), so it
would be preferable to use __get_cpu_var on those platforms.
This defines a __raw_get_cpu_var(x) macro which turns into
per_cpu(x, raw_smp_processor_id()) on architectures that use the
generic per-cpu implementation, and turns into __get_cpu_var(x) on
the architectures that have an optimized per-cpu implementation.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index c0caf43..c745211 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -14,6 +14,7 @@ #define DEFINE_PER_CPU(type, name) \
/* var is in discarded region: offset to particular copy we want */
#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
#define __get_cpu_var(var) per_cpu(var, smp_processor_id())
+#define __raw_get_cpu_var(var) per_cpu(var, raw_smp_processor_id())
/* A macro to avoid #include hell... */
#define percpu_modcopy(pcpudst, src, size) \
@@ -30,6 +31,7 @@ #define DEFINE_PER_CPU(type, name) \
#define per_cpu(var, cpu) (*((void)(cpu), &per_cpu__##var))
#define __get_cpu_var(var) per_cpu__##var
+#define __raw_get_cpu_var(var) per_cpu__##var
#endif /* SMP */
diff --git a/include/asm-ia64/percpu.h b/include/asm-ia64/percpu.h
index 2b14dee..4bfbeb4 100644
--- a/include/asm-ia64/percpu.h
+++ b/include/asm-ia64/percpu.h
@@ -43,6 +43,7 @@ DECLARE_PER_CPU(unsigned long, local_per
#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __ia64_per_cpu_var(local_per_cpu_offset)))
+#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __ia64_per_cpu_var(local_per_cpu_offset)))
extern void percpu_modcopy(void *pcpudst, const void *src, unsigned long size);
extern void setup_per_cpu_areas (void);
@@ -52,6 +53,7 @@ #else /* ! SMP */
#define per_cpu(var, cpu) (*((void)(cpu), &per_cpu__##var))
#define __get_cpu_var(var) per_cpu__##var
+#define __raw_get_cpu_var(var) per_cpu__##var
#define per_cpu_init() (__phys_per_cpu_start)
#endif /* SMP */
diff --git a/include/asm-powerpc/percpu.h b/include/asm-powerpc/percpu.h
index 184a7a4..faa1fc7 100644
--- a/include/asm-powerpc/percpu.h
+++ b/include/asm-powerpc/percpu.h
@@ -22,6 +22,7 @@ #define DEFINE_PER_CPU(type, name) \
/* var is in discarded region: offset to particular copy we want */
#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)))
#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
+#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
/* A macro to avoid #include hell... */
#define percpu_modcopy(pcpudst, src, size) \
@@ -41,6 +42,7 @@ #define DEFINE_PER_CPU(type, name) \
#define per_cpu(var, cpu) (*((void)(cpu), &per_cpu__##var))
#define __get_cpu_var(var) per_cpu__##var
+#define __raw_get_cpu_var(var) per_cpu__##var
#endif /* SMP */
diff --git a/include/asm-s390/percpu.h b/include/asm-s390/percpu.h
index 436d216..d9a8cca 100644
--- a/include/asm-s390/percpu.h
+++ b/include/asm-s390/percpu.h
@@ -40,6 +40,7 @@ #define DEFINE_PER_CPU(type, name) \
__typeof__(type) per_cpu__##name
#define __get_cpu_var(var) __reloc_hide(var,S390_lowcore.percpu_offset)
+#define __raw_get_cpu_var(var) __reloc_hide(var,S390_lowcore.percpu_offset)
#define per_cpu(var,cpu) __reloc_hide(var,__per_cpu_offset[cpu])
/* A macro to avoid #include hell... */
@@ -57,6 +58,7 @@ #define DEFINE_PER_CPU(type, name) \
__typeof__(type) per_cpu__##name
#define __get_cpu_var(var) __reloc_hide(var,0)
+#define __raw_get_cpu_var(var) __reloc_hide(var,0)
#define per_cpu(var,cpu) __reloc_hide(var,0)
#endif /* SMP */
diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
index baef13b..a6ece06 100644
--- a/include/asm-sparc64/percpu.h
+++ b/include/asm-sparc64/percpu.h
@@ -21,6 +21,7 @@ register unsigned long __local_per_cpu_o
/* var is in discarded region: offset to particular copy we want */
#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)))
#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __local_per_cpu_offset))
+#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __local_per_cpu_offset))
/* A macro to avoid #include hell... */
#define percpu_modcopy(pcpudst, src, size) \
@@ -37,6 +38,7 @@ #define DEFINE_PER_CPU(type, name) \
#define per_cpu(var, cpu) (*((void)cpu, &per_cpu__##var))
#define __get_cpu_var(var) per_cpu__##var
+#define __raw_get_cpu_var(var) per_cpu__##var
#endif /* SMP */
diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h
index 7f33aaf..549eb92 100644
--- a/include/asm-x86_64/percpu.h
+++ b/include/asm-x86_64/percpu.h
@@ -21,6 +21,7 @@ #define DEFINE_PER_CPU(type, name) \
/* var is in discarded region: offset to particular copy we want */
#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)))
#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
+#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
/* A macro to avoid #include hell... */
#define percpu_modcopy(pcpudst, src, size) \
@@ -40,6 +41,7 @@ #define DEFINE_PER_CPU(type, name) \
#define per_cpu(var, cpu) (*((void)(cpu), &per_cpu__##var))
#define __get_cpu_var(var) per_cpu__##var
+#define __raw_get_cpu_var(var) per_cpu__##var
#endif /* SMP */
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index b7f0388..63626be 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -572,7 +572,7 @@ void hrtimer_init(struct hrtimer *timer,
memset(timer, 0, sizeof(struct hrtimer));
- bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
+ bases = __raw_get_cpu_var(hrtimer_bases);
if (clock_id == CLOCK_REALTIME && mode != HRTIMER_ABS)
clock_id = CLOCK_MONOTONIC;
@@ -594,7 +594,7 @@ int hrtimer_get_res(const clockid_t whic
{
struct hrtimer_base *bases;
- bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
+ bases = __raw_get_cpu_var(hrtimer_bases);
*tp = ktime_to_timespec(bases[which_clock].resolution);
return 0;
diff --git a/kernel/sched.c b/kernel/sched.c
index 4c64f85..cf904dd 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4168,7 +4168,7 @@ EXPORT_SYMBOL(yield);
*/
void __sched io_schedule(void)
{
- struct runqueue *rq = &per_cpu(runqueues, raw_smp_processor_id());
+ struct runqueue *rq = &__raw_get_cpu_var(runqueues);
atomic_inc(&rq->nr_iowait);
schedule();
@@ -4179,7 +4179,7 @@ EXPORT_SYMBOL(io_schedule);
long __sched io_schedule_timeout(long timeout)
{
- struct runqueue *rq = &per_cpu(runqueues, raw_smp_processor_id());
+ struct runqueue *rq = &__raw_get_cpu_var(runqueues);
long ret;
atomic_inc(&rq->nr_iowait);
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index 14c7faf..2c1be11 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -36,7 +36,7 @@ static struct notifier_block panic_block
void touch_softlockup_watchdog(void)
{
- per_cpu(touch_timestamp, raw_smp_processor_id()) = jiffies;
+ __raw_get_cpu_var(touch_timestamp) = jiffies;
}
EXPORT_SYMBOL(touch_softlockup_watchdog);
diff --git a/kernel/timer.c b/kernel/timer.c
index 67eaf0f..4afc9f1 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -146,7 +146,7 @@ static void internal_add_timer(tvec_base
void fastcall init_timer(struct timer_list *timer)
{
timer->entry.next = NULL;
- timer->base = per_cpu(tvec_bases, raw_smp_processor_id());
+ timer->base = __raw_get_cpu_var(tvec_bases);
}
EXPORT_SYMBOL(init_timer);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index cc9423d..60b11ae 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -244,7 +244,7 @@ static unsigned int rt_hash_rnd;
static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
#define RT_CACHE_STAT_INC(field) \
- (per_cpu(rt_cache_stat, raw_smp_processor_id()).field++)
+ (__raw_get_cpu_var(rt_cache_stat).field++)
static int rt_intern_hash(unsigned hash, struct rtable *rth,
struct rtable **res);
^ permalink raw reply related
* Re: [BUG] mtd redboot (also gcc 4.1 warning fix)
From: Olof Johansson @ 2006-05-10 3:29 UTC (permalink / raw)
To: Matheus Izvekov; +Cc: Daniel Walker, linux-kernel
In-Reply-To: <305c16960605092014t240ece2ob620264501deaa39@mail.gmail.com>
On Wed, May 10, 2006 at 12:14:45AM -0300, Matheus Izvekov wrote:
> On 5/9/06, Daniel Walker <dwalker@mvista.com> wrote:
> >unsigned long may not always be 32 bits, right ? This patch fixes the
> Incorrect, its defined as 32bits for every standard C compiler
Wrong. The only environment I'm aware of that has only P64 is Win64.
Still, that's a bad patch, since it removes the warning without fixing
the bug. It's a valid warning, the underlying problem should be fixed
instead. It's better to keep the warning around until that's been done.
-Olof
^ permalink raw reply
* Re: [BUG] mtd redboot (also gcc 4.1 warning fix)
From: Daniel Walker @ 2006-05-10 3:20 UTC (permalink / raw)
To: Matheus Izvekov; +Cc: linux-kernel
In-Reply-To: <305c16960605092014t240ece2ob620264501deaa39@mail.gmail.com>
On Wed, 2006-05-10 at 00:14 -0300, Matheus Izvekov wrote:
> On 5/9/06, Daniel Walker <dwalker@mvista.com> wrote:
> > unsigned long may not always be 32 bits, right ? This patch fixes the
> Incorrect, its defined as 32bits for every standard C compiler
My 64bit Athlon says it's 64bits (with gcc 3.4) .. Maybe the kernel uses
some compiler options to reduce the size .
Daniel
^ permalink raw reply
* Re: [PATCH -mm] scsi sata_svw gcc 4.1 warning fix
From: Benjamin Herrenschmidt @ 2006-05-10 3:16 UTC (permalink / raw)
To: Daniel Walker; +Cc: akpm, linux-ide, jgarzik, linux-kernel
In-Reply-To: <200605100256.k4A2u6Kd031755@dwalker1.mvista.com>
On Tue, 2006-05-09 at 19:56 -0700, Daniel Walker wrote:
> Fixes the following warning,
Nack... ugly casts. Jeff, what is the status with these ?
Cheers,
Ben.
> drivers/scsi/sata_svw.c: In function 'k2_sata_tf_load':
> drivers/scsi/sata_svw.c:115: warning: passing argument 2 of 'writeb' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:120: warning: passing argument 2 of 'writew' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:121: warning: passing argument 2 of 'writew' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:122: warning: passing argument 2 of 'writew' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:123: warning: passing argument 2 of 'writew' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:124: warning: passing argument 2 of 'writew' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:126: warning: passing argument 2 of 'writew' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:127: warning: passing argument 2 of 'writew' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:128: warning: passing argument 2 of 'writew' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:129: warning: passing argument 2 of 'writew' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:130: warning: passing argument 2 of 'writew' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:134: warning: passing argument 2 of 'writeb' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c: In function 'k2_sata_tf_read':
> drivers/scsi/sata_svw.c:146: warning: passing argument 1 of 'readw' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:147: warning: passing argument 1 of 'readw' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:148: warning: passing argument 1 of 'readw' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:149: warning: passing argument 1 of 'readw' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:150: warning: passing argument 1 of 'readw' makes pointer from integer without a cast
> drivers/scsi/sata_svw.c:151: warning: passing argument 1 of 'readw' makes pointer from integer without a cast
>
> Signed-Off-By: Daniel Walker <dwalker@mvista.com>
>
> Index: linux-2.6.16/drivers/scsi/sata_svw.c
> ===================================================================
> --- linux-2.6.16.orig/drivers/scsi/sata_svw.c
> +++ linux-2.6.16/drivers/scsi/sata_svw.c
> @@ -112,26 +112,26 @@ static void k2_sata_tf_load(struct ata_p
> unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
>
> if (tf->ctl != ap->last_ctl) {
> - writeb(tf->ctl, ioaddr->ctl_addr);
> + writeb(tf->ctl, (void *)ioaddr->ctl_addr);
> ap->last_ctl = tf->ctl;
> ata_wait_idle(ap);
> }
> if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
> - writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->feature_addr);
> - writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
> - writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr);
> - writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr);
> - writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr);
> + writew(tf->feature | (((u16)tf->hob_feature) << 8), (void *)ioaddr->feature_addr);
> + writew(tf->nsect | (((u16)tf->hob_nsect) << 8), (void *)ioaddr->nsect_addr);
> + writew(tf->lbal | (((u16)tf->hob_lbal) << 8), (void *)ioaddr->lbal_addr);
> + writew(tf->lbam | (((u16)tf->hob_lbam) << 8), (void *)ioaddr->lbam_addr);
> + writew(tf->lbah | (((u16)tf->hob_lbah) << 8), (void *)ioaddr->lbah_addr);
> } else if (is_addr) {
> - writew(tf->feature, ioaddr->feature_addr);
> - writew(tf->nsect, ioaddr->nsect_addr);
> - writew(tf->lbal, ioaddr->lbal_addr);
> - writew(tf->lbam, ioaddr->lbam_addr);
> - writew(tf->lbah, ioaddr->lbah_addr);
> + writew(tf->feature, (void *)ioaddr->feature_addr);
> + writew(tf->nsect, (void *)ioaddr->nsect_addr);
> + writew(tf->lbal, (void *)ioaddr->lbal_addr);
> + writew(tf->lbam, (void *)ioaddr->lbam_addr);
> + writew(tf->lbah, (void *)ioaddr->lbah_addr);
> }
>
> if (tf->flags & ATA_TFLAG_DEVICE)
> - writeb(tf->device, ioaddr->device_addr);
> + writeb(tf->device, (void *)ioaddr->device_addr);
>
> ata_wait_idle(ap);
> }
> @@ -143,12 +143,12 @@ static void k2_sata_tf_read(struct ata_p
> u16 nsect, lbal, lbam, lbah, feature;
>
> tf->command = k2_stat_check_status(ap);
> - tf->device = readw(ioaddr->device_addr);
> - feature = readw(ioaddr->error_addr);
> - nsect = readw(ioaddr->nsect_addr);
> - lbal = readw(ioaddr->lbal_addr);
> - lbam = readw(ioaddr->lbam_addr);
> - lbah = readw(ioaddr->lbah_addr);
> + tf->device = readw((void *)ioaddr->device_addr);
> + feature = readw((void *)ioaddr->error_addr);
> + nsect = readw((void *)ioaddr->nsect_addr);
> + lbal = readw((void *)ioaddr->lbal_addr);
> + lbam = readw((void *)ioaddr->lbam_addr);
> + lbah = readw((void *)ioaddr->lbah_addr);
>
> tf->feature = feature;
> tf->nsect = nsect;
> -
> To unsubscribe from this list: send the line "unsubscribe linux-ide" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [BUG] mtd redboot (also gcc 4.1 warning fix)
From: Matheus Izvekov @ 2006-05-10 3:14 UTC (permalink / raw)
To: Daniel Walker; +Cc: linux-kernel
In-Reply-To: <200605100256.k4A2u4FO031737@dwalker1.mvista.com>
On 5/9/06, Daniel Walker <dwalker@mvista.com> wrote:
> unsigned long may not always be 32 bits, right ? This patch fixes the
Incorrect, its defined as 32bits for every standard C compiler
^ permalink raw reply
* Re: [PATCH] powerpc: whitespace cleanup in reg.h
From: Olof Johansson @ 2006-05-10 3:14 UTC (permalink / raw)
To: jschopp; +Cc: linuxppc-dev, Michael Neuling, paulus
In-Reply-To: <4460E0BC.4050908@austin.ibm.com>
On Tue, May 09, 2006 at 01:34:36PM -0500, jschopp wrote:
> > +#define SPRN_HID6 0x3F9 /* BE HID 6 */
> > +#define HID6_LB (0x0F<<12) /* Concurrent Large Page Modes */
> > +#define HID6_DLP (1<<20) /* Disable all large page modes (4K only) */
> > +#define SPRN_TSC_CELL 0x399 /* Thread switch control on Cell */
> > +#define TSC_CELL_DEC_ENABLE_0 0x400000 /* Decrementer Interrupt */
> > +#define TSC_CELL_DEC_ENABLE_1 0x200000 /* Decrementer Interrupt */
> > +#define TSC_CELL_EE_ENABLE 0x100000 /* External Interrupt */
> > +#define TSC_CELL_EE_BOOST 0x080000 /* External Interrupt Boost */
> > +#define SPRN_TSC 0x3FD /* Thread switch control on others */
> > +#define SPRN_TST 0x3FC /* Thread switch timeout on others */
>
> OK, the tab to space for lines like SPRN_HID6 I understand. But then you seem to be
> trying to do indenting with 3 spaces instead of tabs.
It's what the rest of the file uses. It might not correspond to
CodingStyle, but it makes it easy to read.
(Now, I'm not sure it's a good idea to define the meanings of HID bits
in the global register include, but that's unrelated to the whitespace
cleanup Mikey did.)
-Olof
^ permalink raw reply
* What's in git.git
From: Junio C Hamano @ 2006-05-10 3:11 UTC (permalink / raw)
To: git
This week's "What's in" is a day early, since I do not expect to
be able to do much gitting for the rest of the week.
* The 'maint' branch has these fixes since the last announcement.
Dmitry V. Levin:
Separate object name errors from usage errors
Eric Wong:
apply: fix infinite loop with multiple patches with --index
Johannes Schindelin:
repo-config: trim white-space before comment
Junio C Hamano:
core.prefersymlinkrefs: use symlinks for .git/HEAD
repo-config: document what value_regexp does a bit more clearly.
Fix repo-config set-multivar error return path.
Documentation: {caret} fixes (git-rev-list.txt)
Linus Torvalds:
Fix "git diff --stat" with long filenames
revert/cherry-pick: use aggressive merge.
Martin Waitz:
clone: keep --reference even with -l -s
repack: honor -d even when no new pack was created
Matthias Lederhofer:
core-tutorial.txt: escape asterisk
Pavel Roskin:
Release config lock if the regex is invalid
Sean Estabrooks:
Fix for config file section parsing.
Yakov Lerner:
read-cache.c: use xcalloc() not calloc()
* The 'master' branch has these since the last announcement, in
addition to the above. I've flushed topics that have been
cooked in "next" long enough and hadn't given me problems.
Eric Wong:
git-svn: documentation updates
git-svn 1.0.0
Johannes Schindelin:
builtin-push: --all and --tags _are_ explicit refspecs
Fix users of prefix_path() to free() only when necessary
Fix users of prefix_path() to free() only when necessary
Junio C Hamano:
get_sha1(): :path and :[0-3]:path to extract from index.
Makefile: do not link rev-list any specially.
delta: stricter constness
pack-object: squelch eye-candy on non-tty
binary patch.
binary diff: further updates.
update-index --unresolve: work from a subdirectory.
checkout-index: plug memory leak from prefix_path()
update-index: plug memory leak from prefix_path()
update-index --again
update-index --again: take optional pathspecs
binary diff and apply: testsuite.
repo-config: document what value_regexp does a bit more clearly.
get_sha1() - fix infinite loop on nonexistent stage.
Teach git-clean optional <paths>... parameters.
checkout: use --aggressive when running a 3-way merge (-m).
Martin Waitz:
Transitively read alternatives
test case for transitive info/alternates
clone: don't clone the info/alternates file
Nicolas Pitre:
split the diff-delta interface
use delta index data when finding best delta matches
replace adler32 with Rabin's polynomial in diff-delta
tiny optimization to diff-delta
improve diff-delta with sparse and/or repetitive data
improve base85 generated assembly code
Peter Hagervall:
Sparse fix for builtin-diff
Sean Estabrooks:
Several trivial documentation touch ups.
Fix up docs where "--" isn't displayed correctly.
Update git-unpack-objects documentation.
Clarify git-cherry documentation.
Another config file parsing fix.
t1300-repo-config: two new config parsing tests.
* The 'next' branch, in addition, has these.
- cvsserver and cvsexportcommit updates (Martin Langhoff and Martyn Smith)
This is a new merge but not very new code. Martin may want
to comment on how ready they are.
- built-in fmt-patch (Johannes Schindelin)
I think this is ready, even though it does not have some
things we have in format-patch (i.e. --attach, --signoff,
--check). If anybody deeply cares please stop me soon or
better yet enhance with your patches; otherwise I would like
to push this out to "master" sometime next week to supersede
the git-format-patch script.
- built-in grep (me)
I think this is also ready, even though it robs users from
having funky "grep" on their $PATH and invoke it. Compared
to GNU grep, it lacks -P (pcre), -Z (NUL-terminated output),
-q (totally quiet), -z (NUL-terminated input), but all the
commonly used ones including -f (from file), -F (fixed), -w
(word regexp), -l/-L (files with/without match) and -n (line
number) are implemented. The same "stop me or else" comment
applies.
- use config "remote.$name.url" and friends for fetch/pull
(Johannes Schindelin)
I think this itself is ready; the only reason I do not plan
to do so this week is to wait until the new config format
discussion settles, at which time we would need to adjust
this to the new format.
- cache-tree (me)
This has been stalled; I would want to redo it without using
out-of-index data structure, but that would need the
following steps, and lately I have too many distractions to
concentrate on them.
- review existing index/working-tree/tree walkers.
- prepare a merge-tree style path walker that walks index,
working tree, and zero or more trees in parallel. This
would probably have an interator interface to return list
of either tree or blob <mode,sha1> to the caller. Because
index does not currently have tree entries, a "not
up-to-date" tree entry would be returned from the index
part of the walker if I base this change on "master". I
might base this on "next" and use information from
cache-tree.
- using the parallel path walker, revamp diff-cache (both
cached and non cached) to work out kinks to the walker API
and see how well it performs. If I base the work on
"next", the code should be able to skip unchanged
subtrees.
- revamp diff-files (walks index and working tree), although
this will not get any benefit from having tree entries in
the index.
- revamp read-tree (all forms).
- if I based the work on "next", rip out the cache-tree
dependency and make the walker return "not up-to-date"
tree entries for index.
- revamp update-index, apply, and write-tree to have tree
entries in the index. This probably involves revamping
read-cache interface to update the index file contents.
- review read-tree to make sure it correctly maintains the
tree entries in the cache.
* The 'pu' branch, in addition, has the proposed configuration
file syntax updates from Linus with a patch from Sean. I
haven't had time to really look at it, and it seems to fail a
test right now, but I left it as is. This is merged from a
throw-away topic branch for now, but when I resume to gitting
sometime next week I am hoping we have something ready to be
tested (iow, "next" material) based on the list concensus. At
that time we might probably do backport to cope with the
syntax updates for 1.3.X release and perhaps 1.2.X series just
for fun.
^ permalink raw reply
* [PATCH] powerpc: fix LED progress on pseries boxes
From: Anton Blanchard @ 2006-05-10 3:05 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
It looks like we are printing the wrong thing on the op panel.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 5eb55ef..5f79f01 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -255,7 +255,7 @@ static int __init pSeries_init_panel(voi
{
/* Manually leave the kernel version on the panel. */
ppc_md.progress("Linux ppc64\n", 0);
- ppc_md.progress(system_utsname.version, 0);
+ ppc_md.progress(system_utsname.release, 0);
return 0;
}
^ permalink raw reply related
* [PATCH -mm] wireless tiacx gcc 4.1 warning fix
From: Daniel Walker @ 2006-05-10 2:56 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
Fixes warnings like the following,
drivers/net/wireless/tiacx/acx_struct.h:1878: warning: 'packed' attribute ignored for field of type 'u8'
drivers/net/wireless/tiacx/acx_struct.h:1884: warning: 'packed' attribute ignored for field of type 'u8'
drivers/net/wireless/tiacx/acx_struct.h:1885: warning: 'packed' attribute ignored for field of type 'u8'
drivers/net/wireless/tiacx/acx_struct.h:1886: warning: 'packed' attribute ignored for field of type 'u8'
drivers/net/wireless/tiacx/acx_struct.h:1887: warning: 'packed' attribute ignored for field of type 'u8[28u]'
drivers/net/wireless/tiacx/acx_struct.h:1891: warning: 'packed' attribute ignored for field of type 'u8[5u]'
drivers/net/wireless/tiacx/acx_struct.h:1894: warning: 'packed' attribute ignored for field of type 'u8'
drivers/net/wireless/tiacx/acx_struct.h:1895: warning: 'packed' attribute ignored for field of type 'u8'
drivers/net/wireless/tiacx/acx_struct.h:1896: warning: 'packed' attribute ignored for field of type 'u8'
drivers/net/wireless/tiacx/acx_struct.h:1897: warning: 'packed' attribute ignored for field of type 'u8'
drivers/net/wireless/tiacx/acx_struct.h:1898: warning: 'packed' attribute ignored for field of type 'u8[5u]'
drivers/net/wireless/tiacx/acx_struct.h:1899: warning: 'packed' attribute ignored for field of type 'u8[31u]'
drivers/net/wireless/tiacx/acx_struct.h:1905: warning: 'packed' attribute ignored for field of type 'u8'
drivers/net/wireless/tiacx/acx_struct.h:1909: warning: 'packed' attribute ignored for field of type 'u8[5u]'
drivers/net/wireless/tiacx/acx_struct.h:1912: warning: 'packed' attribute ignored for field of type 'u8[28u]'
Signed-Off-By: Daniel Walker <dwalker@mvista.com>
Index: linux-2.6.16/drivers/net/wireless/tiacx/acx_struct.h
===================================================================
--- linux-2.6.16.orig/drivers/net/wireless/tiacx/acx_struct.h
+++ linux-2.6.16/drivers/net/wireless/tiacx/acx_struct.h
@@ -474,8 +474,8 @@ DEF_IE(111_IE_DOT11_INVAL_1013, 0x1013
* --vda
*/
typedef struct phy_hdr {
- u8 unknown[4] ACX_PACKED;
- u8 acx111_unknown[4] ACX_PACKED;
+ u8 unknown[4];
+ u8 acx111_unknown[4];
} phy_hdr_t;
/* seems to be a bit similar to hfa384x_rx_frame.
@@ -537,19 +537,19 @@ time: 4 bytes:
typedef struct rxbuffer {
u16 mac_cnt_rcvd ACX_PACKED; /* only 12 bits are len! (0xfff) */
- u8 mac_cnt_mblks ACX_PACKED;
- u8 mac_status ACX_PACKED;
- u8 phy_stat_baseband ACX_PACKED; /* bit 0x80: used LNA (Low-Noise Amplifier) */
- u8 phy_plcp_signal ACX_PACKED;
- u8 phy_level ACX_PACKED; /* PHY stat */
- u8 phy_snr ACX_PACKED; /* PHY stat */
+ u8 mac_cnt_mblks;
+ u8 mac_status;
+ u8 phy_stat_baseband; /* bit 0x80: used LNA (Low-Noise Amplifier) */
+ u8 phy_plcp_signal;
+ u8 phy_level; /* PHY stat */
+ u8 phy_snr; /* PHY stat */
u32 time ACX_PACKED; /* timestamp upon MAC rcv first byte */
/* 4-byte (acx100) or 8-byte (acx111) phy header will be here
** if RX_CFG1_INCLUDE_PHY_HDR is in effect:
** phy_hdr_t phy */
- wlan_hdr_a3_t hdr_a3 ACX_PACKED;
+ wlan_hdr_a3_t hdr_a3;
/* maximally sized data part of wlan packet */
- u8 data_a3[WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN] ACX_PACKED;
+ u8 data_a3[WLAN_A4FR_MAXLEN_WEP_FCS - WLAN_HDR_A3_LEN];
/* can add hdr/data_a4 if needed */
} rxbuffer_t;
@@ -601,7 +601,7 @@ typedef struct fw_stats {
typedef struct fw_ver {
u16 cmd ACX_PACKED;
u16 size ACX_PACKED;
- char fw_id[20] ACX_PACKED;
+ char fw_id[20];
u32 hw_id ACX_PACKED;
} fw_ver_t;
@@ -800,9 +800,9 @@ typedef struct {
/* Outside of "#ifdef PCI" because USB needs to know sizeof()
** of txdesc and rxdesc: */
struct txdesc {
- acx_ptr pNextDesc ACX_PACKED; /* pointer to next txdesc */
- acx_ptr HostMemPtr ACX_PACKED; /* 0x04 */
- acx_ptr AcxMemPtr ACX_PACKED; /* 0x08 */
+ acx_ptr pNextDesc; /* pointer to next txdesc */
+ acx_ptr HostMemPtr; /* 0x04 */
+ acx_ptr AcxMemPtr; /* 0x08 */
u32 tx_time ACX_PACKED; /* 0x0c */
u16 total_length ACX_PACKED; /* 0x10 */
u16 Reserved ACX_PACKED; /* 0x12 */
@@ -812,44 +812,44 @@ struct txdesc {
** for driver use. amd64 blew up. We dare not use it now */
u32 dummy[4] ACX_PACKED;
- u8 Ctl_8 ACX_PACKED; /* 0x24, 8bit value */
- u8 Ctl2_8 ACX_PACKED; /* 0x25, 8bit value */
- u8 error ACX_PACKED; /* 0x26 */
- u8 ack_failures ACX_PACKED; /* 0x27 */
- u8 rts_failures ACX_PACKED; /* 0x28 */
- u8 rts_ok ACX_PACKED; /* 0x29 */
+ u8 Ctl_8; /* 0x24, 8bit value */
+ u8 Ctl2_8; /* 0x25, 8bit value */
+ u8 error; /* 0x26 */
+ u8 ack_failures; /* 0x27 */
+ u8 rts_failures; /* 0x28 */
+ u8 rts_ok; /* 0x29 */
union {
- struct {
- u8 rate ACX_PACKED; /* 0x2a */
- u8 queue_ctrl ACX_PACKED; /* 0x2b */
- } r1 ACX_PACKED;
+ struct ACX_PACKED {
+ u8 rate; /* 0x2a */
+ u8 queue_ctrl; /* 0x2b */
+ } r1;
struct {
u16 rate111 ACX_PACKED; /* 0x2a */
- } r2 ACX_PACKED;
- } u ACX_PACKED;
+ } r2;
+ } u;
u32 queue_info ACX_PACKED; /* 0x2c (acx100, reserved on acx111) */
}; /* size : 48 = 0x30 */
/* NB: acx111 txdesc structure is 4 byte larger */
/* All these 4 extra bytes are reserved. tx alloc code takes them into account */
struct rxdesc {
- acx_ptr pNextDesc ACX_PACKED; /* 0x00 */
- acx_ptr HostMemPtr ACX_PACKED; /* 0x04 */
- acx_ptr ACXMemPtr ACX_PACKED; /* 0x08 */
+ acx_ptr pNextDesc; /* 0x00 */
+ acx_ptr HostMemPtr; /* 0x04 */
+ acx_ptr ACXMemPtr; /* 0x08 */
u32 rx_time ACX_PACKED; /* 0x0c */
u16 total_length ACX_PACKED; /* 0x10 */
u16 WEP_length ACX_PACKED; /* 0x12 */
u32 WEP_ofs ACX_PACKED; /* 0x14 */
/* the following 16 bytes do not change when acx100 owns the descriptor */
- u8 driverWorkspace[16] ACX_PACKED; /* 0x18 */
+ u8 driverWorkspace[16]; /* 0x18 */
- u8 Ctl_8 ACX_PACKED;
- u8 rate ACX_PACKED;
- u8 error ACX_PACKED;
- u8 SNR ACX_PACKED; /* Signal-to-Noise Ratio */
- u8 RxLevel ACX_PACKED;
- u8 queue_ctrl ACX_PACKED;
+ u8 Ctl_8;
+ u8 rate;
+ u8 error;
+ u8 SNR; /* Signal-to-Noise Ratio */
+ u8 RxLevel;
+ u8 queue_ctrl;
u16 unknown ACX_PACKED;
u32 unknown2 ACX_PACKED;
}; /* size 52 = 0x34 */
@@ -921,26 +921,26 @@ enum {
#define INT_TRIG_CMD 0x01
struct txhostdesc {
- acx_ptr data_phy ACX_PACKED; /* 0x00 [u8 *] */
+ acx_ptr data_phy; /* 0x00 [u8 *] */
u16 data_offset ACX_PACKED; /* 0x04 */
u16 reserved ACX_PACKED; /* 0x06 */
u16 Ctl_16 ACX_PACKED; /* 16bit value, endianness!! */
u16 length ACX_PACKED; /* 0x0a */
- acx_ptr desc_phy_next ACX_PACKED; /* 0x0c [txhostdesc *] */
- acx_ptr pNext ACX_PACKED; /* 0x10 [txhostdesc *] */
+ acx_ptr desc_phy_next; /* 0x0c [txhostdesc *] */
+ acx_ptr pNext; /* 0x10 [txhostdesc *] */
u32 Status ACX_PACKED; /* 0x14, unused on Tx */
/* From here on you can use this area as you want (variable length, too!) */
u8 *data ACX_PACKED;
};
struct rxhostdesc {
- acx_ptr data_phy ACX_PACKED; /* 0x00 [rxbuffer_t *] */
+ acx_ptr data_phy; /* 0x00 [rxbuffer_t *] */
u16 data_offset ACX_PACKED; /* 0x04 */
u16 reserved ACX_PACKED; /* 0x06 */
u16 Ctl_16 ACX_PACKED; /* 0x08; 16bit value, endianness!! */
u16 length ACX_PACKED; /* 0x0a */
- acx_ptr desc_phy_next ACX_PACKED; /* 0x0c [rxhostdesc_t *] */
- acx_ptr pNext ACX_PACKED; /* 0x10 [rxhostdesc_t *] */
+ acx_ptr desc_phy_next; /* 0x0c [rxhostdesc_t *] */
+ acx_ptr pNext; /* 0x10 [rxhostdesc_t *] */
u32 Status ACX_PACKED; /* 0x14 */
/* From here on you can use this area as you want (variable length, too!) */
rxbuffer_t *data ACX_PACKED;
@@ -960,27 +960,27 @@ struct rxhostdesc {
typedef struct usb_txbuffer {
u16 desc ACX_PACKED;
u16 mpdu_len ACX_PACKED;
- u8 queue_index ACX_PACKED;
- u8 rate ACX_PACKED;
+ u8 queue_index;
+ u8 rate;
u32 hostdata ACX_PACKED;
- u8 ctrl1 ACX_PACKED;
- u8 ctrl2 ACX_PACKED;
+ u8 ctrl1;
+ u8 ctrl2;
u16 data_len ACX_PACKED;
/* wlan packet content is placed here: */
- u8 data[WLAN_A4FR_MAXLEN_WEP_FCS] ACX_PACKED;
+ u8 data[WLAN_A4FR_MAXLEN_WEP_FCS];
} usb_txbuffer_t;
/* USB returns either rx packets (see rxbuffer) or
** these "tx status" structs: */
typedef struct usb_txstatus {
u16 mac_cnt_rcvd ACX_PACKED; /* only 12 bits are len! (0xfff) */
- u8 queue_index ACX_PACKED;
- u8 mac_status ACX_PACKED; /* seen 0x20 on tx failure */
+ u8 queue_index;
+ u8 mac_status; /* seen 0x20 on tx failure */
u32 hostdata ACX_PACKED;
- u8 rate ACX_PACKED;
- u8 ack_failures ACX_PACKED;
- u8 rts_failures ACX_PACKED;
- u8 rts_ok ACX_PACKED;
+ u8 rate;
+ u8 ack_failures;
+ u8 rts_failures;
+ u8 rts_ok;
} usb_txstatus_t;
typedef struct usb_tx {
@@ -1012,69 +1012,69 @@ typedef struct usb_rx {
/* Config Option structs */
typedef struct co_antennas {
- u8 type ACX_PACKED;
- u8 len ACX_PACKED;
- u8 list[2] ACX_PACKED;
+ u8 type;
+ u8 len;
+ u8 list[2];
} co_antennas_t;
typedef struct co_powerlevels {
- u8 type ACX_PACKED;
- u8 len ACX_PACKED;
+ u8 type;
+ u8 len;
u16 list[8] ACX_PACKED;
} co_powerlevels_t;
typedef struct co_datarates {
- u8 type ACX_PACKED;
- u8 len ACX_PACKED;
- u8 list[8] ACX_PACKED;
+ u8 type;
+ u8 len;
+ u8 list[8];
} co_datarates_t;
typedef struct co_domains {
- u8 type ACX_PACKED;
- u8 len ACX_PACKED;
- u8 list[6] ACX_PACKED;
+ u8 type;
+ u8 len;
+ u8 list[6];
} co_domains_t;
typedef struct co_product_id {
- u8 type ACX_PACKED;
- u8 len ACX_PACKED;
- u8 list[128] ACX_PACKED;
+ u8 type;
+ u8 len;
+ u8 list[128];
} co_product_id_t;
typedef struct co_manuf_id {
- u8 type ACX_PACKED;
- u8 len ACX_PACKED;
- u8 list[128] ACX_PACKED;
+ u8 type;
+ u8 len;
+ u8 list[128];
} co_manuf_t;
typedef struct co_fixed {
- char NVSv[8] ACX_PACKED;
+ char NVSv[8];
/* u16 NVS_vendor_offs; ACX111-only */
/* u16 unknown; ACX111-only */
- u8 MAC[6] ACX_PACKED; /* ACX100-only */
+ u8 MAC[6]; /* ACX100-only */
u16 probe_delay ACX_PACKED; /* ACX100-only */
u32 eof_memory ACX_PACKED;
- u8 dot11CCAModes ACX_PACKED;
- u8 dot11Diversity ACX_PACKED;
- u8 dot11ShortPreambleOption ACX_PACKED;
- u8 dot11PBCCOption ACX_PACKED;
- u8 dot11ChannelAgility ACX_PACKED;
- u8 dot11PhyType ACX_PACKED; /* FIXME: does 802.11 call it "dot11PHYType"? */
- u8 dot11TempType ACX_PACKED;
- u8 table_count ACX_PACKED;
+ u8 dot11CCAModes;
+ u8 dot11Diversity;
+ u8 dot11ShortPreambleOption;
+ u8 dot11PBCCOption;
+ u8 dot11ChannelAgility;
+ u8 dot11PhyType; /* FIXME: does 802.11 call it "dot11PHYType"? */
+ u8 dot11TempType;
+ u8 table_count;
} co_fixed_t;
typedef struct acx111_ie_configoption {
u16 type ACX_PACKED;
u16 len ACX_PACKED;
/* Do not access below members directly, they are in fact variable length */
- co_fixed_t fixed ACX_PACKED;
- co_antennas_t antennas ACX_PACKED;
- co_powerlevels_t power_levels ACX_PACKED;
- co_datarates_t data_rates ACX_PACKED;
- co_domains_t domains ACX_PACKED;
- co_product_id_t product_id ACX_PACKED;
- co_manuf_t manufacturer ACX_PACKED;
+ co_fixed_t fixed;
+ co_antennas_t antennas;
+ co_powerlevels_t power_levels;
+ co_datarates_t data_rates;
+ co_domains_t domains;
+ co_product_id_t product_id;
+ co_manuf_t manufacturer;
u8 _padding[4];
} acx111_ie_configoption_t;
@@ -1522,15 +1522,15 @@ typedef struct acx100_ie_queueconfig {
u16 len ACX_PACKED;
u32 AreaSize ACX_PACKED;
u32 RxQueueStart ACX_PACKED;
- u8 QueueOptions ACX_PACKED;
- u8 NumTxQueues ACX_PACKED;
- u8 NumRxDesc ACX_PACKED; /* for USB only */
- u8 pad1 ACX_PACKED;
+ u8 QueueOptions;
+ u8 NumTxQueues;
+ u8 NumRxDesc; /* for USB only */
+ u8 pad1;
u32 QueueEnd ACX_PACKED;
u32 HostQueueEnd ACX_PACKED; /* QueueEnd2 */
u32 TxQueueStart ACX_PACKED;
- u8 TxQueuePri ACX_PACKED;
- u8 NumTxDesc ACX_PACKED;
+ u8 TxQueuePri;
+ u8 NumTxDesc;
u16 pad2 ACX_PACKED;
} acx100_ie_queueconfig_t;
@@ -1542,16 +1542,16 @@ typedef struct acx111_ie_queueconfig {
u32 rx1_queue_address ACX_PACKED;
u32 reserved1 ACX_PACKED;
u32 tx1_queue_address ACX_PACKED;
- u8 tx1_attributes ACX_PACKED;
+ u8 tx1_attributes;
u16 reserved2 ACX_PACKED;
- u8 reserved3 ACX_PACKED;
+ u8 reserved3;
} acx111_ie_queueconfig_t;
typedef struct acx100_ie_memconfigoption {
u16 type ACX_PACKED;
u16 len ACX_PACKED;
u32 DMA_config ACX_PACKED;
- acx_ptr pRxHostDesc ACX_PACKED;
+ acx_ptr pRxHostDesc;
u32 rx_mem ACX_PACKED;
u32 tx_mem ACX_PACKED;
u16 RxBlockNum ACX_PACKED;
@@ -1563,27 +1563,27 @@ typedef struct acx111_ie_memoryconfig {
u16 len ACX_PACKED;
u16 no_of_stations ACX_PACKED;
u16 memory_block_size ACX_PACKED;
- u8 tx_rx_memory_block_allocation ACX_PACKED;
- u8 count_rx_queues ACX_PACKED;
- u8 count_tx_queues ACX_PACKED;
- u8 options ACX_PACKED;
- u8 fragmentation ACX_PACKED;
+ u8 tx_rx_memory_block_allocation;
+ u8 count_rx_queues;
+ u8 count_tx_queues;
+ u8 options;
+ u8 fragmentation;
u16 reserved1 ACX_PACKED;
- u8 reserved2 ACX_PACKED;
+ u8 reserved2;
/* start of rx1 block */
- u8 rx_queue1_count_descs ACX_PACKED;
- u8 rx_queue1_reserved1 ACX_PACKED;
- u8 rx_queue1_type ACX_PACKED; /* must be set to 7 */
- u8 rx_queue1_prio ACX_PACKED; /* must be set to 0 */
- acx_ptr rx_queue1_host_rx_start ACX_PACKED;
+ u8 rx_queue1_count_descs;
+ u8 rx_queue1_reserved1;
+ u8 rx_queue1_type; /* must be set to 7 */
+ u8 rx_queue1_prio; /* must be set to 0 */
+ acx_ptr rx_queue1_host_rx_start;
/* end of rx1 block */
/* start of tx1 block */
- u8 tx_queue1_count_descs ACX_PACKED;
- u8 tx_queue1_reserved1 ACX_PACKED;
- u8 tx_queue1_reserved2 ACX_PACKED;
- u8 tx_queue1_attributes ACX_PACKED;
+ u8 tx_queue1_count_descs;
+ u8 tx_queue1_reserved1;
+ u8 tx_queue1_reserved2;
+ u8 tx_queue1_attributes;
/* end of tx1 block */
} acx111_ie_memoryconfig_t;
@@ -1612,7 +1612,7 @@ typedef struct acx111_ie_feature_config
typedef struct acx111_ie_tx_level {
u16 type ACX_PACKED;
u16 len ACX_PACKED;
- u8 level ACX_PACKED;
+ u8 level;
} acx111_ie_tx_level_t;
#define PS_CFG_ENABLE 0x80
@@ -1632,20 +1632,20 @@ typedef struct acx111_ie_tx_level {
typedef struct acx100_ie_powersave {
u16 type ACX_PACKED;
u16 len ACX_PACKED;
- u8 wakeup_cfg ACX_PACKED;
- u8 listen_interval ACX_PACKED; /* for EACH_ITVL: wake up every "beacon units" interval */
- u8 options ACX_PACKED;
- u8 hangover_period ACX_PACKED; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
+ u8 wakeup_cfg;
+ u8 listen_interval; /* for EACH_ITVL: wake up every "beacon units" interval */
+ u8 options;
+ u8 hangover_period; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
u16 enhanced_ps_transition_time ACX_PACKED; /* rem. wake time for Enh. PS */
} acx100_ie_powersave_t;
typedef struct acx111_ie_powersave {
u16 type ACX_PACKED;
u16 len ACX_PACKED;
- u8 wakeup_cfg ACX_PACKED;
- u8 listen_interval ACX_PACKED; /* for EACH_ITVL: wake up every "beacon units" interval */
- u8 options ACX_PACKED;
- u8 hangover_period ACX_PACKED; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
+ u8 wakeup_cfg;
+ u8 listen_interval; /* for EACH_ITVL: wake up every "beacon units" interval */
+ u8 options;
+ u8 hangover_period; /* remaining wake time after Tx MPDU w/ PS bit, in values of 1/1024 seconds */
u32 beacon_rx_time ACX_PACKED;
u32 enhanced_ps_transition_time ACX_PACKED; /* rem. wake time for Enh. PS */
} acx111_ie_powersave_t;
@@ -1678,8 +1678,8 @@ typedef struct acx100_scan {
u16 count ACX_PACKED; /* number of scans to do, 0xffff == continuous */
u16 start_chan ACX_PACKED;
u16 flags ACX_PACKED; /* channel list mask; 0x8000 == all channels? */
- u8 max_rate ACX_PACKED; /* max. probe rate */
- u8 options ACX_PACKED; /* bit mask, see defines above */
+ u8 max_rate; /* max. probe rate */
+ u8 options; /* bit mask, see defines above */
u16 chan_duration ACX_PACKED;
u16 max_probe_delay ACX_PACKED;
} acx100_scan_t; /* length 0xc */
@@ -1698,17 +1698,17 @@ typedef struct acx100_scan {
#define ACX111_SCAN_MOD_OFDM 0x40
typedef struct acx111_scan {
u16 count ACX_PACKED; /* number of scans to do */
- u8 channel_list_select ACX_PACKED; /* 0: scan all channels, 1: from chan_list only */
+ u8 channel_list_select; /* 0: scan all channels, 1: from chan_list only */
u16 reserved1 ACX_PACKED;
- u8 reserved2 ACX_PACKED;
- u8 rate ACX_PACKED; /* rate for probe requests (if active scan) */
- u8 options ACX_PACKED; /* bit mask, see defines above */
+ u8 reserved2;
+ u8 rate; /* rate for probe requests (if active scan) */
+ u8 options; /* bit mask, see defines above */
u16 chan_duration ACX_PACKED; /* min time to wait for reply on one channel (in TU) */
/* (active scan only) (802.11 section 11.1.3.2.2) */
u16 max_probe_delay ACX_PACKED; /* max time to wait for reply on one channel (active scan) */
/* time to listen on a channel (passive scan) */
- u8 modulation ACX_PACKED;
- u8 channel_list[26] ACX_PACKED; /* bits 7:0 first byte: channels 8:1 */
+ u8 modulation;
+ u8 channel_list[26]; /* bits 7:0 first byte: channels 8:1 */
/* bits 7:0 second byte: channels 16:9 */
/* 26 bytes is enough to cover 802.11a */
} acx111_scan_t;
@@ -1748,50 +1748,50 @@ typedef struct acx111_cmd_radiocalib {
** - variable length fields shown only in comments */
typedef struct acx_template_tim {
u16 size ACX_PACKED;
- u8 tim_eid ACX_PACKED; /* 00 1 TIM IE ID * */
- u8 len ACX_PACKED; /* 01 1 Length * */
- u8 dtim_cnt ACX_PACKED; /* 02 1 DTIM Count */
- u8 dtim_period ACX_PACKED; /* 03 1 DTIM Period */
- u8 bitmap_ctrl ACX_PACKED; /* 04 1 Bitmap Control * (except bit0) */
+ u8 tim_eid; /* 00 1 TIM IE ID * */
+ u8 len; /* 01 1 Length * */
+ u8 dtim_cnt; /* 02 1 DTIM Count */
+ u8 dtim_period; /* 03 1 DTIM Period */
+ u8 bitmap_ctrl; /* 04 1 Bitmap Control * (except bit0) */
/* 05 n Partial Virtual Bitmap * */
- u8 variable[0x100 - 1-1-1-1-1] ACX_PACKED;
+ u8 variable[0x100 - 1-1-1-1-1];
} acx_template_tim_t;
typedef struct acx_template_probereq {
u16 size ACX_PACKED;
u16 fc ACX_PACKED; /* 00 2 fc * */
u16 dur ACX_PACKED; /* 02 2 Duration */
- u8 da[6] ACX_PACKED; /* 04 6 Destination Address * */
- u8 sa[6] ACX_PACKED; /* 0A 6 Source Address * */
- u8 bssid[6] ACX_PACKED; /* 10 6 BSSID * */
+ u8 da[6]; /* 04 6 Destination Address * */
+ u8 sa[6]; /* 0A 6 Source Address * */
+ u8 bssid[6]; /* 10 6 BSSID * */
u16 seq ACX_PACKED; /* 16 2 Sequence Control */
/* 18 n SSID * */
/* nn n Supported Rates * */
- u8 variable[0x44 - 2-2-6-6-6-2] ACX_PACKED;
+ u8 variable[0x44 - 2-2-6-6-6-2];
} acx_template_probereq_t;
typedef struct acx_template_proberesp {
u16 size ACX_PACKED;
u16 fc ACX_PACKED; /* 00 2 fc * (bits [15:12] and [10:8] per 802.11 section 7.1.3.1) */
u16 dur ACX_PACKED; /* 02 2 Duration */
- u8 da[6] ACX_PACKED; /* 04 6 Destination Address */
- u8 sa[6] ACX_PACKED; /* 0A 6 Source Address */
- u8 bssid[6] ACX_PACKED; /* 10 6 BSSID */
+ u8 da[6]; /* 04 6 Destination Address */
+ u8 sa[6]; /* 0A 6 Source Address */
+ u8 bssid[6]; /* 10 6 BSSID */
u16 seq ACX_PACKED; /* 16 2 Sequence Control */
- u8 timestamp[8] ACX_PACKED;/* 18 8 Timestamp */
+ u8 timestamp[8];/* 18 8 Timestamp */
u16 beacon_interval ACX_PACKED; /* 20 2 Beacon Interval * */
u16 cap ACX_PACKED; /* 22 2 Capability Information * */
/* 24 n SSID * */
/* nn n Supported Rates * */
/* nn 1 DS Parameter Set * */
- u8 variable[0x54 - 2-2-6-6-6-2-8-2-2] ACX_PACKED;
+ u8 variable[0x54 - 2-2-6-6-6-2-8-2-2];
} acx_template_proberesp_t;
#define acx_template_beacon_t acx_template_proberesp_t
#define acx_template_beacon acx_template_proberesp
typedef struct acx_template_nullframe {
u16 size ACX_PACKED;
- struct wlan_hdr_a3 hdr ACX_PACKED;
+ struct wlan_hdr_a3 hdr;
} acx_template_nullframe_t;
@@ -1801,27 +1801,27 @@ typedef struct acx_template_nullframe {
** as opposed to acx100, acx111 dtim interval is AFTER rates_basic111.
** NOTE: took me about an hour to get !@#$%^& packing right --> struct packing is eeeeevil... */
typedef struct acx_joinbss {
- u8 bssid[ETH_ALEN] ACX_PACKED;
+ u8 bssid[ETH_ALEN];
u16 beacon_interval ACX_PACKED;
union {
struct {
- u8 dtim_interval ACX_PACKED;
- u8 rates_basic ACX_PACKED;
- u8 rates_supported ACX_PACKED;
- } acx100 ACX_PACKED;
+ u8 dtim_interval;
+ u8 rates_basic;
+ u8 rates_supported;
+ } acx100;
struct {
u16 rates_basic ACX_PACKED;
- u8 dtim_interval ACX_PACKED;
- } acx111 ACX_PACKED;
- } u ACX_PACKED;
- u8 genfrm_txrate ACX_PACKED; /* generated frame (bcn, proberesp, RTS, PSpoll) tx rate */
- u8 genfrm_mod_pre ACX_PACKED; /* generated frame modulation/preamble:
+ u8 dtim_interval;
+ } acx111;
+ } u;
+ u8 genfrm_txrate; /* generated frame (bcn, proberesp, RTS, PSpoll) tx rate */
+ u8 genfrm_mod_pre; /* generated frame modulation/preamble:
** bit7: PBCC, bit6: OFDM (else CCK/DQPSK/DBPSK)
** bit5: short pre */
- u8 macmode ACX_PACKED; /* BSS Type, must be one of ACX_MODE_xxx */
- u8 channel ACX_PACKED;
- u8 essid_len ACX_PACKED;
- char essid[IW_ESSID_MAX_SIZE] ACX_PACKED;
+ u8 macmode; /* BSS Type, must be one of ACX_MODE_xxx */
+ u8 channel;
+ u8 essid_len;
+ char essid[IW_ESSID_MAX_SIZE];
} acx_joinbss_t;
#define JOINBSS_RATES_1 0x01
@@ -1862,7 +1862,7 @@ typedef struct mem_read_write {
typedef struct firmware_image {
u32 chksum ACX_PACKED;
u32 size ACX_PACKED;
- u8 data[1] ACX_PACKED; /* the byte array of the actual firmware... */
+ u8 data[1]; /* the byte array of the actual firmware... */
} firmware_image_t;
typedef struct acx_cmd_radioinit {
@@ -1874,42 +1874,42 @@ typedef struct acx100_ie_wep_options {
u16 type ACX_PACKED;
u16 len ACX_PACKED;
u16 NumKeys ACX_PACKED; /* max # of keys */
- u8 WEPOption ACX_PACKED; /* 0 == decrypt default key only, 1 == override decrypt */
- u8 Pad ACX_PACKED; /* used only for acx111 */
+ u8 WEPOption; /* 0 == decrypt default key only, 1 == override decrypt */
+ u8 Pad; /* used only for acx111 */
} acx100_ie_wep_options_t;
typedef struct ie_dot11WEPDefaultKey {
u16 type ACX_PACKED;
u16 len ACX_PACKED;
- u8 action ACX_PACKED;
- u8 keySize ACX_PACKED;
- u8 defaultKeyNum ACX_PACKED;
- u8 key[29] ACX_PACKED; /* check this! was Key[19] */
+ u8 action;
+ u8 keySize;
+ u8 defaultKeyNum;
+ u8 key[29]; /* check this! was Key[19] */
} ie_dot11WEPDefaultKey_t;
typedef struct acx111WEPDefaultKey {
- u8 MacAddr[ETH_ALEN] ACX_PACKED;
+ u8 MacAddr[ETH_ALEN];
u16 action ACX_PACKED; /* NOTE: this is a u16, NOT a u8!! */
u16 reserved ACX_PACKED;
- u8 keySize ACX_PACKED;
- u8 type ACX_PACKED;
- u8 index ACX_PACKED;
- u8 defaultKeyNum ACX_PACKED;
- u8 counter[6] ACX_PACKED;
- u8 key[32] ACX_PACKED; /* up to 32 bytes (for TKIP!) */
+ u8 keySize;
+ u8 type;
+ u8 index;
+ u8 defaultKeyNum;
+ u8 counter[6];
+ u8 key[32]; /* up to 32 bytes (for TKIP!) */
} acx111WEPDefaultKey_t;
typedef struct ie_dot11WEPDefaultKeyID {
u16 type ACX_PACKED;
u16 len ACX_PACKED;
- u8 KeyID ACX_PACKED;
+ u8 KeyID;
} ie_dot11WEPDefaultKeyID_t;
typedef struct acx100_cmd_wep_mgmt {
- u8 MacAddr[ETH_ALEN] ACX_PACKED;
+ u8 MacAddr[ETH_ALEN];
u16 Action ACX_PACKED;
u16 KeySize ACX_PACKED;
- u8 Key[29] ACX_PACKED; /* 29*8 == 232bits == WEP256 */
+ u8 Key[29]; /* 29*8 == 232bits == WEP256 */
} acx100_cmd_wep_mgmt_t;
/* UNUSED?
@@ -1927,7 +1927,7 @@ typedef struct acx_ie_generic {
u16 aid;
/* UNUSED? struct defaultkey dkey ACX_PACKED; */
/* generic member for quick implementation of commands */
- u8 bytes[32] ACX_PACKED;
+ u8 bytes[32];
} m ACX_PACKED;
} acx_ie_generic_t;
Index: linux-2.6.16/drivers/net/wireless/tiacx/wlan_compat.h
===================================================================
--- linux-2.6.16.orig/drivers/net/wireless/tiacx/wlan_compat.h
+++ linux-2.6.16/drivers/net/wireless/tiacx/wlan_compat.h
@@ -243,20 +243,20 @@ typedef void irqreturn_t;
/* local ether header type */
typedef struct wlan_ethhdr {
- u8 daddr[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 saddr[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 daddr[ETH_ALEN];
+ u8 saddr[ETH_ALEN];
u16 type __WLAN_ATTRIB_PACK__;
} wlan_ethhdr_t;
/* local llc header type */
typedef struct wlan_llc {
- u8 dsap __WLAN_ATTRIB_PACK__;
- u8 ssap __WLAN_ATTRIB_PACK__;
- u8 ctl __WLAN_ATTRIB_PACK__;
+ u8 dsap;
+ u8 ssap;
+ u8 ctl;
} wlan_llc_t;
/* local snap header type */
typedef struct wlan_snap {
- u8 oui[WLAN_IEEE_OUI_LEN] __WLAN_ATTRIB_PACK__;
+ u8 oui[WLAN_IEEE_OUI_LEN];
u16 type __WLAN_ATTRIB_PACK__;
} wlan_snap_t;
Index: linux-2.6.16/drivers/net/wireless/tiacx/wlan_hdr.h
===================================================================
--- linux-2.6.16.orig/drivers/net/wireless/tiacx/wlan_hdr.h
+++ linux-2.6.16/drivers/net/wireless/tiacx/wlan_hdr.h
@@ -339,29 +339,29 @@ IEEE16(WF_FSTYPE_CFACK_CFPOLL, 0x70)
typedef struct wlan_hdr {
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 a1[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 a2[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 a3[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 a1[ETH_ALEN];
+ u8 a2[ETH_ALEN];
+ u8 a3[ETH_ALEN];
u16 seq __WLAN_ATTRIB_PACK__;
- u8 a4[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 a4[ETH_ALEN];
} wlan_hdr_t;
/* Separate structs for use if frame type is known */
typedef struct wlan_hdr_a3 {
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 a1[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 a2[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 a3[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 a1[ETH_ALEN];
+ u8 a2[ETH_ALEN];
+ u8 a3[ETH_ALEN];
u16 seq __WLAN_ATTRIB_PACK__;
} wlan_hdr_a3_t;
typedef struct wlan_hdr_mgmt {
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 da[ETH_ALEN];
+ u8 sa[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
u16 seq __WLAN_ATTRIB_PACK__;
} wlan_hdr_mgmt_t;
@@ -369,78 +369,78 @@ typedef struct wlan_hdr_mgmt {
typedef struct { /* ad-hoc peer->peer (to/from DS = 0/0) */
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 da[ETH_ALEN];
+ u8 sa[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
u16 seq __WLAN_ATTRIB_PACK__;
} ibss;
typedef struct { /* ap->sta (to/from DS = 0/1) */
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 da[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+ u8 sa[ETH_ALEN];
u16 seq __WLAN_ATTRIB_PACK__;
} fromap;
typedef struct { /* sta->ap (to/from DS = 1/0) */
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 bssid[ETH_ALEN];
+ u8 sa[ETH_ALEN];
+ u8 da[ETH_ALEN];
u16 seq __WLAN_ATTRIB_PACK__;
} toap;
typedef struct { /* wds->wds (to/from DS = 1/1), the only 4addr pkt */
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 ra[ETH_ALEN];
+ u8 ta[ETH_ALEN];
+ u8 da[ETH_ALEN];
u16 seq __WLAN_ATTRIB_PACK__;
- u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 sa[ETH_ALEN];
} wds;
typedef struct { /* all management packets */
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 da[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 sa[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 da[ETH_ALEN];
+ u8 sa[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
u16 seq __WLAN_ATTRIB_PACK__;
} mgmt;
typedef struct { /* has no body, just a FCS */
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 ra[ETH_ALEN];
+ u8 ta[ETH_ALEN];
} rts;
typedef struct { /* has no body, just a FCS */
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 ra[ETH_ALEN];
} cts;
typedef struct { /* has no body, just a FCS */
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 ra[ETH_ALEN];
} ack;
typedef struct { /* has no body, just a FCS */
u16 fc __WLAN_ATTRIB_PACK__;
/* NB: this one holds Assoc ID in dur field: */
u16 aid __WLAN_ATTRIB_PACK__;
- u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 ta[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 bssid[ETH_ALEN];
+ u8 ta[ETH_ALEN];
} pspoll;
typedef struct { /* has no body, just a FCS */
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 ra[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
} cfend;
typedef struct { /* has no body, just a FCS */
u16 fc __WLAN_ATTRIB_PACK__;
u16 dur __WLAN_ATTRIB_PACK__;
- u8 ra[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- u8 bssid[ETH_ALEN] __WLAN_ATTRIB_PACK__;
+ u8 ra[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
} cfendcfack;
#endif
@@ -472,17 +472,17 @@ typedef struct wlanitem_u32 {
typedef struct wlansniffrm {
u32 msgcode __WLAN_ATTRIB_PACK__;
u32 msglen __WLAN_ATTRIB_PACK__;
- u8 devname[WLAN_DEVNAMELEN_MAX] __WLAN_ATTRIB_PACK__;
- wlanitem_u32_t hosttime __WLAN_ATTRIB_PACK__;
- wlanitem_u32_t mactime __WLAN_ATTRIB_PACK__;
- wlanitem_u32_t channel __WLAN_ATTRIB_PACK__;
- wlanitem_u32_t rssi __WLAN_ATTRIB_PACK__;
- wlanitem_u32_t sq __WLAN_ATTRIB_PACK__;
- wlanitem_u32_t signal __WLAN_ATTRIB_PACK__;
- wlanitem_u32_t noise __WLAN_ATTRIB_PACK__;
- wlanitem_u32_t rate __WLAN_ATTRIB_PACK__;
- wlanitem_u32_t istx __WLAN_ATTRIB_PACK__; /* tx? 0:no 1:yes */
- wlanitem_u32_t frmlen __WLAN_ATTRIB_PACK__;
+ u8 devname[WLAN_DEVNAMELEN_MAX];
+ wlanitem_u32_t hosttime;
+ wlanitem_u32_t mactime;
+ wlanitem_u32_t channel;
+ wlanitem_u32_t rssi;
+ wlanitem_u32_t sq;
+ wlanitem_u32_t signal;
+ wlanitem_u32_t noise;
+ wlanitem_u32_t rate;
+ wlanitem_u32_t istx; /* tx? 0:no 1:yes */
+ wlanitem_u32_t frmlen;
} wlansniffrm_t;
#define WLANSNIFFFRM 0x0041
#define WLANSNIFFFRM_hosttime 0x1041
Index: linux-2.6.16/drivers/net/wireless/tiacx/wlan_mgmt.h
===================================================================
--- linux-2.6.16.orig/drivers/net/wireless/tiacx/wlan_mgmt.h
+++ linux-2.6.16/drivers/net/wireless/tiacx/wlan_mgmt.h
@@ -199,84 +199,84 @@ IEEE16(WF_MGMT_CAP_CCKOFDM, 0x2000)
/* prototype structure, all IEs start with these members */
typedef struct wlan_ie {
- u8 eid __WLAN_ATTRIB_PACK__;
- u8 len __WLAN_ATTRIB_PACK__;
+ u8 eid;
+ u8 len;
} wlan_ie_t;
/*-- Service Set Identity (SSID) -----------------*/
typedef struct wlan_ie_ssid {
- u8 eid __WLAN_ATTRIB_PACK__;
- u8 len __WLAN_ATTRIB_PACK__;
- u8 ssid[1] __WLAN_ATTRIB_PACK__; /* may be zero */
+ u8 eid;
+ u8 len;
+ u8 ssid[1]; /* may be zero */
} wlan_ie_ssid_t;
/*-- Supported Rates -----------------------------*/
typedef struct wlan_ie_supp_rates {
- u8 eid __WLAN_ATTRIB_PACK__;
- u8 len __WLAN_ATTRIB_PACK__;
- u8 rates[1] __WLAN_ATTRIB_PACK__; /* had better be at LEAST one! */
+ u8 eid;
+ u8 len;
+ u8 rates[1]; /* had better be at LEAST one! */
} wlan_ie_supp_rates_t;
/*-- FH Parameter Set ----------------------------*/
typedef struct wlan_ie_fh_parms {
- u8 eid __WLAN_ATTRIB_PACK__;
- u8 len __WLAN_ATTRIB_PACK__;
+ u8 eid;
+ u8 len;
u16 dwell __WLAN_ATTRIB_PACK__;
- u8 hopset __WLAN_ATTRIB_PACK__;
- u8 hoppattern __WLAN_ATTRIB_PACK__;
- u8 hopindex __WLAN_ATTRIB_PACK__;
+ u8 hopset;
+ u8 hoppattern;
+ u8 hopindex;
} wlan_ie_fh_parms_t;
/*-- DS Parameter Set ----------------------------*/
typedef struct wlan_ie_ds_parms {
- u8 eid __WLAN_ATTRIB_PACK__;
- u8 len __WLAN_ATTRIB_PACK__;
- u8 curr_ch __WLAN_ATTRIB_PACK__;
+ u8 eid;
+ u8 len;
+ u8 curr_ch;
} wlan_ie_ds_parms_t;
/*-- CF Parameter Set ----------------------------*/
typedef struct wlan_ie_cf_parms {
- u8 eid __WLAN_ATTRIB_PACK__;
- u8 len __WLAN_ATTRIB_PACK__;
- u8 cfp_cnt __WLAN_ATTRIB_PACK__;
- u8 cfp_period __WLAN_ATTRIB_PACK__;
+ u8 eid;
+ u8 len;
+ u8 cfp_cnt;
+ u8 cfp_period;
u16 cfp_maxdur __WLAN_ATTRIB_PACK__;
u16 cfp_durremaining __WLAN_ATTRIB_PACK__;
} wlan_ie_cf_parms_t;
/*-- TIM ------------------------------------------*/
typedef struct wlan_ie_tim {
- u8 eid __WLAN_ATTRIB_PACK__;
- u8 len __WLAN_ATTRIB_PACK__;
- u8 dtim_cnt __WLAN_ATTRIB_PACK__;
- u8 dtim_period __WLAN_ATTRIB_PACK__;
- u8 bitmap_ctl __WLAN_ATTRIB_PACK__;
- u8 virt_bm[1] __WLAN_ATTRIB_PACK__;
+ u8 eid;
+ u8 len;
+ u8 dtim_cnt;
+ u8 dtim_period;
+ u8 bitmap_ctl;
+ u8 virt_bm[1];
} wlan_ie_tim_t;
/*-- IBSS Parameter Set ---------------------------*/
typedef struct wlan_ie_ibss_parms {
- u8 eid __WLAN_ATTRIB_PACK__;
- u8 len __WLAN_ATTRIB_PACK__;
+ u8 eid;
+ u8 len;
u16 atim_win __WLAN_ATTRIB_PACK__;
} wlan_ie_ibss_parms_t;
/*-- Challenge Text ------------------------------*/
typedef struct wlan_ie_challenge {
- u8 eid __WLAN_ATTRIB_PACK__;
- u8 len __WLAN_ATTRIB_PACK__;
- u8 challenge[1] __WLAN_ATTRIB_PACK__;
+ u8 eid;
+ u8 len;
+ u8 challenge[1];
} wlan_ie_challenge_t;
/*-- ERP (42) -------------------------------------*/
typedef struct wlan_ie_erp {
- u8 eid __WLAN_ATTRIB_PACK__;
- u8 len __WLAN_ATTRIB_PACK__;
+ u8 eid;
+ u8 len;
/* bit 0:Non ERP present
** 1:Use Protection
** 2:Barker Preamble mode
** 3-7:reserved */
- u8 erp __WLAN_ATTRIB_PACK__;
+ u8 erp;
} wlan_ie_erp_t;
/* Types for parsing mgmt frames */
@@ -434,21 +434,21 @@ typedef struct auth_frame_body {
u16 auth_alg __WLAN_ATTRIB_PACK__;
u16 auth_seq __WLAN_ATTRIB_PACK__;
u16 status __WLAN_ATTRIB_PACK__;
- wlan_ie_challenge_t challenge __WLAN_ATTRIB_PACK__;
+ wlan_ie_challenge_t challenge;
} auth_frame_body_t;
typedef struct assocresp_frame_body {
u16 cap_info __WLAN_ATTRIB_PACK__;
u16 status __WLAN_ATTRIB_PACK__;
u16 aid __WLAN_ATTRIB_PACK__;
- wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
+ wlan_ie_supp_rates_t rates;
} assocresp_frame_body_t;
typedef struct reassocreq_frame_body {
u16 cap_info __WLAN_ATTRIB_PACK__;
u16 listen_int __WLAN_ATTRIB_PACK__;
- u8 current_ap[ETH_ALEN] __WLAN_ATTRIB_PACK__;
- wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
+ u8 current_ap[ETH_ALEN];
+ wlan_ie_ssid_t ssid;
/* access to this one is disabled since ssid_t is variable length: */
/* wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__; */
} reassocreq_frame_body_t;
@@ -457,7 +457,7 @@ typedef struct reassocresp_frame_body {
u16 cap_info __WLAN_ATTRIB_PACK__;
u16 status __WLAN_ATTRIB_PACK__;
u16 aid __WLAN_ATTRIB_PACK__;
- wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
+ wlan_ie_supp_rates_t rates;
} reassocresp_frame_body_t;
typedef struct deauthen_frame_body {
@@ -469,15 +469,15 @@ typedef struct disassoc_frame_body {
} disassoc_frame_body_t;
typedef struct probereq_frame_body {
- wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
- wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__;
+ wlan_ie_ssid_t ssid;
+ wlan_ie_supp_rates_t rates;
} probereq_frame_body_t;
typedef struct proberesp_frame_body {
- u8 timestamp[8] __WLAN_ATTRIB_PACK__;
+ u8 timestamp[8];
u16 beacon_int __WLAN_ATTRIB_PACK__;
u16 cap_info __WLAN_ATTRIB_PACK__;
- wlan_ie_ssid_t ssid __WLAN_ATTRIB_PACK__;
+ wlan_ie_ssid_t ssid;
/* access to these is disabled since ssid_t is variable length: */
/* wlan_ie_supp_rates_t rates __WLAN_ATTRIB_PACK__; */
/* fhps_t fhps __WLAN_ATTRIB_PACK__; */
Index: linux-2.6.16/drivers/net/wireless/tiacx/usb.c
===================================================================
--- linux-2.6.16.orig/drivers/net/wireless/tiacx/usb.c
+++ linux-2.6.16/drivers/net/wireless/tiacx/usb.c
@@ -281,7 +281,7 @@ acxusb_s_issue_cmd_timeo_debug(
struct {
u16 cmd ACX_PACKED;
u16 status ACX_PACKED;
- u8 data[1] ACX_PACKED;
+ u8 data[1];
} *loc;
const char *devname;
int acklen, blocklen, inpipe, outpipe;
^ permalink raw reply
* [PATCH -mm] emu10k gcc 4.1 warning fix
From: Daniel Walker @ 2006-05-10 2:55 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
Fixes the following warning,
sound/oss/emu10k1/passthrough.c: In function 'emu10k1_pt_write':
sound/oss/emu10k1/passthrough.c:165: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
sound/oss/emu10k1/passthrough.c:170: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
sound/oss/emu10k1/passthrough.c:181: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
sound/oss/emu10k1/passthrough.c:196: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
sound/oss/emu10k1/cardwi.c: In function 'copy_block':
sound/oss/emu10k1/cardwi.c:310: warning: ignoring return value of '__copy_to_user', declared with attribute warn_unused_result
sound/oss/emu10k1/cardwi.c:319: warning: ignoring return value of '__copy_to_user', declared with attribute warn_unused_result
Signed-Off-By: Daniel Walker <dwalker@mvista.com>
Index: linux-2.6.16/sound/oss/emu10k1/passthrough.c
===================================================================
--- linux-2.6.16.orig/sound/oss/emu10k1/passthrough.c
+++ linux-2.6.16/sound/oss/emu10k1/passthrough.c
@@ -162,12 +162,14 @@ ssize_t emu10k1_pt_write(struct file *fi
DPD(3, "prepend size %d, prepending %d bytes\n", pt->prepend_size, needed);
if (count < needed) {
- copy_from_user(pt->buf + pt->prepend_size, buffer, count);
+ if (copy_from_user(pt->buf + pt->prepend_size, buffer, count))
+ return -EFAULT;
pt->prepend_size += count;
DPD(3, "prepend size now %d\n", pt->prepend_size);
return count;
}
- copy_from_user(pt->buf + pt->prepend_size, buffer, needed);
+ if (copy_from_user(pt->buf + pt->prepend_size, buffer, needed))
+ return -EFAULT;
r = pt_putblock(wave_dev, (u16 *) pt->buf, nonblock);
if (r)
return r;
@@ -178,7 +180,8 @@ ssize_t emu10k1_pt_write(struct file *fi
blocks_copied = 0;
while (blocks > 0) {
u16 __user *bufptr = (u16 __user *) buffer + (bytes_copied/2);
- copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE);
+ if (copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE))
+ return -EFAULT;
r = pt_putblock(wave_dev, (u16 *)pt->buf, nonblock);
if (r) {
if (bytes_copied)
@@ -193,7 +196,8 @@ ssize_t emu10k1_pt_write(struct file *fi
i = count - bytes_copied;
if (i) {
pt->prepend_size = i;
- copy_from_user(pt->buf, buffer + bytes_copied, i);
+ if (copy_from_user(pt->buf, buffer + bytes_copied, i))
+ return -EFAULT;
bytes_copied += i;
DPD(3, "filling prepend buffer with %d bytes", i);
}
Index: linux-2.6.16/sound/oss/emu10k1/cardwi.c
===================================================================
--- linux-2.6.16.orig/sound/oss/emu10k1/cardwi.c
+++ linux-2.6.16/sound/oss/emu10k1/cardwi.c
@@ -307,7 +307,7 @@ void emu10k1_wavein_getxfersize(struct w
static void copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
{
if (cov == 1)
- __copy_to_user(dst, src + str, len);
+ WARN_ON(__copy_to_user(dst, src + str, len));
else {
u8 byte;
u32 i;
@@ -316,7 +316,7 @@ static void copy_block(u8 __user *dst, u
for (i = 0; i < len; i++) {
byte = src[2 * i] ^ 0x80;
- __copy_to_user(dst + i, &byte, 1);
+ WARN_ON(__copy_to_user(dst + i, &byte, 1));
}
}
}
^ permalink raw reply
* [PATCH -mm] matroxfb_maven gcc 4.1 warning fix
From: Daniel Walker @ 2006-05-10 2:56 UTC (permalink / raw)
To: akpm; +Cc: vandrove, linux-kernel
It looks possible that the PLL and clock functions might get into a condition
when these stack variables would get used/returned with uninitialized
data . So it needs further review ..
Fixes the following warning,
drivers/video/matrox/matroxfb_maven.c: In function 'maven_out_compute':
drivers/video/matrox/matroxfb_maven.c:287: warning: 'p' may be used uninitialized in this function
drivers/video/matrox/matroxfb_maven.c:718: warning: 'h2' may be used uninitialized in this function
drivers/video/matrox/matroxfb_maven.c:718: warning: 'b' may be used uninitialized in this function
drivers/video/matrox/matroxfb_maven.c:718: warning: 'a' may be used uninitialized in this function
Signed-Off-By: Daniel Walker <dwalker@mvista.com>
Index: linux-2.6.16/drivers/video/matrox/matroxfb_maven.c
===================================================================
--- linux-2.6.16.orig/drivers/video/matrox/matroxfb_maven.c
+++ linux-2.6.16/drivers/video/matrox/matroxfb_maven.c
@@ -284,7 +284,7 @@ static unsigned int matroxfb_mavenclock(
unsigned int* in, unsigned int* feed, unsigned int* post,
unsigned int* htotal2) {
unsigned int fvco;
- unsigned int p;
+ unsigned int p = 0;
fvco = matroxfb_PLL_mavenclock(&maven1000_pll, ctl, htotal, vtotal, in, feed, &p, htotal2);
if (!fvco)
@@ -715,7 +715,10 @@ static int maven_find_exact_clocks(unsig
m->regs[0x82] = 0x81;
for (x = 0; x < 8; x++) {
- unsigned int a, b, c, h2;
+ unsigned int a = 0;
+ unsigned int b = 0;
+ unsigned int h2 = 0;
+ unsigned int c;
unsigned int h = ht + 2 + x;
if (!matroxfb_mavenclock((m->mode == MATROXFB_OUTPUT_MODE_PAL) ? &maven_PAL : &maven_NTSC, h, vt, &a, &b, &c, &h2)) {
^ permalink raw reply
* [PATCH -mm] BusLogic gcc 4.1 warning fixes
From: Daniel Walker @ 2006-05-10 2:55 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
I just commented out BusLogic_AbortCommand because the code that uses it is
commented out the same way .. It could just be removed .
Fixes the following warnings,
drivers/scsi/BusLogic.c: In function 'BusLogic_init':
drivers/scsi/BusLogic.c:2302: warning: ignoring return value of 'scsi_add_host', declared with attribute warn_unused_result
drivers/scsi/BusLogic.c: At top level:
drivers/scsi/BusLogic.c:2963: warning: 'BusLogic_AbortCommand' defined but not used
Signed-Off-By: Daniel Walker <dwalker@mvista.com>
Index: linux-2.6.16/drivers/scsi/BusLogic.c
===================================================================
--- linux-2.6.16.orig/drivers/scsi/BusLogic.c
+++ linux-2.6.16/drivers/scsi/BusLogic.c
@@ -2299,7 +2299,8 @@ static int __init BusLogic_init(void)
scsi_host_put(Host);
} else {
BusLogic_InitializeHostStructure(HostAdapter, Host);
- scsi_add_host(Host, HostAdapter->PCI_Device ? &HostAdapter->PCI_Device->dev : NULL);
+ if (scsi_add_host(Host, HostAdapter->PCI_Device ? &HostAdapter->PCI_Device->dev : NULL))
+ return -ENODEV;
scsi_scan_host(Host);
BusLogicHostAdapterCount++;
}
@@ -2955,6 +2956,7 @@ static int BusLogic_QueueCommand(struct
}
+#if 0
/*
BusLogic_AbortCommand aborts Command if possible.
*/
@@ -3025,6 +3027,7 @@ static int BusLogic_AbortCommand(struct
return SUCCESS;
}
+#endif
/*
BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all
currently executing SCSI Commands as having been Reset.
^ permalink raw reply
* [PATCH -mm] isdn sc driver gcc 4.1 warnings fix
From: Daniel Walker @ 2006-05-10 2:55 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
Fixes the following warnings,
drivers/isdn/sc/shmem.c: In function 'memcpy_toshmem':
drivers/isdn/sc/shmem.c:60: warning: passing argument 1 of 'memcpy_toio' makes pointer from integer without a cast
drivers/isdn/sc/init.c: In function 'identify_board':
drivers/isdn/sc/init.c:492: warning: passing argument 1 of 'readl' makes pointer from integer without a cast
drivers/isdn/sc/init.c:502: warning: passing argument 1 of 'readl' makes pointer from integer without a cast
drivers/isdn/sc/init.c:512: warning: passing argument 1 of 'readl' makes pointer from integer without a cast
Signed-Off-By: Daniel Walker <dwalker@mvista.com>
Index: linux-2.6.16/drivers/isdn/sc/init.c
===================================================================
--- linux-2.6.16.orig/drivers/isdn/sc/init.c
+++ linux-2.6.16/drivers/isdn/sc/init.c
@@ -489,7 +489,7 @@ static int identify_board(unsigned long
*/
outb(PRI_BASEPG_VAL, pgport);
msleep_interruptible(1000);
- sig = readl(rambase + SIG_OFFSET);
+ sig = readl((void *)(rambase + SIG_OFFSET));
pr_debug("Looking for a signature, got 0x%x\n", sig);
if(sig == SIGNATURE)
return PRI_BOARD;
@@ -499,7 +499,7 @@ static int identify_board(unsigned long
*/
outb(BRI_BASEPG_VAL, pgport);
msleep_interruptible(1000);
- sig = readl(rambase + SIG_OFFSET);
+ sig = readl((void *)(rambase + SIG_OFFSET));
pr_debug("Looking for a signature, got 0x%x\n", sig);
if(sig == SIGNATURE)
return BRI_BOARD;
@@ -509,7 +509,7 @@ static int identify_board(unsigned long
/*
* Try to spot a card
*/
- sig = readl(rambase + SIG_OFFSET);
+ sig = readl((void *)(rambase + SIG_OFFSET));
pr_debug("Looking for a signature, got 0x%x\n", sig);
if(sig != SIGNATURE)
return -1;
Index: linux-2.6.16/drivers/isdn/sc/shmem.c
===================================================================
--- linux-2.6.16.orig/drivers/isdn/sc/shmem.c
+++ linux-2.6.16/drivers/isdn/sc/shmem.c
@@ -56,8 +56,8 @@ void memcpy_toshmem(int card, void *dest
outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
- memcpy_toio(sc_adapter[card]->rambase +
- ((unsigned long) dest % 0x4000), src, n);
+ memcpy_toio((void *)(sc_adapter[card]->rambase +
+ ((unsigned long) dest % 0x4000)), src, n);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.