Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2003-06-13 20:15:21 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-06-13 20:15:21 -0700
commitbd91ad934d281efd5092847043322b99b2677fb0 (patch)
treeb2fe199d7ee78a09143a0b4f7116bc42ee83eacd
parent40588f73e90edbb0c33dd12ea243a5ed53d61dbc (diff)
parent5ba15264497f679311126896820b7f63c81f03ba (diff)
Merge bk://linux-dj.bkbits.net/agpgart
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--arch/alpha/vmlinux.lds.S3
-rw-r--r--arch/arm/vmlinux-armo.lds.in1
-rw-r--r--arch/arm/vmlinux-armv.lds.in1
-rw-r--r--arch/cris/vmlinux.lds.S7
-rw-r--r--arch/h8300/platform/h8300h/generic/rom.ld1
-rw-r--r--arch/i386/vmlinux.lds.S1
-rw-r--r--arch/ia64/vmlinux.lds.S4
-rw-r--r--arch/m68k/vmlinux-std.lds1
-rw-r--r--arch/m68k/vmlinux-sun3.lds1
-rw-r--r--arch/m68knommu/vmlinux.lds.S4
-rw-r--r--arch/mips/vmlinux.lds.S1
-rw-r--r--arch/mips64/vmlinux.lds.S1
-rw-r--r--arch/parisc/vmlinux.lds.S1
-rw-r--r--arch/ppc/vmlinux.lds.S2
-rw-r--r--arch/ppc64/vmlinux.lds.S1
-rw-r--r--arch/s390/vmlinux.lds.S1
-rw-r--r--arch/sh/vmlinux.lds.S1
-rw-r--r--arch/sparc/vmlinux.lds.S1
-rw-r--r--arch/sparc64/vmlinux.lds.S1
-rw-r--r--arch/x86_64/Kconfig12
-rw-r--r--arch/x86_64/ia32/ia32entry.S1
-rw-r--r--arch/x86_64/kernel/acpi/boot.c6
-rw-r--r--arch/x86_64/kernel/apic.c8
-rw-r--r--arch/x86_64/kernel/bluesmoke.c14
-rw-r--r--arch/x86_64/kernel/pci-gart.c15
-rw-r--r--arch/x86_64/kernel/process.c6
-rw-r--r--arch/x86_64/kernel/smpboot.c11
-rw-r--r--arch/x86_64/kernel/time.c258
-rw-r--r--arch/x86_64/kernel/traps.c2
-rw-r--r--arch/x86_64/kernel/vsyscall.c18
-rw-r--r--arch/x86_64/lib/clear_page.S32
-rw-r--r--arch/x86_64/lib/copy_page.S149
-rw-r--r--arch/x86_64/lib/csum-copy.S294
-rw-r--r--arch/x86_64/lib/csum-partial.c100
-rw-r--r--arch/x86_64/lib/csum-wrappers.c62
-rw-r--r--arch/x86_64/lib/memcpy.S95
-rw-r--r--arch/x86_64/lib/memset.S57
-rw-r--r--arch/x86_64/vmlinux.lds.S7
-rw-r--r--drivers/char/rocket.c287
-rw-r--r--drivers/char/rocket.h24
-rw-r--r--drivers/char/rocket_int.h46
-rw-r--r--drivers/ieee1394/dv1394.c7
-rw-r--r--drivers/ieee1394/eth1394.c8
-rw-r--r--drivers/ieee1394/ohci1394.c2
-rw-r--r--drivers/pci/pci.ids2
-rw-r--r--drivers/scsi/scsi_scan.c4
-rw-r--r--fs/fs-writeback.c15
-rw-r--r--fs/namei.c2
-rw-r--r--include/asm-generic/vmlinux.lds.h6
-rw-r--r--include/asm-i386/fixmap.h8
-rw-r--r--include/asm-x86_64/checksum.h12
-rw-r--r--include/asm-x86_64/fixmap.h2
-rw-r--r--include/asm-x86_64/mc146818rtc.h5
-rw-r--r--include/asm-x86_64/processor.h2
-rw-r--r--include/asm-x86_64/proto.h2
-rw-r--r--include/asm-x86_64/timex.h30
-rw-r--r--include/asm-x86_64/vsyscall.h18
-rw-r--r--include/linux/init.h6
-rw-r--r--include/linux/pci_ids.h2
-rw-r--r--include/linux/security.h39
-rw-r--r--init/main.c2
-rw-r--r--kernel/sys.c20
-rw-r--r--mm/memory.c14
-rw-r--r--security/capability.c10
-rw-r--r--security/dummy.c12
-rw-r--r--security/root_plug.c3
-rw-r--r--security/security.c13
67 files changed, 888 insertions, 896 deletions
diff --git a/arch/alpha/vmlinux.lds.S b/arch/alpha/vmlinux.lds.S
index 863e60644e83..7afd00d5d46b 100644
--- a/arch/alpha/vmlinux.lds.S
+++ b/arch/alpha/vmlinux.lds.S
@@ -74,6 +74,9 @@ SECTIONS
__con_initcall_end = .;
}
+ . = ALIGN(8);
+ SECURITY_INIT
+
. = ALIGN(64);
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
diff --git a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
index 18e100b67d67..7fc51a94a942 100644
--- a/arch/arm/vmlinux-armo.lds.in
+++ b/arch/arm/vmlinux-armo.lds.in
@@ -43,6 +43,7 @@ SECTIONS
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(32768);
__init_end = .;
}
diff --git a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
index d43fee522ecf..0c84ec532647 100644
--- a/arch/arm/vmlinux-armv.lds.in
+++ b/arch/arm/vmlinux-armv.lds.in
@@ -53,6 +53,7 @@ SECTIONS
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(32);
__initramfs_start = .;
usr/built-in.o(.init.ramfs)
diff --git a/arch/cris/vmlinux.lds.S b/arch/cris/vmlinux.lds.S
index 541857dd070d..3a5f1a36da38 100644
--- a/arch/cris/vmlinux.lds.S
+++ b/arch/cris/vmlinux.lds.S
@@ -74,7 +74,12 @@ SECTIONS
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
-
+ }
+ .security_initcall.init : {
+ __security_initcall_start = .;
+ *(.security_initcall.init)
+ __security_initcall_end = .;
+
/* We fill to the next page, so we can discard all init
pages without needing to consider what payload might be
appended to the kernel image. */
diff --git a/arch/h8300/platform/h8300h/generic/rom.ld b/arch/h8300/platform/h8300h/generic/rom.ld
index 5453fe42b586..412d9006f2ea 100644
--- a/arch/h8300/platform/h8300h/generic/rom.ld
+++ b/arch/h8300/platform/h8300h/generic/rom.ld
@@ -83,6 +83,7 @@ SECTIONS
___con_initcall_start = .;
*(.con_initcall.init)
___con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(4);
___initramfs_start = .;
*(.init.ramfs)
diff --git a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
index 5f024651c44a..fb1ef98b8c25 100644
--- a/arch/i386/vmlinux.lds.S
+++ b/arch/i386/vmlinux.lds.S
@@ -81,6 +81,7 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(4);
__alt_instructions = .;
.altinstructions : { *(.altinstructions) }
diff --git a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S
index fc52b7b57626..3d9f69fefaa3 100644
--- a/arch/ia64/vmlinux.lds.S
+++ b/arch/ia64/vmlinux.lds.S
@@ -141,6 +141,10 @@ SECTIONS
.con_initcall.init : AT(ADDR(.con_initcall.init) - PAGE_OFFSET)
{ *(.con_initcall.init) }
__con_initcall_end = .;
+ __security_initcall_start = .;
+ .security_initcall.init : AT(ADDR(.security_initcall.init) - PAGE_OFFSET)
+ { *(.security_initcall.init) }
+ __security_initcall_end = .;
. = ALIGN(PAGE_SIZE);
__init_end = .;
diff --git a/arch/m68k/vmlinux-std.lds b/arch/m68k/vmlinux-std.lds
index 959c6ae41430..bd41fc992169 100644
--- a/arch/m68k/vmlinux-std.lds
+++ b/arch/m68k/vmlinux-std.lds
@@ -67,6 +67,7 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(8192);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
diff --git a/arch/m68k/vmlinux-sun3.lds b/arch/m68k/vmlinux-sun3.lds
index 03ada554c074..2e81cde14987 100644
--- a/arch/m68k/vmlinux-sun3.lds
+++ b/arch/m68k/vmlinux-sun3.lds
@@ -61,6 +61,7 @@ __init_begin = .;
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(8192);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
diff --git a/arch/m68knommu/vmlinux.lds.S b/arch/m68knommu/vmlinux.lds.S
index 1ab8a31ef964..fa2004ada4ba 100644
--- a/arch/m68knommu/vmlinux.lds.S
+++ b/arch/m68knommu/vmlinux.lds.S
@@ -277,9 +277,7 @@ SECTIONS {
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
- __security_initcall_start = .;
- *(.security_initcall.init)
- __security_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(4);
__initramfs_start = .;
*(.init.ramfs)
diff --git a/arch/mips/vmlinux.lds.S b/arch/mips/vmlinux.lds.S
index edf922683c41..328e87a5face 100644
--- a/arch/mips/vmlinux.lds.S
+++ b/arch/mips/vmlinux.lds.S
@@ -54,6 +54,7 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(4096); /* Align double page for init_task_union */
__init_end = .;
diff --git a/arch/mips64/vmlinux.lds.S b/arch/mips64/vmlinux.lds.S
index fe42ea894f53..89bf58aa67bd 100644
--- a/arch/mips64/vmlinux.lds.S
+++ b/arch/mips64/vmlinux.lds.S
@@ -53,6 +53,7 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(4096); /* Align double page for init_task_union */
__init_end = .;
diff --git a/arch/parisc/vmlinux.lds.S b/arch/parisc/vmlinux.lds.S
index 99db5cb1cc56..32c089a36c9c 100644
--- a/arch/parisc/vmlinux.lds.S
+++ b/arch/parisc/vmlinux.lds.S
@@ -80,6 +80,7 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
diff --git a/arch/ppc/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S
index a682eccfa0dd..467b859c4266 100644
--- a/arch/ppc/vmlinux.lds.S
+++ b/arch/ppc/vmlinux.lds.S
@@ -119,6 +119,8 @@ SECTIONS
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
+
__start___ftr_fixup = .;
__ftr_fixup : { *(__ftr_fixup) }
__stop___ftr_fixup = .;
diff --git a/arch/ppc64/vmlinux.lds.S b/arch/ppc64/vmlinux.lds.S
index f6429d5d13c0..8ce3e03d23e6 100644
--- a/arch/ppc64/vmlinux.lds.S
+++ b/arch/ppc64/vmlinux.lds.S
@@ -104,6 +104,7 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
diff --git a/arch/s390/vmlinux.lds.S b/arch/s390/vmlinux.lds.S
index db6140c6b30a..bf599bab85e1 100644
--- a/arch/s390/vmlinux.lds.S
+++ b/arch/s390/vmlinux.lds.S
@@ -94,6 +94,7 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(256);
__initramfs_start = .;
.init.ramfs : { *(.init.initramfs) }
diff --git a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S
index f618f3b43900..a4c0869ac3e1 100644
--- a/arch/sh/vmlinux.lds.S
+++ b/arch/sh/vmlinux.lds.S
@@ -71,6 +71,7 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
__machvec_start = .;
.machvec.init : { *(.machvec.init) }
__machvec_end = .;
diff --git a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S
index 40fbec8537e2..0862360d865d 100644
--- a/arch/sparc/vmlinux.lds.S
+++ b/arch/sparc/vmlinux.lds.S
@@ -62,6 +62,7 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
diff --git a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S
index 0c8919aa9f87..ad95e88a3cbc 100644
--- a/arch/sparc64/vmlinux.lds.S
+++ b/arch/sparc64/vmlinux.lds.S
@@ -68,6 +68,7 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(8192);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 0bc2d8c94181..10f78014d6e6 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -52,6 +52,18 @@ config EARLY_PRINTK
klogd/syslogd or the X server. You should normally N here, unless
you want to debug such a crash.
+config HPET_TIMER
+ bool
+ default y
+ help
+ Use the IA-PC HPET (High Precision Event Timer) to manage
+ time in preference to the PIT and RTC, if a HPET is
+ present. The HPET provides a stable time base on SMP
+ systems, unlike the RTC, but it is more expensive to access,
+ as it is off-chip. You can find the HPET spec at
+ <http://www.intel.com/labs/platcomp/hpet/hpetspec.htm>.
+
+ If unsure, say Y.
config GENERIC_ISA_DMA
bool
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index a3cb3f13e9a7..4032f0720c2a 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -47,6 +47,7 @@
ENTRY(ia32_cstar_target)
swapgs
movl %esp,%r8d
+ movq %r8,%gs:pda_oldrsp
movq %gs:pda_kernelstack,%rsp
sti
SAVE_ARGS 8,1
diff --git a/arch/x86_64/kernel/acpi/boot.c b/arch/x86_64/kernel/acpi/boot.c
index e88862d9127b..d222d13acd7e 100644
--- a/arch/x86_64/kernel/acpi/boot.c
+++ b/arch/x86_64/kernel/acpi/boot.c
@@ -244,9 +244,11 @@ acpi_parse_hpet (
return -1;
}
- hpet.address = hpet_tbl->addr.addrl | ((long) hpet_tbl->addr.addrh << 32);
+ vxtime.hpet_address = hpet_tbl->addr.addrl |
+ ((long) hpet_tbl->addr.addrh << 32);
- printk(KERN_INFO "acpi: HPET id: %#x base: %#lx\n", hpet_tbl->id, hpet.address);
+ printk(KERN_INFO "acpi: HPET id: %#x base: %#lx\n",
+ hpet_tbl->id, vxtime.hpet_address);
return 0;
}
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 98440f87fc84..1addbb749ec2 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -690,7 +690,13 @@ static void setup_APIC_timer(unsigned int clocks)
}
/* wait for irq slice */
- {
+ if (vxtime.hpet_address) {
+ int trigger = hpet_readl(HPET_T0_CMP);
+ while (hpet_readl(HPET_COUNTER) >= trigger)
+ /* do nothing */ ;
+ while (hpet_readl(HPET_COUNTER) < trigger)
+ /* do nothing */ ;
+ } else {
int c1, c2;
outb_p(0x00, 0x43);
c2 = inb_p(0x40);
diff --git a/arch/x86_64/kernel/bluesmoke.c b/arch/x86_64/kernel/bluesmoke.c
index 00f2abe0ba46..392b8bab96ee 100644
--- a/arch/x86_64/kernel/bluesmoke.c
+++ b/arch/x86_64/kernel/bluesmoke.c
@@ -363,22 +363,12 @@ static void __init k8_mcheck_init(struct cpuinfo_x86 *c)
machine_check_vector = k8_machine_check;
for (i = 0; i < banks; i++) {
u64 val = ((1UL<<i) & disabled_banks) ? 0 : ~0UL;
+ if (val && i == 4)
+ val = k8_nb_flags;
wrmsrl(MSR_IA32_MC0_CTL+4*i, val);
wrmsrl(MSR_IA32_MC0_STATUS+4*i,0);
}
- nb = find_k8_nb();
- if (nb != NULL) {
- u32 reg, reg2;
- pci_read_config_dword(nb, 0x40, &reg);
- pci_write_config_dword(nb, 0x40, k8_nb_flags);
- pci_read_config_dword(nb, 0x44, &reg2);
- pci_write_config_dword(nb, 0x44, reg2);
- printk(KERN_INFO "Machine Check for K8 Northbridge %d enabled (%x,%x)\n",
- nb->devfn, reg, reg2);
- ignored_banks |= (1UL<<4);
- }
-
set_in_cr4(X86_CR4_MCE);
if (mcheck_interval && (smp_processor_id() == 0)) {
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index 8e69eb12d341..12047fff5230 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -173,12 +173,10 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
if (iommu_page == -1)
goto error;
- /* Fill in the GATT, allocating pages as needed. */
+ /* Fill in the GATT */
for (i = 0; i < size; i++) {
unsigned long phys_mem;
void *mem = memory + i*PAGE_SIZE;
- if (i > 0)
- atomic_inc(&virt_to_page(mem)->count);
phys_mem = virt_to_phys(mem);
BUG_ON(phys_mem & ~PHYSICAL_PAGE_MASK);
iommu_gatt_base[iommu_page + i] = GPTE_ENCODE(phys_mem);
@@ -206,16 +204,14 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size,
size = round_up(size, PAGE_SIZE);
if (bus >= iommu_bus_base && bus <= iommu_bus_base + iommu_size) {
unsigned pages = size >> PAGE_SHIFT;
+ int i;
iommu_page = (bus - iommu_bus_base) >> PAGE_SHIFT;
vaddr = __va(GPTE_DECODE(iommu_gatt_base[iommu_page]));
-#ifdef CONFIG_IOMMU_DEBUG
- int i;
for (i = 0; i < pages; i++) {
u64 pte = iommu_gatt_base[iommu_page + i];
BUG_ON((pte & GPTE_VALID) == 0);
iommu_gatt_base[iommu_page + i] = 0;
}
-#endif
free_iommu(iommu_page, pages);
}
free_pages((unsigned long)vaddr, get_order(size));
@@ -319,11 +315,6 @@ dma_addr_t pci_map_single(struct pci_dev *dev, void *addr, size_t size, int dir)
*/
iommu_gatt_base[iommu_page + i] = GPTE_ENCODE(phys_mem);
-#ifdef CONFIG_IOMMU_DEBUG
- /* paranoia check */
- BUG_ON(GPTE_DECODE(iommu_gatt_base[iommu_page+i]) != phys_mem);
-#endif
-
#ifdef CONFIG_IOMMU_LEAK
/* XXX need eventually caller of pci_map_sg */
if (iommu_leak_tab)
@@ -350,7 +341,6 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
return;
iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;
npages = round_up(size + (dma_addr & ~PAGE_MASK), PAGE_SIZE) >> PAGE_SHIFT;
-#ifdef CONFIG_IOMMU_DEBUG
int i;
for (i = 0; i < npages; i++) {
iommu_gatt_base[iommu_page + i] = 0;
@@ -359,7 +349,6 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
iommu_leak_tab[iommu_page + i] = 0;
#endif
}
-#endif
free_iommu(iommu_page, npages);
}
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index e2c5421dcb1f..5a5b2fe81e6c 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -150,7 +150,7 @@ __setup("idle=", idle_setup);
/* Prints also some state that isn't saved in the pt_regs */
-void show_regs(struct pt_regs * regs)
+void __show_regs(struct pt_regs * regs)
{
unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs;
unsigned int fsindex,gsindex;
@@ -192,7 +192,11 @@ void show_regs(struct pt_regs * regs)
fs,fsindex,gs,gsindex,shadowgs);
printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0);
printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4);
+}
+void show_regs(struct pt_regs *regs)
+{
+ __show_regs(regs);
show_trace(&regs->rsp);
}
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index d554126c5e64..00ee45c7a21b 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -67,6 +67,8 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
/* Set when the idlers are all forked */
int smp_threads_ready;
+extern void time_init_smp(void);
+
/*
* Trampoline 80x86 program as an array.
*/
@@ -760,7 +762,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
if (APIC_init_uniprocessor())
printk(KERN_NOTICE "Local APIC not detected."
" Using dummy APIC emulation.\n");
- return;
+ goto smp_done;
}
/*
@@ -784,7 +786,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
cpu_online_map = phys_cpu_present_map = 1;
phys_cpu_present_map = 1;
disable_apic = 1;
- return;
+ goto smp_done;
}
verify_local_APIC();
@@ -799,7 +801,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
cpu_online_map = phys_cpu_present_map = 1;
phys_cpu_present_map = 1;
disable_apic = 1;
- return;
+ goto smp_done;
}
connect_bsp_APIC();
@@ -883,6 +885,9 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
*/
if (cpu_has_tsc && cpucount)
synchronize_tsc_bp();
+
+ smp_done:
+ time_init_smp();
}
/* These are wrappers to interface to the new boot process. Someone
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 18c60397a8ea..aaa976327a82 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/bcd.h>
+#include <asm/pgtable.h>
#include <asm/vsyscall.h>
#include <asm/timex.h>
#ifdef CONFIG_X86_LOCAL_APIC
@@ -35,41 +36,61 @@ u64 jiffies_64 = INITIAL_JIFFIES;
extern int using_apic_timer;
spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
extern int using_apic_timer;
extern void smp_local_timer_interrupt(struct pt_regs * regs);
+#undef HPET_HACK_ENABLE_DANGEROUS
+
unsigned int cpu_khz; /* TSC clocks / usec, not used here */
unsigned long hpet_period; /* fsecs / HPET clock */
unsigned long hpet_tick; /* HPET clocks / interrupt */
-int hpet_report_lost_ticks; /* command line option */
+unsigned long vxtime_hz = 1193182;
+int report_lost_ticks; /* command line option */
-struct hpet_data __hpet __section_hpet; /* address, quotient, trigger, hz */
+struct vxtime_data __vxtime __section_vxtime; /* for vsyscalls */
volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES;
struct timespec __xtime __section_xtime;
struct timezone __sys_tz __section_sys_tz;
+static inline void rdtscll_sync(unsigned long *tsc)
+{
+#ifdef CONFIG_SMP
+ sync_core();
+#endif
+ rdtscll(*tsc);
+}
+
/*
* do_gettimeoffset() returns microseconds since last timer interrupt was
* triggered by hardware. A memory read of HPET is slower than a register read
* of TSC, but much more reliable. It's also synchronized to the timer
* interrupt. Note that do_gettimeoffset() may return more than hpet_tick, if a
- * timer interrupt has happened already, but hpet.trigger wasn't updated yet.
+ * timer interrupt has happened already, but vxtime.trigger wasn't updated yet.
* This is not a problem, because jiffies hasn't updated either. They are bound
* together by xtime_lock.
*/
-inline unsigned int do_gettimeoffset(void)
+static inline unsigned int do_gettimeoffset_tsc(void)
{
unsigned long t;
- sync_core();
- rdtscll(t);
- return (t - hpet.last_tsc) * (1000000L / HZ) / hpet.ticks + hpet.offset;
+ unsigned long x;
+ rdtscll_sync(&t);
+ x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> 32;
+ return x;
+}
+
+static inline unsigned int do_gettimeoffset_hpet(void)
+{
+ return ((hpet_readl(HPET_COUNTER) - vxtime.last) * vxtime.quot) >> 32;
}
+unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
+
/*
* This version of gettimeofday() has microsecond resolution and better than
* microsecond precision, as we're using at least a 10 MHz (usually 14.31818
@@ -87,7 +108,8 @@ void do_gettimeofday(struct timeval *tv)
sec = xtime.tv_sec;
usec = xtime.tv_nsec / 1000;
- t = (jiffies - wall_jiffies) * (1000000L / HZ) + do_gettimeoffset();
+ t = (jiffies - wall_jiffies) * (1000000L / HZ) +
+ do_gettimeoffset();
usec += t;
} while (read_seqretry(&xtime_lock, seq));
@@ -107,7 +129,7 @@ void do_settimeofday(struct timeval *tv)
write_seqlock_irq(&xtime_lock);
tv->tv_usec -= do_gettimeoffset() +
- (jiffies - wall_jiffies) * tick_usec;
+ (jiffies - wall_jiffies) * (USEC_PER_SEC/HZ);
while (tv->tv_usec < 0) {
tv->tv_usec += 1000000;
@@ -178,8 +200,8 @@ static void set_rtc_mmss(unsigned long nowtime)
CMOS_WRITE(real_seconds, RTC_SECONDS);
CMOS_WRITE(real_minutes, RTC_MINUTES);
} else
- printk(KERN_WARNING "time.c: can't update CMOS clock from %d to %d\n",
- cmos_minutes, real_minutes);
+ printk(KERN_WARNING "time.c: can't update CMOS clock "
+ "from %d to %d\n", cmos_minutes, real_minutes);
/*
* The following flags have to be released exactly in this order, otherwise the
@@ -198,6 +220,8 @@ static void set_rtc_mmss(unsigned long nowtime)
static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
static unsigned long rtc_update = 0;
+ unsigned long tsc, lost = 0;
+ int delay, offset = 0;
/*
* Here we are in the timer irq handler. We have irqs locally disabled (so we
@@ -208,17 +232,53 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
write_seqlock(&xtime_lock);
- {
- unsigned long t;
+ if (vxtime.hpet_address) {
+ offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
+ delay = hpet_readl(HPET_COUNTER) - offset;
+ } else {
+ spin_lock(&i8253_lock);
+ outb_p(0x00, 0x43);
+ delay = inb_p(0x40);
+ delay |= inb(0x40) << 8;
+ spin_unlock(&i8253_lock);
+ delay = LATCH - 1 - delay;
+ }
- sync_core();
- rdtscll(t);
- hpet.offset = (t - hpet.last_tsc) * (1000000L / HZ) / hpet.ticks + hpet.offset - 1000000L / HZ;
- if (hpet.offset >= 1000000L / HZ)
- hpet.offset = 0;
- hpet.ticks = min_t(long, max_t(long, (t - hpet.last_tsc) * (1000000L / HZ) / (1000000L / HZ - hpet.offset),
- cpu_khz * 1000/HZ * 15 / 16), cpu_khz * 1000/HZ * 16 / 15);
- hpet.last_tsc = t;
+ rdtscll_sync(&tsc);
+
+ if (vxtime.mode == VXTIME_HPET) {
+ if (offset - vxtime.last > hpet_tick) {
+ lost = (offset - vxtime.last) / hpet_tick - 1;
+ }
+
+ vxtime.last = offset;
+ } else {
+ offset = (((tsc - vxtime.last_tsc) *
+ vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ);
+
+ if (offset < 0)
+ offset = 0;
+
+ if (offset > (USEC_PER_SEC / HZ)) {
+ lost = offset / (USEC_PER_SEC / HZ);
+ offset %= (USEC_PER_SEC / HZ);
+ }
+
+ vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot;
+
+ if ((((tsc - vxtime.last_tsc) *
+ vxtime.tsc_quot) >> 32) < offset)
+ vxtime.last_tsc = tsc -
+ (((long) offset << 32) / vxtime.tsc_quot) - 1;
+ }
+
+ if (lost) {
+ if (report_lost_ticks)
+ printk(KERN_WARNING "time.c: Lost %ld timer "
+ "tick(s)! (rip %016lx)\n",
+ (offset - vxtime.last) / hpet_tick - 1,
+ regs->rip);
+ jiffies += lost;
}
/*
@@ -244,7 +304,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* If we have an externally synchronized Linux clock, then update CMOS clock
* accordingly every ~11 minutes. set_rtc_mmss() will be called in the jiffy
* closest to exactly 500 ms before the next second. If the update fails, we
- * don'tcare, as it'll be updated on the next turn, and the problem (time way
+ * don't care, as it'll be updated on the next turn, and the problem (time way
* off) isn't likely to go away much sooner anyway.
*/
@@ -263,6 +323,7 @@ unsigned long get_cmos_time(void)
{
unsigned int timeout, year, mon, day, hour, min, sec;
unsigned char last, this;
+ unsigned long flags;
/*
* The Linux interpretation of the CMOS clock register contents: When the
@@ -272,7 +333,7 @@ unsigned long get_cmos_time(void)
* standard 8.3 MHz ISA bus.
*/
- spin_lock(&rtc_lock);
+ spin_lock_irqsave(&rtc_lock, flags);
timeout = 1000000;
last = this = 0;
@@ -295,7 +356,7 @@ unsigned long get_cmos_time(void)
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
- spin_unlock(&rtc_lock);
+ spin_unlock_irqrestore(&rtc_lock, flags);
/*
* We know that x86-64 always uses BCD format, no need to check the config
@@ -326,6 +387,32 @@ unsigned long get_cmos_time(void)
#define TICK_COUNT 100000000
+static unsigned int __init hpet_calibrate_tsc(void)
+{
+ int tsc_start, hpet_start;
+ int tsc_now, hpet_now;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ local_irq_disable();
+
+ hpet_start = hpet_readl(HPET_COUNTER);
+ rdtscl(tsc_start);
+
+ do {
+ local_irq_disable();
+ hpet_now = hpet_readl(HPET_COUNTER);
+ sync_core();
+ rdtscl(tsc_now);
+ local_irq_restore(flags);
+ } while ((tsc_now - tsc_start) < TICK_COUNT &&
+ (hpet_now - hpet_start) < TICK_COUNT);
+
+ return (tsc_now - tsc_start) * 1000000000L
+ / ((hpet_now - hpet_start) * hpet_period / 1000);
+}
+
+
/*
* pit_calibrate_tsc() uses the speaker output (channel 2) of
* the PIT. This is better than using the timer interrupt output,
@@ -339,10 +426,9 @@ static unsigned int __init pit_calibrate_tsc(void)
unsigned long start, end;
unsigned long flags;
- outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+ spin_lock_irqsave(&i8253_lock, flags);
- local_irq_save(flags);
- local_irq_disable();
+ outb((inb(0x61) & ~0x02) | 0x01, 0x61);
outb(0xb0, 0x43);
outb((1193182 / (1000 / 50)) & 0xff, 0x42);
@@ -353,42 +439,146 @@ static unsigned int __init pit_calibrate_tsc(void)
sync_core();
rdtscll(end);
-
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&i8253_lock, flags);
return (end - start) / 50;
}
+static int hpet_init(void)
+{
+ unsigned int cfg, id;
+
+ if (!vxtime.hpet_address)
+ return -1;
+ set_fixmap_nocache(FIX_HPET_BASE, vxtime.hpet_address);
+
+/*
+ * Read the period, compute tick and quotient.
+ */
+
+ id = hpet_readl(HPET_ID);
+
+ if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER) ||
+ !(id & HPET_ID_LEGSUP))
+ return -1;
+
+ hpet_period = hpet_readl(HPET_PERIOD);
+ if (hpet_period < 100000 || hpet_period > 100000000)
+ return -1;
+
+ hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) /
+ hpet_period;
+
+/*
+ * Stop the timers and reset the main counter.
+ */
+
+ cfg = hpet_readl(HPET_CFG);
+ cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
+ hpet_writel(cfg, HPET_CFG);
+ hpet_writel(0, HPET_COUNTER);
+ hpet_writel(0, HPET_COUNTER + 4);
+
+/*
+ * Set up timer 0, as periodic with first interrupt to happen at hpet_tick,
+ * and period also hpet_tick.
+ */
+
+ hpet_writel(HPET_T0_ENABLE | HPET_T0_PERIODIC | HPET_T0_SETVAL |
+ HPET_T0_32BIT, HPET_T0_CFG);
+ hpet_writel(hpet_tick, HPET_T0_CMP);
+ hpet_writel(hpet_tick, HPET_T0_CMP);
+
+/*
+ * Go!
+ */
+
+ cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY;
+ hpet_writel(cfg, HPET_CFG);
+
+ return 0;
+}
+
void __init pit_init(void)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&i8253_lock, flags);
outb_p(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff, 0x40); /* LSB */
outb_p(LATCH >> 8, 0x40); /* MSB */
+ spin_unlock_irqrestore(&i8253_lock, flags);
}
int __init time_setup(char *str)
{
- hpet_report_lost_ticks = 1;
+ report_lost_ticks = 1;
return 1;
}
-static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
+static struct irqaction irq0 = {
+ timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL
+};
extern void __init config_acpi_tables(void);
void __init time_init(void)
{
+ char *timename;
+
+#ifdef HPET_HACK_ENABLE_DANGEROUS
+ if (!vxtime.hpet_address) {
+ printk(KERN_WARNING "time.c: WARNING: Enabling HPET base "
+ "manually!\n");
+ outl(0x800038a0, 0xcf8);
+ outl(0xff000001, 0xcfc);
+ outl(0x800038a0, 0xcf8);
+ hpet_address = inl(0xcfc) & 0xfffffffe;
+ printk(KERN_WARNING "time.c: WARNING: Enabled HPET "
+ "at %#lx.\n", hpet_address);
+ }
+#endif
+
xtime.tv_sec = get_cmos_time();
xtime.tv_nsec = 0;
+ if (!hpet_init()) {
+ vxtime_hz = (1000000000000000L + hpet_period / 2) /
+ hpet_period;
+ cpu_khz = hpet_calibrate_tsc();
+ timename = "HPET";
+ } else {
pit_init();
- printk(KERN_INFO "time.c: Using 1.1931816 MHz PIT timer.\n");
cpu_khz = pit_calibrate_tsc();
+ timename = "PIT";
+ }
+
+ printk(KERN_INFO "time.c: Using %ld.%06ld MHz %s timer.\n",
+ vxtime_hz / 1000000, vxtime_hz % 1000000, timename);
printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
cpu_khz / 1000, cpu_khz % 1000);
- hpet.ticks = cpu_khz * (1000 / HZ);
- rdtscll(hpet.last_tsc);
+ vxtime.mode = VXTIME_TSC;
+ vxtime.quot = (1000000L << 32) / vxtime_hz;
+ vxtime.tsc_quot = (1000L << 32) / cpu_khz;
+ vxtime.hz = vxtime_hz;
+ rdtscll_sync(&vxtime.last_tsc);
setup_irq(0, &irq0);
}
+void __init time_init_smp(void)
+{
+ char *timetype;
+
+ if (vxtime.hpet_address) {
+ timetype = "HPET";
+ vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
+ vxtime.mode = VXTIME_HPET;
+ do_gettimeoffset = do_gettimeoffset_hpet;
+ } else {
+ timetype = "PIT/TSC";
+ vxtime.mode = VXTIME_TSC;
+ }
+ printk(KERN_INFO "time.c: Using %s based timekeeping.\n", timetype);
+}
+
__setup("report_lost_ticks", time_setup);
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index e1620dc69800..24d5862bdcd7 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -263,7 +263,7 @@ void show_registers(struct pt_regs *regs)
rsp = regs->rsp;
printk("CPU %d ", cpu);
- show_regs(regs);
+ __show_regs(regs);
printk("Process %s (pid: %d, stackpage=%08lx)\n",
cur->comm, cur->pid, 4096+(unsigned long)cur);
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index 4162dd9bf8dc..cb52162ae495 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -78,13 +78,21 @@ static force_inline void do_vgettimeofday(struct timeval * tv)
do {
sequence = read_seqbegin(&__xtime_lock);
- sync_core();
- rdtscll(t);
sec = __xtime.tv_sec;
usec = (__xtime.tv_nsec / 1000) +
- (__jiffies - __wall_jiffies) * (1000000 / HZ) +
- (t - __hpet.last_tsc) * (1000000 / HZ) / __hpet.ticks + __hpet.offset;
-
+ (__jiffies - __wall_jiffies) * (1000000 / HZ);
+
+ if (__vxtime.mode == VXTIME_TSC) {
+ sync_core();
+ rdtscll(t);
+ usec += ((t - __vxtime.last_tsc) *
+ __vxtime.tsc_quot) >> 32;
+ } else {
+#if 0
+ usec += ((readl(fix_to_virt(VSYSCALL_HPET) + 0xf0) -
+ __vxtime.last) * __vxtime.quot) >> 32;
+#endif
+ }
} while (read_seqretry(&__xtime_lock, sequence));
tv->tv_sec = sec + usec / 1000000;
diff --git a/arch/x86_64/lib/clear_page.S b/arch/x86_64/lib/clear_page.S
index b34c34f85fc6..5867f704c0ad 100644
--- a/arch/x86_64/lib/clear_page.S
+++ b/arch/x86_64/lib/clear_page.S
@@ -1,19 +1,18 @@
-/*
- * Copyright 2002 Andi Kleen, SuSE Labs.
- */
- #include <linux/linkage.h>
/*
* Zero a page.
* rdi page
*/
-ENTRY(clear_page)
+ .globl clear_page
+ .p2align 4
+clear_page:
xorl %eax,%eax
- movl $4096/128,%ecx
- movl $128,%edx
-loop:
+ movl $4096/64,%ecx
+ .p2align 4
+.Lloop:
+ decl %ecx
#define PUT(x) movq %rax,x*8(%rdi)
- PUT(0)
+ movq %rax,(%rdi)
PUT(1)
PUT(2)
PUT(3)
@@ -21,17 +20,8 @@ loop:
PUT(5)
PUT(6)
PUT(7)
- PUT(8)
- PUT(9)
- PUT(10)
- PUT(11)
- PUT(12)
- PUT(13)
- PUT(14)
- PUT(15)
- addq %rdx,%rdi
- decl %ecx
- jnz loop
- sfence
+ leaq 64(%rdi),%rdi
+ jnz .Lloop
+ nop
ret
diff --git a/arch/x86_64/lib/copy_page.S b/arch/x86_64/lib/copy_page.S
index 71d3c57441fa..72eb9314bd37 100644
--- a/arch/x86_64/lib/copy_page.S
+++ b/arch/x86_64/lib/copy_page.S
@@ -1,74 +1,91 @@
-/*
- * Copyright 2002 Andi Kleen, SuSE Labs.
- */
+/* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */
- #include <linux/linkage.h>
- #include <linux/config.h>
- #ifdef CONFIG_PREEMPT
- #warning "check your fpu context saving!"
- #endif
+/* Don't use streaming store because it's better when the target
+ ends up in cache. */
+
+/* Could vary the prefetch distance based on SMP/UP */
-/*
- * Copy a page.
- *
- * rdi destination page
- * rsi source page
- *
- * src/dst must be aligned to 16 bytes.
- *
- * Warning: in case of super lazy FP save this needs to be preempt_stop
- */
-
.globl copy_page
- .p2align
+ .p2align 4
copy_page:
- prefetchnta (%rsi)
- prefetchnta 64(%rsi)
-
- movq %rsp,%rax
- subq $16*4,%rsp
- andq $~15,%rsp
- movdqa %xmm0,(%rsp)
- movdqa %xmm1,16(%rsp)
- movdqa %xmm2,32(%rsp)
- movdqa %xmm3,48(%rsp)
-
- movl $(4096/128)-2,%ecx
- movl $128,%edx
-loop:
- prefetchnta (%rsi)
- prefetchnta 64(%rsi)
-loop_no_prefetch:
- movdqa (%rsi),%xmm0
- movdqa 16(%rsi),%xmm1
- movdqa 32(%rsi),%xmm2
- movdqa 48(%rsi),%xmm3
- movntdq %xmm0,(%rdi)
- movntdq %xmm1,16(%rdi)
- movntdq %xmm2,32(%rdi)
- movntdq %xmm3,48(%rdi)
-
- movdqa 64(%rsi),%xmm0
- movdqa 80(%rsi),%xmm1
- movdqa 96(%rsi),%xmm2
- movdqa 112(%rsi),%xmm3
- movntdq %xmm0,64(%rdi)
- movntdq %xmm1,80(%rdi)
- movntdq %xmm2,96(%rdi)
- movntdq %xmm3,112(%rdi)
+ prefetch (%rsi)
+ prefetch 1*64(%rsi)
+ prefetch 2*64(%rsi)
+ prefetch 3*64(%rsi)
+ prefetch 4*64(%rsi)
+ prefetchw (%rdi)
+ prefetchw 1*64(%rdi)
+ prefetchw 2*64(%rdi)
+ prefetchw 3*64(%rdi)
+ prefetchw 4*64(%rdi)
+
+ subq $3*8,%rsp
+ movq %rbx,(%rsp)
+ movq %r12,1*8(%rsp)
+ movq %r13,2*8(%rsp)
+
+ movl $(4096/64)-5,%ecx
+ .p2align 4
+.Loop64:
+ dec %rcx
+
+ movq (%rsi), %rax
+ movq 8 (%rsi), %rbx
+ movq 16 (%rsi), %rdx
+ movq 24 (%rsi), %r8
+ movq 32 (%rsi), %r9
+ movq 40 (%rsi), %r10
+ movq 48 (%rsi), %r11
+ movq 56 (%rsi), %r12
+
+ prefetch 5*64(%rsi)
+
+ movq %rax, (%rdi)
+ movq %rbx, 8 (%rdi)
+ movq %rdx, 16 (%rdi)
+ movq %r8, 24 (%rdi)
+ movq %r9, 32 (%rdi)
+ movq %r10, 40 (%rdi)
+ movq %r11, 48 (%rdi)
+ movq %r12, 56 (%rdi)
- addq %rdx,%rdi
- addq %rdx,%rsi
+ prefetchw 5*64(%rdi)
+
+ leaq 64 (%rsi), %rsi
+ leaq 64 (%rdi), %rdi
+
+ jnz .Loop64
+
+ movl $5,%ecx
+ .p2align 4
+.Loop2:
decl %ecx
- jns loop
- cmpl $-1,%ecx
- je loop_no_prefetch
-
- sfence
- movdqa (%rsp),%xmm0
- movdqa 16(%rsp),%xmm1
- movdqa 32(%rsp),%xmm2
- movdqa 48(%rsp),%xmm3
- movq %rax,%rsp
+ movq (%rsi), %rax
+ movq 8 (%rsi), %rbx
+ movq 16 (%rsi), %rdx
+ movq 24 (%rsi), %r8
+ movq 32 (%rsi), %r9
+ movq 40 (%rsi), %r10
+ movq 48 (%rsi), %r11
+ movq 56 (%rsi), %r12
+
+ movq %rax, (%rdi)
+ movq %rbx, 8 (%rdi)
+ movq %rdx, 16 (%rdi)
+ movq %r8, 24 (%rdi)
+ movq %r9, 32 (%rdi)
+ movq %r10, 40 (%rdi)
+ movq %r11, 48 (%rdi)
+ movq %r12, 56 (%rdi)
+
+ leaq 64(%rdi),%rdi
+ leaq 64(%rsi),%rsi
+
+ jnz .Loop2
+
+ movq (%rsp),%rbx
+ movq 1*8(%rsp),%r12
+ movq 2*8(%rsp),%r13
+ addq $3*8,%rsp
ret
diff --git a/arch/x86_64/lib/csum-copy.S b/arch/x86_64/lib/csum-copy.S
index ccd89d25fe85..7aa2cec7ab8f 100644
--- a/arch/x86_64/lib/csum-copy.S
+++ b/arch/x86_64/lib/csum-copy.S
@@ -1,5 +1,5 @@
/*
- * Copyright 2002 Andi Kleen
+ * Copyright 2002,2003 Andi Kleen, SuSE Labs.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
@@ -8,7 +8,6 @@
#include <linux/linkage.h>
#include <asm/errno.h>
-// #define FIX_ALIGNMENT 1
/*
* Checksum copy with exception handling.
* On exceptions src_err_ptr or dst_err_ptr is set to -EFAULT and the
@@ -26,17 +25,14 @@
* eax 64bit sum. undefined in case of exception.
*
* Wrappers need to take care of valid exception sum and zeroing.
+ * They also should align source or destination to 8 bytes.
*/
-/* for now - should vary this based on direction */
- #define prefetch prefetcht2
- #define movnti movq
-
.macro source
10:
.section __ex_table,"a"
.align 8
- .quad 10b,bad_source
+ .quad 10b,.Lbad_source
.previous
.endm
@@ -44,57 +40,74 @@
20:
.section __ex_table,"a"
.align 8
- .quad 20b,bad_dest
+ .quad 20b,.Lbad_dest
.previous
.endm
+ .macro ignore L=.Lignore
+30:
+ .section __ex_table,"a"
+ .align 8
+ .quad 30b,\L
+ .previous
+ .endm
+
+
.globl csum_partial_copy_generic
- .p2align
+ .p2align 4
csum_partial_copy_generic:
- prefetchnta (%rdi)
+ cmpl $3*64,%edx
+ jle .Lignore
+
+ ignore
+ prefetch (%rdi)
+ ignore
+ prefetch 1*64(%rdi)
+ ignore
+ prefetch 2*64(%rdi)
+ ignore
+ prefetch 3*64(%rdi)
+ ignore
+ prefetch 4*64(%rdi)
+ ignore
+ prefetchw (%rsi)
+ ignore
+ prefetchw 1*64(%rsi)
+ ignore
+ prefetchw 2*64(%rsi)
+ ignore
+ prefetchw 3*64(%rsi)
+ ignore
+ prefetchw 4*64(%rsi)
+
+.Lignore:
+ subq $7*8,%rsp
+ movq %rbx,2*8(%rsp)
+ movq %r12,3*8(%rsp)
+ movq %r14,4*8(%rsp)
+ movq %r13,5*8(%rsp)
+ movq %rbp,6*8(%rsp)
+
+ movq %r8,(%rsp)
+ movq %r9,1*8(%rsp)
- pushq %rbx
- pushq %r12
- pushq %r14
- pushq %r15
- movq %r8,%r14
- movq %r9,%r15
movl %ecx,%eax
movl %edx,%ecx
-#ifdef FIX_ALIGNMENT
- /* align source to 8 bytes */
- movl %edi,%r8d
- andl $7,%r8d
- jnz bad_alignment
-after_bad_alignment:
-#endif
-
- movl $64,%r10d
xorl %r9d,%r9d
movq %rcx,%r12
shrq $6,%r12
- /* loopcounter is maintained as one less to test efficiently for the
- previous to last iteration. This is needed to stop the prefetching. */
- decq %r12
- js handle_tail /* < 64 */
- jz loop_no_prefetch /* = 64 + X */
+ jz .Lhandle_tail /* < 64 */
+
+ clc
/* main loop. clear in 64 byte blocks */
- /* tries hard not to prefetch over the boundary */
- /* r10: 64, r9: zero, r8: temp2, rbx: temp1, rax: sum, rcx: saved length */
+ /* r9: zero, r8: temp2, rbx: temp1, rax: sum, rcx: saved length */
/* r11: temp3, rdx: temp4, r12 loopcnt */
- .p2align
-loop:
- /* Could prefetch more than one loop, but then it would be even
- trickier to avoid prefetching over the boundary. The hardware prefetch
- should take care of this anyways. The reason for this prefetch is
- just the non temporal hint to avoid cache pollution. Hopefully this
- will be handled properly by the hardware. */
- prefetchnta 64(%rdi)
-
-loop_no_prefetch:
+ /* r10: temp5, rbp: temp6, r14 temp7, r13 temp8 */
+ .p2align 4
+.Lloop:
source
movq (%rdi),%rbx
source
@@ -104,175 +117,136 @@ loop_no_prefetch:
source
movq 24(%rdi),%rdx
- dest
- movnti %rbx,(%rsi)
- dest
- movnti %r8,8(%rsi)
- dest
- movnti %r11,16(%rsi)
- dest
- movnti %rdx,24(%rsi)
+ source
+ movq 32(%rdi),%r10
+ source
+ movq 40(%rdi),%rbp
+ source
+ movq 48(%rdi),%r14
+ source
+ movq 56(%rdi),%r13
- addq %rbx,%rax
+ ignore 2f
+ prefetch 5*64(%rdi)
+2:
+ adcq %rbx,%rax
adcq %r8,%rax
adcq %r11,%rax
adcq %rdx,%rax
+ adcq %r10,%rax
+ adcq %rbp,%rax
+ adcq %r14,%rax
+ adcq %r13,%rax
- source
- movq 32(%rdi),%rbx
- source
- movq 40(%rdi),%r8
- source
- movq 48(%rdi),%r11
- source
- movq 56(%rdi),%rdx
+ decl %r12d
dest
- movnti %rbx,32(%rsi)
+ movq %rbx,(%rsi)
dest
- movnti %r8,40(%rsi)
+ movq %r8,8(%rsi)
dest
- movnti %r11,48(%rsi)
+ movq %r11,16(%rsi)
dest
- movnti %rdx,56(%rsi)
+ movq %rdx,24(%rsi)
- adcq %rbx,%rax
- adcq %r8,%rax
- adcq %r11,%rax
- adcq %rdx,%rax
+ dest
+ movq %r10,32(%rsi)
+ dest
+ movq %rbp,40(%rsi)
+ dest
+ movq %r14,48(%rsi)
+ dest
+ movq %r13,56(%rsi)
- adcq %r9,%rax /* add in carry */
+ ignore 3f
+ prefetchw 5*64(%rsi)
+3:
- addq %r10,%rdi
- addq %r10,%rsi
+ leaq 64(%rdi),%rdi
+ leaq 64(%rsi),%rsi
- decq %r12
- jz loop_no_prefetch /* previous to last iteration? */
- jns loop
+ jnz .Lloop
+
+ adcq %r9,%rax
/* do last upto 56 bytes */
-handle_tail:
+.Lhandle_tail:
/* ecx: count */
movl %ecx,%r10d
andl $63,%ecx
shrl $3,%ecx
- jz fold
+ jz .Lfold
clc
- movl $8,%edx
-loop_8:
+ .p2align 4
+.Lloop_8:
source
movq (%rdi),%rbx
adcq %rbx,%rax
- dest
- movnti %rbx,(%rsi)
- leaq (%rsi,%rdx),%rsi /* preserve carry */
- leaq (%rdi,%rdx),%rdi
decl %ecx
- jnz loop_8
+ dest
+ movq %rbx,(%rsi)
+ leaq 8(%rsi),%rsi /* preserve carry */
+ leaq 8(%rdi),%rdi
+ jnz .Lloop_8
adcq %r9,%rax /* add in carry */
-fold:
+.Lfold:
+ /* reduce checksum to 32bits */
movl %eax,%ebx
shrq $32,%rax
- addq %rbx,%rax
+ addl %ebx,%eax
+ adcl %r9d,%eax
/* do last upto 6 bytes */
-handle_7:
+.Lhandle_7:
movl %r10d,%ecx
andl $7,%ecx
shrl $1,%ecx
- jz handle_1
+ jz .Lhandle_1
movl $2,%edx
xorl %ebx,%ebx
clc
-loop_1:
+ .p2align 4
+.Lloop_1:
source
movw (%rdi),%bx
- adcq %rbx,%rax
+ adcl %ebx,%eax
dest
- movw %bx,(%rsi)
- addq %rdx,%rdi
- addq %rdx,%rsi
decl %ecx
- jnz loop_1
- adcw %r9w,%ax /* add in carry */
+ movw %bx,(%rsi)
+ leaq 2(%rdi),%rdi
+ leaq 2(%rsi),%rsi
+ jnz .Lloop_1
+ adcl %r9d,%eax /* add in carry */
/* handle last odd byte */
-handle_1:
+.Lhandle_1:
testl $1,%r10d
- jz ende
+ jz .Lende
xorl %ebx,%ebx
source
movb (%rdi),%bl
dest
movb %bl,(%rsi)
- addw %bx,%ax
- adcw %r9w,%ax /* carry */
+ addl %ebx,%eax
+ adcl %r9d,%eax /* carry */
-ende:
- sfence
- popq %r15
- popq %r14
- popq %r12
- popq %rbx
+.Lende:
+ movq 2*8(%rsp),%rbx
+ movq 3*8(%rsp),%r12
+ movq 4*8(%rsp),%r14
+ movq 5*8(%rsp),%r13
+ movq 6*8(%rsp),%rbp
+ addq $7*8,%rsp
ret
-#ifdef FIX_ALIGNMENT
- /* align source to 8 bytes. */
- /* r8d: unalignedness, ecx len */
-bad_alignment:
- testl $1,%edi
- jnz odd_source
-
- /* compute distance to next aligned position */
- movl $8,%r8d
- xchgl %r8d,%ecx
- subl %r8d,%ecx
-
- /* handle unaligned part */
- shrl $1,%ecx
- xorl %ebx,%ebx
- movl $2,%r10d
-align_loop:
- source
- movw (%rdi),%bx
- addq %rbx,%rax /* carry cannot happen */
- dest
- movw %bx,(%rsi)
- addq %r10,%rdi
- addq %r10,%rsi
- decl %ecx
- jnz align_loop
- jmp after_bad_alignment
-
- /* weird case. need to swap the sum at the end because the spec requires
- 16 bit words of the sum to be always paired.
- handle it recursively because it should be rather rare. */
-odd_source:
- /* copy odd byte */
- xorl %ebx,%ebx
- source
- movb (%rdi),%bl
- addl %ebx,%eax /* add to old checksum */
- adcl $0,%ecx
- dest
- movb %al,(%rsi)
-
- /* fix arguments */
- movl %eax,%ecx
- incq %rsi
- incq %rdi
- decq %rdx
- call csum_partial_copy_generic
- bswap %eax /* this should work, but check */
- jmp ende
-#endif
-
/* Exception handlers. Very simple, zeroing is done in the wrappers */
-bad_source:
- movl $-EFAULT,(%r14)
- jmp ende
+.Lbad_source:
+ movq (%rsp),%rax
+ movl $-EFAULT,(%rax)
+ jmp .Lende
-bad_dest:
- movl $-EFAULT,(%r15)
- jmp ende
+.Lbad_dest:
+ movq 8(%rsp),%rax
+ movl $-EFAULT,(%rax)
+ jmp .Lende
diff --git a/arch/x86_64/lib/csum-partial.c b/arch/x86_64/lib/csum-partial.c
index 180e7a5810cb..2eb49de9b027 100644
--- a/arch/x86_64/lib/csum-partial.c
+++ b/arch/x86_64/lib/csum-partial.c
@@ -7,35 +7,39 @@
#include <linux/compiler.h>
#include <linux/module.h>
+#include <asm/checksum.h>
-/* Better way for this sought */
-static inline unsigned short from64to16(unsigned long x)
+#define __force_inline inline __attribute__((always_inline))
+
+static inline unsigned short from32to16(unsigned a)
{
- /* add up 32-bit words for 33 bits */
- x = (x & 0xffffffff) + (x >> 32);
- /* add up 16-bit and 17-bit words for 17+c bits */
- x = (x & 0xffff) + (x >> 16);
- /* add up 16-bit and 2-bit for 16+c bit */
- x = (x & 0xffff) + (x >> 16);
- /* add up carry.. */
- x = (x & 0xffff) + (x >> 16);
- return x;
+ unsigned short b = a >> 16;
+ asm("addw %w2,%w0\n\t"
+ "adcw $0,%w0\n"
+ : "=r" (b)
+ : "0" (b), "r" (a));
+ return b;
}
/*
* Do a 64-bit checksum on an arbitrary memory area.
* Returns a 32bit checksum.
*
- * This isn't a great routine, but it's not _horrible_ either.
- * We rely on the compiler to unroll.
+ * This isn't as time critical as it used to be because many NICs
+ * do hardware checksumming these days.
+ *
+ * Things tried and found to not make it faster:
+ * Manual Prefetching
+ * Unrolling to an 128 bytes inner loop.
+ * Using interleaving with more registers to break the carry chains.
*/
-static inline unsigned do_csum(const unsigned char * buff, int len)
+static __force_inline unsigned do_csum(const unsigned char *buff, unsigned len)
{
- int odd, count;
+ unsigned odd, count;
unsigned long result = 0;
- if (len <= 0)
- goto out;
+ if (unlikely(len == 0))
+ return result;
odd = 1 & (unsigned long) buff;
if (unlikely(odd)) {
result = *buff << 8;
@@ -45,7 +49,7 @@ static inline unsigned do_csum(const unsigned char * buff, int len)
count = len >> 1; /* nr of 16-bit words.. */
if (count) {
if (2 & (unsigned long) buff) {
- result += *(unsigned short *) buff;
+ result += *(unsigned short *)buff;
count--;
len -= 2;
buff += 2;
@@ -59,18 +63,41 @@ static inline unsigned do_csum(const unsigned char * buff, int len)
buff += 4;
}
count >>= 1; /* nr of 64-bit words.. */
- if (count) {
+
+ /* main loop using 64byte blocks */
unsigned long zero = 0;
- do {
- asm(" addq %1,%0\n"
- " adcq %2,%0\n"
+ unsigned count64 = count >> 3;
+ while (count64) {
+ asm("addq 0*8(%[src]),%[res]\n\t"
+ "adcq 1*8(%[src]),%[res]\n\t"
+ "adcq 2*8(%[src]),%[res]\n\t"
+ "adcq 3*8(%[src]),%[res]\n\t"
+ "adcq 4*8(%[src]),%[res]\n\t"
+ "adcq 5*8(%[src]),%[res]\n\t"
+ "adcq 6*8(%[src]),%[res]\n\t"
+ "adcq 7*8(%[src]),%[res]\n\t"
+ "adcq %[zero],%[res]"
+ : [res] "=r" (result)
+ : [src] "r" (buff), [zero] "r" (zero),
+ "[res]" (result));
+ buff += 64;
+ count64--;
+ }
+
+ /* last upto 7 8byte blocks */
+ count %= 8;
+ while (count) {
+ asm("addq %1,%0\n\t"
+ "adcq %2,%0\n"
: "=r" (result)
- : "m" (*buff), "r" (zero), "0" (result));
- count--;
+ : "m" (*(unsigned long *)buff),
+ "r" (zero), "0" (result));
+ --count;
buff += 8;
- } while (count);
- result = (result & 0xffffffff) + (result >> 32);
}
+ result = add32_with_carry(result>>32,
+ result&0xffffffff);
+
if (len & 4) {
result += *(unsigned int *) buff;
buff += 4;
@@ -83,10 +110,11 @@ static inline unsigned do_csum(const unsigned char * buff, int len)
}
if (len & 1)
result += *buff;
- result = from64to16(result);
- if (unlikely(odd))
- return ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-out:
+ result = add32_with_carry(result>>32, result & 0xffffffff);
+ if (unlikely(odd)) {
+ result = from32to16(result);
+ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+ }
return result;
}
@@ -102,18 +130,11 @@ out:
*
* it's best to have buff aligned on a 64-bit boundary
*/
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+unsigned csum_partial(const unsigned char *buff, unsigned len, unsigned sum)
{
- unsigned result = do_csum(buff, len);
-
- /* add in old sum, and carry.. */
- asm("addl %1,%0\n\t"
- "adcl $0,%0" : "=r" (result) : "r" (sum), "0" (result));
- return result;
+ return add32_with_carry(do_csum(buff, len), sum);
}
-//EXPORT_SYMBOL(csum_partial);
-
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
@@ -123,4 +144,3 @@ unsigned short ip_compute_csum(unsigned char * buff, int len)
return ~csum_partial(buff,len,0);
}
-EXPORT_SYMBOL(ip_compute_csum);
diff --git a/arch/x86_64/lib/csum-wrappers.c b/arch/x86_64/lib/csum-wrappers.c
index a55a6e3e4136..b89aca460ec5 100644
--- a/arch/x86_64/lib/csum-wrappers.c
+++ b/arch/x86_64/lib/csum-wrappers.c
@@ -1,4 +1,4 @@
-/* Copyright 2002 Andi Kleen, SuSE Labs.
+/* Copyright 2002,2003 Andi Kleen, SuSE Labs.
* Subject to the GNU Public License v.2
*
* Wrappers of assembly checksum functions for x86-64.
@@ -7,18 +7,6 @@
#include <asm/checksum.h>
#include <linux/module.h>
-/* Better way for this sought */
-static inline unsigned from64to32(unsigned long x)
-{
- /* add up 32-bit words for 33 bits */
- x = (x & 0xffffffff) + (x >> 32);
- /* add up 16-bit and 17-bit words for 17+c bits */
- x = (x & 0xffff) + (x >> 16);
- /* add up 16-bit and 2-bit for 16+c bit */
- x = (x & 0xffff) + (x >> 16);
- return x;
-}
-
/**
* csum_partial_copy_from_user - Copy and checksum from user space.
* @src: source address (user space)
@@ -36,14 +24,32 @@ csum_partial_copy_from_user(const char *src, char *dst,
{
*errp = 0;
if (likely(access_ok(VERIFY_READ,src, len))) {
- unsigned long sum;
- sum = csum_partial_copy_generic(src,dst,len,isum,errp,NULL);
+ /* Why 6, not 7? To handle odd addresses aligned we
+ would need to do considerable complications to fix the
+ checksum which is defined as an 16bit accumulator. The
+ fix alignment code is primarily for performance
+ compatibility with 32bit and that will handle odd
+ addresses slowly too. */
+ if (unlikely((unsigned long)src & 6)) {
+ while (((unsigned long)src & 6) && len >= 2) {
+ __u16 val16;
+ *errp = __get_user(val16, (__u16 *)src);
+ if (*errp)
+ return isum;
+ *(__u16 *)dst = val16;
+ isum = add32_with_carry(isum, val16);
+ src += 2;
+ dst += 2;
+ len -= 2;
+ }
+ }
+ isum = csum_partial_copy_generic(src,dst,len,isum,errp,NULL);
if (likely(*errp == 0))
- return from64to32(sum);
+ return isum;
}
*errp = -EFAULT;
memset(dst,0,len);
- return 0;
+ return isum;
}
EXPORT_SYMBOL(csum_partial_copy_from_user);
@@ -67,8 +73,22 @@ csum_partial_copy_to_user(const char *src, char *dst,
*errp = -EFAULT;
return 0;
}
+
+ if (unlikely((unsigned long)dst & 6)) {
+ while (((unsigned long)dst & 6) && len >= 2) {
+ __u16 val16 = *(__u16 *)src;
+ isum = add32_with_carry(isum, val16);
+ *errp = __put_user(val16, (__u16 *)dst);
+ if (*errp)
+ return isum;
+ src += 2;
+ dst += 2;
+ len -= 2;
+ }
+ }
+
*errp = 0;
- return from64to32(csum_partial_copy_generic(src,dst,len,isum,NULL,errp));
+ return csum_partial_copy_generic(src,dst,len,isum,NULL,errp);
}
EXPORT_SYMBOL(csum_partial_copy_to_user);
@@ -85,11 +105,9 @@ EXPORT_SYMBOL(csum_partial_copy_to_user);
unsigned int
csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum)
{
- return from64to32(csum_partial_copy_generic(src,dst,len,sum,NULL,NULL));
+ return csum_partial_copy_generic(src,dst,len,sum,NULL,NULL);
}
-//EXPORT_SYMBOL(csum_partial_copy_nocheck);
-
unsigned short csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
__u32 len, unsigned short proto, unsigned int sum)
{
@@ -103,7 +121,7 @@ unsigned short csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
" adcq $0,%[sum]\n"
: [sum] "=r" (sum64)
: "[sum]" (rest),[saddr] "r" (saddr), [daddr] "r" (daddr));
- return csum_fold(from64to32(sum64));
+ return csum_fold(add32_with_carry(sum64 & 0xffffffff, sum64>>32));
}
EXPORT_SYMBOL(csum_ipv6_magic);
diff --git a/arch/x86_64/lib/memcpy.S b/arch/x86_64/lib/memcpy.S
index 72d13ec58732..0204140937f2 100644
--- a/arch/x86_64/lib/memcpy.S
+++ b/arch/x86_64/lib/memcpy.S
@@ -12,103 +12,78 @@
* rax original destination
*/
- // #define FIX_ALIGNMENT
.globl __memcpy
.globl memcpy
- .p2align
+ .p2align 4
__memcpy:
memcpy:
pushq %rbx
movq %rdi,%rax
-#ifdef FIX_ALIGNMENT
- movl %edi,%ecx
- andl $7,%ecx
- jnz bad_alignment
-after_bad_alignment:
-#endif
-
- movq %rdx,%rcx
- movl $64,%ebx
- shrq $6,%rcx
- jz handle_tail
+ movl %edx,%ecx
+ shrl $6,%ecx
+ jz .Lhandle_tail
+
+ .p2align 4
+.Lloop_64:
+ decl %ecx
-loop_64:
movq (%rsi),%r11
movq 8(%rsi),%r8
- movq 2*8(%rsi),%r9
- movq 3*8(%rsi),%r10
+
movq %r11,(%rdi)
movq %r8,1*8(%rdi)
+
+ movq 2*8(%rsi),%r9
+ movq 3*8(%rsi),%r10
+
movq %r9,2*8(%rdi)
movq %r10,3*8(%rdi)
movq 4*8(%rsi),%r11
movq 5*8(%rsi),%r8
- movq 6*8(%rsi),%r9
- movq 7*8(%rsi),%r10
+
movq %r11,4*8(%rdi)
movq %r8,5*8(%rdi)
+
+ movq 6*8(%rsi),%r9
+ movq 7*8(%rsi),%r10
+
movq %r9,6*8(%rdi)
movq %r10,7*8(%rdi)
- addq %rbx,%rsi
- addq %rbx,%rdi
- decl %ecx
- jnz loop_64
+ leaq 64(%rsi),%rsi
+ leaq 64(%rdi),%rdi
+ jnz .Lloop_64
-handle_tail:
+.Lhandle_tail:
movl %edx,%ecx
andl $63,%ecx
shrl $3,%ecx
- jz handle_7
- movl $8,%ebx
-loop_8:
+ jz .Lhandle_7
+ .p2align 4
+.Lloop_8:
+ decl %ecx
movq (%rsi),%r8
movq %r8,(%rdi)
- addq %rbx,%rdi
- addq %rbx,%rsi
- decl %ecx
- jnz loop_8
+ leaq 8(%rdi),%rdi
+ leaq 8(%rsi),%rsi
+ jnz .Lloop_8
-handle_7:
+.Lhandle_7:
movl %edx,%ecx
andl $7,%ecx
- jz ende
-loop_1:
+ jz .Lende
+ .p2align 4
+.Lloop_1:
movb (%rsi),%r8b
movb %r8b,(%rdi)
incq %rdi
incq %rsi
decl %ecx
- jnz loop_1
+ jnz .Lloop_1
-ende:
- sfence
+.Lende:
popq %rbx
ret
-
-#ifdef FIX_ALIGNMENT
- /* align destination */
- /* This is simpleminded. For bigger blocks it may make sense to align
- src and dst to their aligned subset and handle the rest separately */
-bad_alignment:
- movl $8,%r9d
- subl %ecx,%r9d
- movl %r9d,%ecx
- subq %r9,%rdx
- js small_alignment
- jz small_alignment
-align_1:
- movb (%rsi),%r8b
- movb %r8b,(%rdi)
- incq %rdi
- incq %rsi
- decl %ecx
- jnz align_1
- jmp after_bad_alignment
-small_alignment:
- addq %r9,%rdx
- jmp handle_7
-#endif
diff --git a/arch/x86_64/lib/memset.S b/arch/x86_64/lib/memset.S
index 64b53971fc1c..4877825dd065 100644
--- a/arch/x86_64/lib/memset.S
+++ b/arch/x86_64/lib/memset.S
@@ -11,7 +11,7 @@
*/
.globl __memset
.globl memset
- .p2align
+ .p2align 4
memset:
__memset:
movq %rdi,%r10
@@ -25,15 +25,16 @@ __memset:
/* align dst */
movl %edi,%r9d
andl $7,%r9d
- jnz bad_alignment
-after_bad_alignment:
+ jnz .Lbad_alignment
+.Lafter_bad_alignment:
- movq %r11,%rcx
- movl $64,%r8d
- shrq $6,%rcx
- jz handle_tail
+ movl %r11d,%ecx
+ shrl $6,%ecx
+ jz .Lhandle_tail
-loop_64:
+ .p2align 4
+.Lloop_64:
+ decl %ecx
movq %rax,(%rdi)
movq %rax,8(%rdi)
movq %rax,16(%rdi)
@@ -42,43 +43,45 @@ loop_64:
movq %rax,40(%rdi)
movq %rax,48(%rdi)
movq %rax,56(%rdi)
- addq %r8,%rdi
- decl %ecx
- jnz loop_64
+ leaq 64(%rdi),%rdi
+ jnz .Lloop_64
/* Handle tail in loops. The loops should be faster than hard
to predict jump tables. */
-handle_tail:
+ .p2align 4
+.Lhandle_tail:
movl %r11d,%ecx
andl $63&(~7),%ecx
- jz handle_7
+ jz .Lhandle_7
shrl $3,%ecx
-loop_8:
- movq %rax,(%rdi)
- addq $8,%rdi
+ .p2align 4
+.Lloop_8:
decl %ecx
- jnz loop_8
+ movq %rax,(%rdi)
+ leaq 8(%rdi),%rdi
+ jnz .Lloop_8
-handle_7:
+.Lhandle_7:
movl %r11d,%ecx
andl $7,%ecx
- jz ende
-loop_1:
- movb %al,(%rdi)
- addq $1,%rdi
+ jz .Lende
+ .p2align 4
+.Lloop_1:
decl %ecx
- jnz loop_1
+ movb %al,(%rdi)
+ leaq 1(%rdi),%rdi
+ jnz .Lloop_1
-ende:
+.Lende:
movq %r10,%rax
ret
-bad_alignment:
+.Lbad_alignment:
cmpq $7,%r11
- jbe handle_7
+ jbe .Lhandle_7
movq %rax,(%rdi) /* unaligned store */
movq $8,%r8
subq %r9,%r8
addq %r8,%rdi
subq %r8,%r11
- jmp after_bad_alignment
+ jmp .Lafter_bad_alignment
diff --git a/arch/x86_64/vmlinux.lds.S b/arch/x86_64/vmlinux.lds.S
index 2ad9f0e9f90d..61e402904eec 100644
--- a/arch/x86_64/vmlinux.lds.S
+++ b/arch/x86_64/vmlinux.lds.S
@@ -50,10 +50,10 @@ SECTIONS
.xtime_lock : AT ((LOADADDR(.vsyscall_0) + SIZEOF(.vsyscall_0) + 63) & ~(63)) { *(.xtime_lock) }
xtime_lock = LOADADDR(.xtime_lock);
. = ALIGN(16);
- .hpet : AT ((LOADADDR(.xtime_lock) + SIZEOF(.xtime_lock) + 15) & ~(15)) { *(.hpet) }
- hpet = LOADADDR(.hpet);
+ .vxtime : AT ((LOADADDR(.xtime_lock) + SIZEOF(.xtime_lock) + 15) & ~(15)) { *(.vxtime) }
+ vxtime = LOADADDR(.vxtime);
. = ALIGN(16);
- .wall_jiffies : AT ((LOADADDR(.hpet) + SIZEOF(.hpet) + 15) & ~(15)) { *(.wall_jiffies) }
+ .wall_jiffies : AT ((LOADADDR(.vxtime) + SIZEOF(.vxtime) + 15) & ~(15)) { *(.wall_jiffies) }
wall_jiffies = LOADADDR(.wall_jiffies);
. = ALIGN(16);
.sys_tz : AT ((LOADADDR(.wall_jiffies) + SIZEOF(.wall_jiffies) + 15) & ~(15)) { *(.sys_tz) }
@@ -105,6 +105,7 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ SECURITY_INIT
. = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 6480a243ee24..254d32f2c5a6 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -40,23 +40,12 @@
*/
/****** Defines ******/
-#include <linux/config.h>
-#include <linux/version.h>
-
#ifdef PCI_NUM_RESOURCES
#define PCI_BASE_ADDRESS(dev, r) ((dev)->resource[r].start)
#else
#define PCI_BASE_ADDRESS(dev, r) ((dev)->base_address[r])
#endif
-#ifndef VERSION_CODE
-# define VERSION_CODE(vers,rel,seq) ( ((vers)<<16) | ((rel)<<8) | (seq) )
-#endif
-
-#if LINUX_VERSION_CODE < VERSION_CODE(2,2,9) /* No version < 2.2 */
-# error "This kernel is too old: not supported by this file"
-#endif
-
#define ROCKET_PARANOIA_CHECK
#define ROCKET_DISABLE_SIMUSAGE
@@ -72,45 +61,12 @@
#undef REV_PCI_ORDER
#undef ROCKET_DEBUG_IO
-/* CAUTION!!!!! The TIME_STAT Function relies on the Pentium 64 bit
- * register. For various reasons related to 1.2.13, the test for this
- * register is omitted from this driver. If you are going to enable
- * this option, make sure you are running a Pentium CPU and that a
- * cat of /proc/cpuinfo shows ability TS Counters as Yes. Warning part
- * done, don't cry to me if you enable this options and things won't
- * work. If it gives you any problems, then disable the option. The code
- * in this function is pretty straight forward, if it breaks on your
- * CPU, there is probably something funny about your CPU.
- */
-
-#undef TIME_STAT /* For performing timing statistics on driver. */
- /* Produces printks, one every TIME_COUNTER loops, eats */
- /* some of your CPU time. Good for testing or */
- /* other checking, otherwise, leave it undefed */
- /* Doug Ledford */
-#define TIME_STAT_CPU 100 /* This needs to be set to your processor speed */
- /* For example, 100Mhz CPU, set this to 100 */
-#define TIME_COUNTER 180000 /* This is how many iterations to run before */
- /* performing the printk statements. */
- /* 6000 = 1 minute, 360000 = 1 hour, etc. */
- /* Since time_stat is long long, this */
- /* Can be really high if you want :) */
-#undef TIME_STAT_VERBOSE /* Undef this if you want a terse log message. */
-
-#if LINUX_VERSION_CODE < VERSION_CODE(2,4,0)
-#define TTY_DRIVER_NO_DEVFS 0
-#endif
-
#define POLL_PERIOD HZ/100 /* Polling period .01 seconds (10ms) */
/****** Kernel includes ******/
#ifdef MODVERSIONS
-#if LINUX_VERSION_CODE < VERSION_CODE(2,5,00)
-#include <linux/modversions.h>
-#else
#include <config/modversions.h>
-#endif
#endif
#include <linux/module.h>
@@ -118,13 +74,7 @@
#include <linux/major.h>
#include <linux/kernel.h>
#include <linux/signal.h>
-
-#if LINUX_VERSION_CODE < VERSION_CODE(2,4,0)
-#include <linux/malloc.h>
-#else
#include <linux/slab.h>
-#endif
-
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/timer.h>
@@ -153,20 +103,8 @@
#include "rocket_int.h"
#include "rocket.h"
-#ifdef LOCAL_ROCKET_H
-#include "version.h"
-#else
-#define ROCKET_VERSION "2.08"
-#define ROCKET_DATE "02-June-2003"
-#endif /* LOCAL_ROCKET_H */
-
-/*
- * All of the compatibilty code so we can compile serial.c against
- * older kernels is hidden in rocket_compat.h
- */
-#if defined(LOCAL_ROCKET_H) || (LINUX_VERSION_CODE < VERSION_CODE(2,3,23))
-#include "rocket_compat.h"
-#endif
+#define ROCKET_VERSION "2.09"
+#define ROCKET_DATE "12-June-2003"
/****** RocketPort Local Variables ******/
@@ -205,13 +143,6 @@ static int is_PCI[NUM_BOARDS];
static rocketModel_t rocketModel[NUM_BOARDS];
static int max_board;
-#ifdef TIME_STAT
-static unsigned long long time_stat;
-static unsigned long time_stat_short;
-static unsigned long time_stat_long;
-static unsigned long time_counter;
-#endif
-
/*
* The following arrays define the interrupt bits corresponding to each AIOP.
* These bits are different between the ISA and regular PCI boards and the
@@ -241,7 +172,7 @@ static unsigned char lineNumbers[MAX_RP_PORTS];
static unsigned long nextLineNumber;
/***** RocketPort Static Prototypes *********/
-static int __init init_ISA(int i, int *reserved_controller);
+static int __init init_ISA(int i);
static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
static void rp_flush_buffer(struct tty_struct *tty);
static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
@@ -564,16 +495,6 @@ static void rp_do_poll(unsigned long dummy)
unsigned char AiopMask;
Word_t bit;
-#ifdef TIME_STAT
- unsigned long low = 0, high = 0, loop_time;
- unsigned long long time_stat_tmp = 0, time_stat_tmp2 = 0;
-
- __asm__(".byte 0x0f,0x31":"=a"(low), "=d"(high));
- time_stat_tmp = high;
- time_stat_tmp <<= 32;
- time_stat_tmp += low;
-#endif /* TIME_STAT */
-
/* Walk through all the boards (ctrl's) */
for (ctrl = 0; ctrl < max_board; ctrl++) {
if (rcktpt_io_addr[ctrl] <= 0)
@@ -635,48 +556,6 @@ static void rp_do_poll(unsigned long dummy)
*/
if (atomic_read(&rp_num_ports_open))
mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
-
-#ifdef TIME_STAT
- __asm__(".byte 0x0f,0x31":"=a"(low), "=d"(high));
- time_stat_tmp2 = high;
- time_stat_tmp2 <<= 32;
- time_stat_tmp2 += low;
- time_stat_tmp2 -= time_stat_tmp;
- time_stat += time_stat_tmp2;
- if (time_counter == 0)
- time_stat_short = time_stat_long = time_stat_tmp2;
- else {
- if (time_stat_tmp2 < time_stat_short)
- time_stat_short = time_stat_tmp2;
- else if (time_stat_tmp2 > time_stat_long)
- time_stat_long = time_stat_tmp2;
- }
- if (++time_counter == TIME_COUNTER) {
- loop_time =
- (unsigned
- long) (((unsigned long) (time_stat >> 32) *
- ((unsigned long) (0xffffffff) /
- (TIME_STAT_CPU * TIME_COUNTER))) +
- ((unsigned long) time_stat /
- (TIME_STAT_CPU * TIME_COUNTER)));
-#ifdef TIME_STAT_VERBOSE
- printk(KERN_INFO "rp_do_poll: Interrupt Timings\n");
- printk(KERN_INFO " %5ld iterations; %ld us min,\n",
- (long) TIME_COUNTER,
- (time_stat_short / TIME_STAT_CPU));
- printk(KERN_INFO " %5ld us max, %ld us average per iteration.\n",
- (time_stat_long / TIME_STAT_CPU), loop_time);
- printk(KERN_INFO "We want to use < 5,000 us for an iteration.\n");
-#else /* TIME_STAT_VERBOSE */
- printk(KERN_INFO "rp: %ld loops: %ld min, %ld max, %ld us/loop.\n",
- (long) TIME_COUNTER,
- (time_stat_short / TIME_STAT_CPU),
- (time_stat_long / TIME_STAT_CPU), loop_time);
-#endif /* TIME_STAT_VERBOSE */
- time_counter = time_stat = 0;
- time_stat_short = time_stat_long = 0;
- }
-#endif /* TIME_STAT */
}
/*
@@ -762,10 +641,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
spin_lock_init(&info->slock);
sema_init(&info->write_sem, 1);
rp_table[line] = info;
-#if LINUX_VERSION_CODE > VERSION_CODE(2,5,0)
if (pci_dev)
tty_register_device(rocket_driver, line, &pci_dev->dev);
-#endif
}
/*
@@ -1039,12 +916,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
CHANNEL_t *cp;
unsigned long page;
-#if LINUX_VERSION_CODE > VERSION_CODE(2,5,0)
line = TTY_GET_LINE(tty);
-#else
- line = MINOR(tty->device) - TTY_DRIVER_MINOR_START(tty);
-#endif
-
if ((line < 0) || (line >= MAX_RP_PORTS) || ((info = rp_table[line]) == NULL))
return -ENXIO;
@@ -1070,9 +942,6 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
info->tty = tty;
if (info->count++ == 0) {
-#if ((LINUX_VERSION_CODE < VERSION_CODE(2,5,0)) && defined(MODULE))
- MOD_INC_USE_COUNT;
-#endif
atomic_inc(&rp_num_ports_open);
#ifdef ROCKET_DEBUG_OPEN
@@ -1254,10 +1123,6 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
info->flags &= ~(ROCKET_INITIALIZED | ROCKET_CLOSING | ROCKET_NORMAL_ACTIVE);
tty->closing = 0;
wake_up_interruptible(&info->close_wait);
-
-#if ((LINUX_VERSION_CODE < VERSION_CODE(2,5,0)) && defined(MODULE))
- MOD_DEC_USE_COUNT;
-#endif
atomic_dec(&rp_num_ports_open);
#ifdef ROCKET_DEBUG_OPEN
@@ -1406,8 +1271,6 @@ static int set_modem_info(struct r_port *info, unsigned int cmd,
return 0;
}
-#if LINUX_VERSION_CODE > VERSION_CODE(2,5,0)
-
/*
* Returns the state of the serial modem control lines. These next 2 functions
* are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
@@ -1450,8 +1313,6 @@ static int rp_tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
-#endif /* Linux > 2.5 */
-
static int get_config(struct r_port *info, struct rocket_config *retinfo)
{
struct rocket_config tmp;
@@ -1781,12 +1642,8 @@ static void rp_hangup(struct tty_struct *tty)
rp_flush_buffer(tty);
if (info->flags & ROCKET_CLOSING)
return;
- if (info->count) {
-#if ((LINUX_VERSION_CODE < VERSION_CODE(2,5,0)) && defined(MODULE))
- MOD_DEC_USE_COUNT;
-#endif
+ if (info->count)
atomic_dec(&rp_num_ports_open);
- }
clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
info->count = 0;
@@ -2344,17 +2201,9 @@ __init int register_PCI(int i, struct pci_dev *dev)
for (aiop = 0; aiop < max_num_aiops; aiop++)
ctlp->AiopNumChan[aiop] = ports_per_aiop;
-#if LINUX_VERSION_CODE < VERSION_CODE(2,3,99)
- printk(KERN_INFO "Comtrol PCI controller #%d ID 0x%x found at 0x%lx, "
- "%d AIOP(s) (%s)\n", i, dev->device, rcktpt_io_addr[i],
- num_aiops, rocketModel[i].modelString);
-#else
- printk
- ("Comtrol PCI controller #%d ID 0x%x found in bus:slot:fn %s at address %04lx, "
+ printk("Comtrol PCI controller #%d ID 0x%x found in bus:slot:fn %s at address %04lx, "
"%d AIOP(s) (%s)\n", i, dev->device, dev->slot_name,
rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString);
-#endif
-
printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
rocketModel[i].modelString,
rocketModel[i].startingPortNumber,
@@ -2391,9 +2240,6 @@ __init int register_PCI(int i, struct pci_dev *dev)
return (1);
}
-#if LINUX_VERSION_CODE > VERSION_CODE(2,3,99) /* Linux version 2.4 and greater */
-
-
/*
* Probes for PCI cards, inits them if found
* Input: board_found = number of ISA boards already found, or the
@@ -2413,51 +2259,6 @@ static int __init init_PCI(int boards_found)
return (count);
}
-#else /* Linux version 2.2 */
-
-/*
- * Linux 2.2 pci_find_device() does not allow a search of all devices for a certain vendor,
- * you have to try each device ID. Comtrol device ID's are 0x0000 -0x000F for the original
- * boards. Newer board are 0x08xx (see upci_ids[]).
- */
-static int __init init_PCI(int boards_found)
-{
- int j, count = 0;
- struct pci_dev *dev = NULL;
-
- static int upci_ids[] = {
- PCI_DEVICE_ID_URP32INTF,
- PCI_DEVICE_ID_URP8INTF,
- PCI_DEVICE_ID_URP16INTF,
- PCI_DEVICE_ID_CRP16INTF,
- PCI_DEVICE_ID_URP8OCTA,
- PCI_DEVICE_ID_UPCI_RM3_8PORT,
- PCI_DEVICE_ID_UPCI_RM3_4PORT
- };
-
-#define NUM_UPCI_IDS (sizeof(upci_ids) / sizeof(upci_ids[0]))
-
- /* Try finding devices with PCI ID's 0x0000 - 0x000F */
- for (j = 0; j < 16; j++) {
- while ((dev = pci_find_device(PCI_VENDOR_ID_RP, j, dev))) {
- register_PCI(count + boards_found, dev);
- count++;
- }
- }
-
- /* Now try finding the UPCI devices, which have PCI ID's 0x0800 - 0x080F */
- for (j = 0; j < NUM_UPCI_IDS; j++) {
- while ((dev =
- pci_find_device(PCI_VENDOR_ID_RP, upci_ids[j], dev))) {
- register_PCI(count + boards_found, dev);
- count++;
- }
- }
- return (count);
-}
-
-#endif /* Linux version 2.2/2.4 */
-
#endif /* CONFIG_PCI */
/*
@@ -2465,7 +2266,7 @@ static int __init init_PCI(int boards_found)
* Input: i = the board number to look for
* Returns: 1 if board found, 0 else
*/
-static int __init init_ISA(int i, int *reserved_controller)
+static int __init init_ISA(int i)
{
int num_aiops, num_chan = 0, total_num_chan = 0;
int aiop, chan;
@@ -2473,20 +2274,16 @@ static int __init init_ISA(int i, int *reserved_controller)
CONTROLLER_t *ctlp;
char *type_string;
- if (rcktpt_io_addr[i] == 0 || controller == 0)
+ /* If io_addr is zero, no board configured */
+ if (rcktpt_io_addr[i] == 0)
return (0);
- if (check_region(rcktpt_io_addr[i], 64)) {
- printk(KERN_INFO "RocketPort board address 0x%lx in use...\n", rcktpt_io_addr[i]);
+ /* Reserve the IO region */
+ if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) {
+ printk(KERN_INFO "Unable to reserve IO region for configured ISA RocketPort at address 0x%lx, board not installed...\n", rcktpt_io_addr[i]);
rcktpt_io_addr[i] = 0;
return (0);
}
- if (rcktpt_io_addr[i] + 0x40 == controller) {
- *reserved_controller = 1;
- request_region(rcktpt_io_addr[i], 68, "Comtrol RocketPort");
- } else {
- request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort");
- }
ctlp = sCtlNumToCtlPtr(i);
@@ -2522,24 +2319,22 @@ static int __init init_ISA(int i, int *reserved_controller)
for (aiop = 0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x400);
- num_aiops =
- sInitController(ctlp, i, controller + (i * 0x400), aiopio, MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0);
+ num_aiops = sInitController(ctlp, i, controller + (i * 0x400), aiopio, MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0);
if (ctlp->boardType == ROCKET_TYPE_PC104) {
sEnAiop(ctlp, 2); /* only one AIOPIC, but these */
sEnAiop(ctlp, 3); /* CSels used for other stuff */
}
+ /* If something went wrong initing the AIOP's release the ISA IO memory */
if (num_aiops <= 0) {
- if (rcktpt_io_addr[i] + 0x40 == controller) {
- *reserved_controller = 0;
- release_region(rcktpt_io_addr[i], 68);
- } else {
- release_region(rcktpt_io_addr[i], 64);
- }
+ release_region(rcktpt_io_addr[i], 64);
rcktpt_io_addr[i] = 0;
return (0);
}
+
+ rocketModel[i].startingPortNumber = nextLineNumber;
+
for (aiop = 0; aiop < num_aiops; aiop++) {
sResetAiopByNum(ctlp, aiop);
sEnAiop(ctlp, aiop);
@@ -2565,9 +2360,9 @@ static int __init init_ISA(int i, int *reserved_controller)
rocketModel[i].numPorts = total_num_chan;
rocketModel[i].model = MODEL_ISA;
- printk(KERN_INFO "Comtrol ISA controller #%d found at 0x%lx, "
- "%d AIOPs %s\n", i, rcktpt_io_addr[i], num_aiops,
- type_string);
+ printk(KERN_INFO "RocketPort ISA card #%d found at 0x%lx - %d AIOPs %s\n",
+ i, rcktpt_io_addr[i], num_aiops, type_string);
+
printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
rocketModel[i].modelString,
rocketModel[i].startingPortNumber,
@@ -2595,10 +2390,8 @@ static struct tty_operations rocket_ops = {
.break_ctl = rp_break,
.send_xchar = rp_send_xchar,
.wait_until_sent = rp_wait_until_sent,
-#if (LINUX_VERSION_CODE > VERSION_CODE(2,5,0))
.tiocmget = rp_tiocmget,
.tiocmset = rp_tiocmset,
-#endif /* Kernel > 2.5 */
};
/*
@@ -2607,7 +2400,6 @@ static struct tty_operations rocket_ops = {
int __init rp_init(void)
{
int retval, pci_boards_found, isa_boards_found, i;
- int reserved_controller = 0;
printk(KERN_INFO "RocketPort device driver module, version %s, %s\n",
ROCKET_VERSION, ROCKET_DATE);
@@ -2634,12 +2426,20 @@ int __init rp_init(void)
nextLineNumber = 0;
memset(rocketModel, 0, sizeof (rocketModel));
- if (board1 && controller == 0)
- controller = board1 + 0x40;
+ /*
+ * If board 1 is non-zero, there is at least one ISA configured. If controller is
+ * zero, use the default controller IO address of board1 + 0x40.
+ */
+ if (board1) {
+ if (controller == 0)
+ controller = board1 + 0x40;
+ } else {
+ controller = 0; /* Used as a flag, meaning no ISA boards */
+ }
- if (controller && check_region(controller, 4)) {
- printk(KERN_INFO "Controller IO addresses in use, unloading driver.\n");
- put_tty_driver(rocket_driver);
+ /* If an ISA card is configured, reserve the 4 byte IO space for the Mudbac controller */
+ if (controller && (!request_region(controller, 4, "Comtrol RocketPort"))) {
+ printk(KERN_INFO "Unable to reserve IO region for first configured ISA RocketPort controller 0x%lx. Driver exiting \n", controller);
return -EBUSY;
}
@@ -2663,9 +2463,7 @@ int __init rp_init(void)
* driver with the tty layer.
*/
-#if (LINUX_VERSION_CODE > VERSION_CODE(2,5,0))
rocket_driver->owner = THIS_MODULE;
-#endif /* Kernel > 2.5 */
rocket_driver->flags = TTY_DRIVER_NO_DEVFS;
rocket_driver->devfs_name = "tts/R";
rocket_driver->name = "ttyR";
@@ -2701,7 +2499,7 @@ int __init rp_init(void)
pci_boards_found = 0;
for (i = 0; i < NUM_BOARDS; i++) {
- if (init_ISA(i, &reserved_controller))
+ if (init_ISA(i))
isa_boards_found++;
}
@@ -2720,13 +2518,6 @@ int __init rp_init(void)
return -ENXIO;
}
- if (isa_boards_found) {
- if (reserved_controller == 0)
- request_region(controller, 4, "Comtrol RocketPort");
- } else {
- controller = 0;
- }
-
return 0;
}
@@ -2736,7 +2527,6 @@ static void rp_cleanup_module(void)
{
int retval;
int i;
- int released_controller = 0;
del_timer_sync(&rocket_timer);
@@ -2754,14 +2544,9 @@ static void rp_cleanup_module(void)
for (i = 0; i < NUM_BOARDS; i++) {
if (rcktpt_io_addr[i] <= 0 || is_PCI[i])
continue;
- if (rcktpt_io_addr[i] + 0x40 == controller) {
- released_controller++;
- release_region(rcktpt_io_addr[i], 68);
- } else {
- release_region(rcktpt_io_addr[i], 64);
- }
+ release_region(rcktpt_io_addr[i], 64);
}
- if (controller && released_controller == 0)
+ if (controller)
release_region(controller, 4);
}
#endif
diff --git a/drivers/char/rocket.h b/drivers/char/rocket.h
index 7128fbd92b09..ae6b04f90c03 100644
--- a/drivers/char/rocket.h
+++ b/drivers/char/rocket.h
@@ -1,29 +1,9 @@
/*
- * rocket.h --- the exported interface of the rocket driver to
- * its configuration program.
+ * rocket.h --- the exported interface of the rocket driver to its configuration program.
*
* Written by Theodore Ts'o, Copyright 1997.
+ * Copyright 1997 Comtrol Corporation.
*
- * Copyright 1994, 1997, 2003 Comtrol Corporation. All Rights Reserved.
- *
- * The following source code is subject to Comtrol Corporation's
- * Developer's License Agreement.
- *
- * This source code is protected by United States copyright law and
- * international copyright treaties.
- *
- * This source code may only be used to develop software products that
- * will operate with Comtrol brand hardware.
- *
- * You may not reproduce nor distribute this source code in its original
- * form but must produce a derivative work which includes portions of
- * this source code only.
- *
- * The portions of this source code which you use in your derivative
- * work must bear Comtrol's copyright notice:
- *
- * Copyright 1994 Comtrol Corporation.
- *
*/
/* Model Information Struct */
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
index f5c8d3ac1417..7297281f358d 100644
--- a/drivers/char/rocket_int.h
+++ b/drivers/char/rocket_int.h
@@ -2,26 +2,7 @@
* rocket_int.h --- internal header file for rocket.c
*
* Written by Theodore Ts'o, Copyright 1997.
- *
- * Copyright 1994, 1997, 2003 Comtrol Corporation. All Rights Reserved.
- *
- * The following source code is subject to Comtrol Corporation's
- * Developer's License Agreement.
- *
- * This source code is protected by United States copyright law and
- * international copyright treaties.
- *
- * This source code may only be used to develop software products that
- * will operate with Comtrol brand hardware.
- *
- * You may not reproduce nor distribute this source code in its original
- * form but must produce a derivative work which includes portions of
- * this source code only.
- *
- * The portions of this source code which you use in your derivative
- * work must bear Comtrol's copyright notice:
- *
- * Copyright 1994 Comtrol Corporation.
+ * Copyright 1997 Comtrol Corporation.
*
*/
@@ -98,17 +79,9 @@ static inline unsigned short sInW(unsigned short port)
#define sInW(a) (inw_p(a))
#endif /* ROCKET_DEBUG_IO */
-/* This is used to move arrays of bytes so byte swapping isn't
- * appropriate. On Linux 2.3 and above outsw is the same as
- * outsw_ns, but we use the old form for compatibility with
- * old kernels. */
-#if defined(__BIG_ENDIAN) && (LINUX_VERSION_CODE < VERSION_CODE(2,3,0))
-#define sOutStrW(port, addr, count) if (count) outsw_ns(port, addr, count)
-#define sInStrW(port, addr, count) if (count) insw_ns(port, addr, count)
-#else
+/* This is used to move arrays of bytes so byte swapping isn't appropriate. */
#define sOutStrW(port, addr, count) if (count) outsw(port, addr, count)
#define sInStrW(port, addr, count) if (count) insw(port, addr, count)
-#endif
#define CTL_SIZE 8
#define AIOP_CTL_SIZE 4
@@ -1318,11 +1291,7 @@ struct r_port {
/* Compact PCI device */
#define PCI_DEVICE_ID_CRP16INTF 0x0903 /* Rocketport Compact PCI 16 port w/external I/F */
-/* Taking care of some kernel incompatibilities... */
-#if LINUX_VERSION_CODE > VERSION_CODE(2,5,68)
-
#define TTY_GET_LINE(t) t->index
-
#define TTY_DRIVER_MINOR_START(t) t->driver->minor_start
#define TTY_DRIVER_SUBTYPE(t) t->driver->subtype
#define TTY_DRIVER_NAME(t) t->driver->name
@@ -1330,15 +1299,4 @@ struct r_port {
#define TTY_DRIVER_FLUSH_BUFFER_EXISTS(t) t->driver->flush_buffer
#define TTY_DRIVER_FLUSH_BUFFER(t) t->driver->flush_buffer(t)
-#else
-#define TTY_GET_LINE(t) minor(t->device) - TTY_DRIVER_MINOR_START(t)
-
-#define TTY_DRIVER_MINOR_START(t) t->driver.minor_start
-#define TTY_DRIVER_SUBTYPE(t) t->driver.subtype
-#define TTY_DRIVER_NAME(t) t->driver.name
-#define TTY_DRIVER_NAME_BASE(t) t->driver.name_base
-#define TTY_DRIVER_FLUSH_BUFFER_EXISTS(t) t->driver.flush_buffer
-#define TTY_DRIVER_FLUSH_BUFFER(t) t->driver.flush_buffer(t)
-
-#endif
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 12fdd2034c37..e58a83d6ad55 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2289,16 +2289,15 @@ static void ir_tasklet_func(unsigned long data)
/* get the descriptor based on packet_buffer cursor */
f = video->frames[video->current_packet / MAX_PACKETS];
block = &(f->descriptor_pool[video->current_packet % MAX_PACKETS]);
- xferstatus = le16_to_cpu(block->u.in.il.q[3] >> 16);
+ xferstatus = le32_to_cpu(block->u.in.il.q[3]) >> 16;
xferstatus &= 0x1F;
+ irq_printk("ir_tasklet_func: xferStatus/resCount [%d] = 0x%08x\n", i, le32_to_cpu(block->u.in.il.q[3]) );
/* get the current frame */
f = video->frames[video->active_frame];
/* exclude empty packet */
if (packet_length > 8 && xferstatus == 0x11) {
- irq_printk("ir_tasklet_func: xferStatus/resCount [%d] = 0x%08x\n", i, le32_to_cpu(block->u.in.il.q[3]) );
-
/* check for start of frame */
/* DRD> Changed to check section type ([0]>>5==0)
and dif sequence ([1]>>4==0) */
@@ -2380,7 +2379,7 @@ static void ir_tasklet_func(unsigned long data)
} else {
prev->u.in.il.q[0] |= 3 << 20; /* enable interrupt */
}
- prev->u.in.il.q[2] = (cpu_to_le32(next_dma) | 1); /* set Z=1 */
+ prev->u.in.il.q[2] = cpu_to_le32(next_dma | 1); /* set Z=1 */
wmb();
/* wake up DMA in case it fell asleep */
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index d293c6035d94..ce286ef763a1 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -86,7 +86,7 @@
#define TRACE() printk(KERN_ERR "eth1394:%s[%d] ---- TRACE\n", __FUNCTION__, __LINE__)
static char version[] __devinitdata =
- "$Rev: 945 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 951 $ Ben Collins <bcollins@debian.org>";
struct fragment_info {
struct list_head list;
@@ -1424,6 +1424,12 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
struct packet_task *ptask;
struct node_entry *ne;
+ if (skb_is_nonlinear(skb)) {
+ ret = skb_linearize(skb, kmflags);
+ if(ret)
+ goto fail;
+ }
+
ptask = kmem_cache_alloc(packet_task_cache, kmflags);
if(ptask == NULL) {
ret = -ENOMEM;
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index fc9b69e556d0..3fc15598dbee 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -164,7 +164,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata =
- "$Rev: 938 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 948 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
static int phys_dma = 1;
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
index 17ec39f43fe2..0b227fe0059f 100644
--- a/drivers/pci/pci.ids
+++ b/drivers/pci/pci.ids
@@ -3752,6 +3752,8 @@
0005 Rocketport 8 port w/octa cable
0006 Rocketport 8 port w/RJ11 connectors
0007 Rocketport 4 port w/RJ11 connectors
+ 0008 Rocketport 8 port w/ DB78 SNI (Siemens) connector
+ 0009 Rocketport 16 port w/ DB78 SNI (Siemens) connector
000a Rocketport Plus 4 port
000b Rocketport Plus 8 port
000c RocketModem 6 port
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index d4dcd6f1239b..947b99663d02 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -619,12 +619,12 @@ static int scsi_add_lun(Scsi_Device *sdev, char *inq_result, int *bflags)
if (inq_result[7] & 0x10)
sdev->sdtr = 1;
- scsi_device_register(sdev);
-
sprintf(sdev->devfs_name, "scsi/host%d/bus%d/target%d/lun%d",
sdev->host->host_no, sdev->channel,
sdev->id, sdev->lun);
+ scsi_device_register(sdev);
+
/*
* End driverfs/devfs code.
*/
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 74e717cb5f37..8bbd871b03db 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -260,8 +260,21 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
struct address_space *mapping = inode->i_mapping;
struct backing_dev_info *bdi = mapping->backing_dev_info;
- if (bdi->memory_backed)
+ if (bdi->memory_backed) {
+ if (sb == blockdev_superblock) {
+ /*
+ * Dirty memory-backed blockdev: the ramdisk
+ * driver does this.
+ */
+ list_move(&inode->i_list, &sb->s_dirty);
+ continue;
+ }
+ /*
+ * Assume that all inodes on this superblock are memory
+ * backed. Skip the superblock.
+ */
break;
+ }
if (wbc->nonblocking && bdi_write_congested(bdi)) {
wbc->encountered_congestion = 1;
diff --git a/fs/namei.c b/fs/namei.c
index a9384f6fe8ea..28feeb2366c4 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -325,7 +325,7 @@ static inline int exec_permission_lite(struct inode *inode)
return -EACCES;
ok:
- return security_inode_permission_lite(inode, MAY_EXEC);
+ return security_inode_permission(inode, MAY_EXEC);
}
/*
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0f09f5b73a69..59c2b950e8b8 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -45,3 +45,9 @@
*(__ksymtab_strings) \
}
+#define SECURITY_INIT \
+ .security_initcall.init : { \
+ __security_initcall_start = .; \
+ *(.security_initcall.init) \
+ __security_initcall_end = .; \
+ }
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 6570d0d65e02..9d99b8b53af0 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -107,6 +107,14 @@ extern void __set_fixmap (enum fixed_addresses idx,
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START (__fix_to_virt(FIX_VSYSCALL))
+#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE)
+
+
extern void __this_fixmap_does_not_exist(void);
/*
diff --git a/include/asm-x86_64/checksum.h b/include/asm-x86_64/checksum.h
index 1b84eeab1cc7..35d3e37d9378 100644
--- a/include/asm-x86_64/checksum.h
+++ b/include/asm-x86_64/checksum.h
@@ -125,7 +125,7 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
* Before filling it in it needs to be csum_fold()'ed.
* buff should be aligned to a 64bit boundary if possible.
*/
-extern unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum);
+extern unsigned int csum_partial(const unsigned char *buff, unsigned len, unsigned int sum);
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1
#define HAVE_CSUM_COPY_USER 1
@@ -179,4 +179,14 @@ extern unsigned short
csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
__u32 len, unsigned short proto, unsigned int sum);
+static inline unsigned add32_with_carry(unsigned a, unsigned b)
+{
+ asm("addl %2,%0\n\t"
+ "adcl $0,%0"
+ : "=r" (a)
+ : "0" (a), "r" (b));
+ return a;
+}
+
#endif
+
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index 1133a85d40ed..a03fc84b2b62 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -35,6 +35,8 @@
enum fixed_addresses {
VSYSCALL_LAST_PAGE,
VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
+ VSYSCALL_HPET,
+ FIX_HPET_BASE,
#ifdef CONFIG_X86_LOCAL_APIC
FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */
#endif
diff --git a/include/asm-x86_64/mc146818rtc.h b/include/asm-x86_64/mc146818rtc.h
index d6e3009430c1..9333b6bfacec 100644
--- a/include/asm-x86_64/mc146818rtc.h
+++ b/include/asm-x86_64/mc146818rtc.h
@@ -24,6 +24,11 @@ outb_p((addr),RTC_PORT(0)); \
outb_p((val),RTC_PORT(1)); \
})
+#ifndef CONFIG_HPET_TIMER
#define RTC_IRQ 8
+#else
+/* Temporary workaround due to IRQ routing problem. */
+#define RTC_IRQ 0
+#endif
#endif /* _ASM_MC146818RTC_H */
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index c1fbae233c35..243c83f7e222 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -313,7 +313,7 @@ extern inline void sync_core(void)
#define ARCH_HAS_PREFETCH
static inline void prefetch(void *x)
{
- asm volatile("2: prefetchnta %0\n1:\t"
+ asm volatile("2: prefetcht0 %0\n1:\t"
".section __ex_table,\"a\"\n\t"
" .align 8\n\t"
" .quad 2b,1b\n\t"
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index c5900a1356b3..78f6a491449d 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -54,6 +54,8 @@ extern void swap_low_mappings(void);
extern void oops_begin(void);
extern void die(const char *,struct pt_regs *,long);
extern void __die(const char * str, struct pt_regs * regs, long err);
+extern void __show_regs(struct pt_regs * regs);
+extern void show_regs(struct pt_regs * regs);
extern int map_syscall32(struct mm_struct *mm, unsigned long address);
extern char *syscall32_page;
diff --git a/include/asm-x86_64/timex.h b/include/asm-x86_64/timex.h
index 7e0a1309bfce..bc5620ace301 100644
--- a/include/asm-x86_64/timex.h
+++ b/include/asm-x86_64/timex.h
@@ -30,6 +30,34 @@ static inline cycles_t get_cycles (void)
extern unsigned int cpu_khz;
-extern struct hpet_data hpet;
+/*
+ * Documentation on HPET can be found at:
+ * http://www.intel.com/ial/home/sp/pcmmspec.htm
+ * ftp://download.intel.com/ial/home/sp/mmts098.pdf
+ */
+
+#define HPET_ID 0x000
+#define HPET_PERIOD 0x004
+#define HPET_CFG 0x010
+#define HPET_STATUS 0x020
+#define HPET_COUNTER 0x0f0
+#define HPET_T0_CFG 0x100
+#define HPET_T0_CMP 0x108
+#define HPET_T0_ROUTE 0x110
+
+#define HPET_ID_VENDOR 0xffff0000
+#define HPET_ID_LEGSUP 0x00008000
+#define HPET_ID_NUMBER 0x00000f00
+#define HPET_ID_REV 0x000000ff
+
+#define HPET_CFG_ENABLE 0x001
+#define HPET_CFG_LEGACY 0x002
+
+#define HPET_T0_ENABLE 0x004
+#define HPET_T0_PERIODIC 0x008
+#define HPET_T0_SETVAL 0x040
+#define HPET_T0_32BIT 0x100
+
+extern struct vxtime_data vxtime;
#endif
diff --git a/include/asm-x86_64/vsyscall.h b/include/asm-x86_64/vsyscall.h
index 86947472e9fd..b78e931a39c8 100644
--- a/include/asm-x86_64/vsyscall.h
+++ b/include/asm-x86_64/vsyscall.h
@@ -15,7 +15,7 @@ enum vsyscall_num {
#ifdef __KERNEL__
-#define __section_hpet __attribute__ ((unused, __section__ (".hpet"), aligned(16)))
+#define __section_vxtime __attribute__ ((unused, __section__ (".vxtime"), aligned(16)))
#define __section_wall_jiffies __attribute__ ((unused, __section__ (".wall_jiffies"), aligned(16)))
#define __section_jiffies __attribute__ ((unused, __section__ (".jiffies"), aligned(16)))
#define __section_sys_tz __attribute__ ((unused, __section__ (".sys_tz"), aligned(16)))
@@ -23,22 +23,24 @@ enum vsyscall_num {
#define __section_xtime __attribute__ ((unused, __section__ (".xtime"), aligned(16)))
#define __section_xtime_lock __attribute__ ((unused, __section__ (".xtime_lock"), aligned(L1_CACHE_BYTES)))
+#define VXTIME_TSC 1
+#define VXTIME_HPET 2
-struct hpet_data {
- long address; /* base address */
+struct vxtime_data {
+ long hpet_address; /* HPET base address */
unsigned long hz; /* HPET clocks / sec */
- int trigger; /* value at last interrupt */
int last;
- int offset;
unsigned long last_tsc;
- long ticks;
+ long quot;
+ long tsc_quot;
+ int mode;
};
#define hpet_readl(a) readl(fix_to_virt(FIX_HPET_BASE) + a)
#define hpet_writel(d,a) writel(d, fix_to_virt(FIX_HPET_BASE) + a)
/* vsyscall space (readonly) */
-extern struct hpet_data __hpet;
+extern struct vxtime_data __vxtime;
extern struct timespec __xtime;
extern volatile unsigned long __jiffies;
extern unsigned long __wall_jiffies;
@@ -46,7 +48,7 @@ extern struct timezone __sys_tz;
extern seqlock_t __xtime_lock;
/* kernel space (writeable) */
-extern struct hpet_data hpet;
+extern struct vxtime_data vxtime;
extern unsigned long wall_jiffies;
extern struct timezone sys_tz;
extern int sysctl_vsyscall;
diff --git a/include/linux/init.h b/include/linux/init.h
index ea0c7559adb7..64d4fdf7a77d 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -64,6 +64,7 @@ typedef int (*initcall_t)(void);
typedef void (*exitcall_t)(void);
extern initcall_t __con_initcall_start, __con_initcall_end;
+extern initcall_t __security_initcall_start, __security_initcall_end;
#endif
#ifndef MODULE
@@ -96,6 +97,9 @@ extern initcall_t __con_initcall_start, __con_initcall_end;
#define console_initcall(fn) \
static initcall_t __initcall_##fn __attribute__ ((unused,__section__ (".con_initcall.init")))=fn
+#define security_initcall(fn) \
+ static initcall_t __initcall_##fn __attribute__ ((unused,__section__ (".security_initcall.init"))) = fn
+
struct obs_kernel_param {
const char *str;
int (*setup_func)(char *);
@@ -143,6 +147,8 @@ struct obs_kernel_param {
#define device_initcall(fn) module_init(fn)
#define late_initcall(fn) module_init(fn)
+#define security_initcall(fn) module_init(fn)
+
/* These macros create a dummy inline: gcc 2.9x does not count alias
as usage, hence the `unused function' warning when __init functions
are declared static. We use the dummy __*_module_inline functions
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index ba8d9fac6bf3..9b51d57947f1 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1399,6 +1399,8 @@
#define PCI_DEVICE_ID_RP8OCTA 0x0005
#define PCI_DEVICE_ID_RP8J 0x0006
#define PCI_DEVICE_ID_RP4J 0x0007
+#define PCI_DEVICE_ID_RP8SNI 0x0008
+#define PCI_DEVICE_ID_RP16SNI 0x0009
#define PCI_DEVICE_ID_RPP4 0x000A
#define PCI_DEVICE_ID_RPP8 0x000B
#define PCI_DEVICE_ID_RP8M 0x000C
diff --git a/include/linux/security.h b/include/linux/security.h
index c1d1480d2f49..62b1639bd3aa 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -46,7 +46,6 @@ extern void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,
extern int cap_bprm_set_security (struct linux_binprm *bprm);
extern void cap_bprm_compute_creds (struct linux_binprm *bprm);
extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
-extern void cap_task_kmod_set_label (void);
extern void cap_task_reparent_to_init (struct task_struct *p);
extern int cap_syslog (int type);
@@ -328,16 +327,6 @@ struct swap_info_struct;
* @inode contains the inode structure to check.
* @mask contains the permission mask.
* Return 0 if permission is granted.
- * @inode_permission_lite:
- * Check permission before accessing an inode. This hook is
- * currently only called when checking MAY_EXEC access during
- * pathname resolution. The dcache lock is held and thus modules
- * that could sleep or contend the lock should return -EAGAIN to
- * inform the kernel to drop the lock and try again calling the
- * full permission hook.
- * @inode contains the inode structure to check.
- * @mask contains the permission mask.
- * Return 0 if permission is granted.
* @inode_setattr:
* Check permission before setting file attributes. Note that the kernel
* call to notify_change is performed from several locations, whenever
@@ -607,10 +596,6 @@ struct swap_info_struct;
* @arg4 contains a argument.
* @arg5 contains a argument.
* Return 0 if permission is granted.
- * @task_kmod_set_label:
- * Set the security attributes in current->security for the kernel module
- * loader thread, so that it has the permissions needed to perform its
- * function.
* @task_reparent_to_init:
* Set the security attributes in @p->security for a kernel thread that
* is being reparented to the init task.
@@ -1057,7 +1042,6 @@ struct security_operations {
int (*inode_readlink) (struct dentry *dentry);
int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
int (*inode_permission) (struct inode *inode, int mask);
- int (*inode_permission_lite) (struct inode *inode, int mask);
int (*inode_setattr) (struct dentry *dentry, struct iattr *attr);
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
void (*inode_delete) (struct inode *inode);
@@ -1111,7 +1095,6 @@ struct security_operations {
int (*task_prctl) (int option, unsigned long arg2,
unsigned long arg3, unsigned long arg4,
unsigned long arg5);
- void (*task_kmod_set_label) (void);
void (*task_reparent_to_init) (struct task_struct * p);
void (*task_to_inode)(struct task_struct *p, struct inode *inode);
@@ -1471,12 +1454,6 @@ static inline int security_inode_permission (struct inode *inode, int mask)
return security_ops->inode_permission (inode, mask);
}
-static inline int security_inode_permission_lite (struct inode *inode,
- int mask)
-{
- return security_ops->inode_permission_lite (inode, mask);
-}
-
static inline int security_inode_setattr (struct dentry *dentry,
struct iattr *attr)
{
@@ -1692,11 +1669,6 @@ static inline int security_task_prctl (int option, unsigned long arg2,
return security_ops->task_prctl (option, arg2, arg3, arg4, arg5);
}
-static inline void security_task_kmod_set_label (void)
-{
- security_ops->task_kmod_set_label ();
-}
-
static inline void security_task_reparent_to_init (struct task_struct *p)
{
security_ops->task_reparent_to_init (p);
@@ -2108,12 +2080,6 @@ static inline int security_inode_permission (struct inode *inode, int mask)
return 0;
}
-static inline int security_inode_permission_lite (struct inode *inode,
- int mask)
-{
- return 0;
-}
-
static inline int security_inode_setattr (struct dentry *dentry,
struct iattr *attr)
{
@@ -2321,11 +2287,6 @@ static inline int security_task_prctl (int option, unsigned long arg2,
return 0;
}
-static inline void security_task_kmod_set_label (void)
-{
- cap_task_kmod_set_label ();
-}
-
static inline void security_task_reparent_to_init (struct task_struct *p)
{
cap_task_reparent_to_init (p);
diff --git a/init/main.c b/init/main.c
index e80b5d321abe..4774a4bee2fb 100644
--- a/init/main.c
+++ b/init/main.c
@@ -439,8 +439,8 @@ asmlinkage void __init start_kernel(void)
pte_chain_init();
fork_init(num_physpages);
proc_caches_init();
- security_scaffolding_startup();
buffer_init();
+ security_scaffolding_startup();
vfs_caches_init(num_physpages);
radix_tree_init();
signals_init();
diff --git a/kernel/sys.c b/kernel/sys.c
index eb3e920d557e..b7642b8a6a2c 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -831,13 +831,11 @@ asmlinkage long sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
asmlinkage long sys_setfsuid(uid_t uid)
{
int old_fsuid;
- int retval;
-
- retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
- if (retval)
- return retval;
old_fsuid = current->fsuid;
+ if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS))
+ return old_fsuid;
+
if (uid == current->uid || uid == current->euid ||
uid == current->suid || uid == current->fsuid ||
capable(CAP_SETUID))
@@ -850,9 +848,7 @@ asmlinkage long sys_setfsuid(uid_t uid)
current->fsuid = uid;
}
- retval = security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
- if (retval)
- return retval;
+ security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
return old_fsuid;
}
@@ -863,13 +859,11 @@ asmlinkage long sys_setfsuid(uid_t uid)
asmlinkage long sys_setfsgid(gid_t gid)
{
int old_fsgid;
- int retval;
-
- retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS);
- if (retval)
- return retval;
old_fsgid = current->fsgid;
+ if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
+ return old_fsgid;
+
if (gid == current->gid || gid == current->egid ||
gid == current->sgid || gid == current->fsgid ||
capable(CAP_SETGID))
diff --git a/mm/memory.c b/mm/memory.c
index e0dee2c62f5d..c95671289175 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -689,15 +689,16 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
vma = find_extend_vma(mm, start);
-#ifdef FIXADDR_START
- if (!vma && start >= FIXADDR_START && start < FIXADDR_TOP) {
+#ifdef FIXADDR_USER_START
+ if (!vma &&
+ start >= FIXADDR_USER_START && start < FIXADDR_USER_END) {
static struct vm_area_struct fixmap_vma = {
/* Catch users - if there are any valid
ones, we can make this be "&init_mm" or
something. */
.vm_mm = NULL,
- .vm_start = FIXADDR_START,
- .vm_end = FIXADDR_TOP,
+ .vm_start = FIXADDR_USER_START,
+ .vm_end = FIXADDR_USER_END,
.vm_page_prot = PAGE_READONLY,
.vm_flags = VM_READ | VM_EXEC,
};
@@ -705,6 +706,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
+ if (write) /* user fixmap pages are read-only */
+ return i ? : -EFAULT;
pgd = pgd_offset_k(pg);
if (!pgd)
return i ? : -EFAULT;
@@ -712,8 +715,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
if (!pmd)
return i ? : -EFAULT;
pte = pte_offset_kernel(pmd, pg);
- if (!pte || !pte_present(*pte) || !pte_user(*pte) ||
- !(write ? pte_write(*pte) : pte_read(*pte)))
+ if (!pte || !pte_present(*pte))
return i ? : -EFAULT;
if (pages) {
pages[i] = pte_page(*pte);
diff --git a/security/capability.c b/security/capability.c
index 02cb4112fce0..e2496a3f39ab 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -248,12 +248,6 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
return 0;
}
-void cap_task_kmod_set_label (void)
-{
- cap_set_full (current->cap_effective);
- return;
-}
-
void cap_task_reparent_to_init (struct task_struct *p)
{
p->cap_effective = CAP_INIT_EFF_SET;
@@ -278,7 +272,6 @@ EXPORT_SYMBOL(cap_capset_set);
EXPORT_SYMBOL(cap_bprm_set_security);
EXPORT_SYMBOL(cap_bprm_compute_creds);
EXPORT_SYMBOL(cap_task_post_setuid);
-EXPORT_SYMBOL(cap_task_kmod_set_label);
EXPORT_SYMBOL(cap_task_reparent_to_init);
EXPORT_SYMBOL(cap_syslog);
@@ -298,7 +291,6 @@ static struct security_operations capability_ops = {
.bprm_set_security = cap_bprm_set_security,
.task_post_setuid = cap_task_post_setuid,
- .task_kmod_set_label = cap_task_kmod_set_label,
.task_reparent_to_init = cap_task_reparent_to_init,
.syslog = cap_syslog,
@@ -348,7 +340,7 @@ static void __exit capability_exit (void)
}
}
-module_init (capability_init);
+security_initcall (capability_init);
module_exit (capability_exit);
MODULE_DESCRIPTION("Standard Linux Capabilities Security Module");
diff --git a/security/dummy.c b/security/dummy.c
index 4774b769a6de..18de8edb32c8 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -308,11 +308,6 @@ static int dummy_inode_permission (struct inode *inode, int mask)
return 0;
}
-static int dummy_inode_permission_lite (struct inode *inode, int mask)
-{
- return 0;
-}
-
static int dummy_inode_setattr (struct dentry *dentry, struct iattr *iattr)
{
return 0;
@@ -517,11 +512,6 @@ static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3,
return 0;
}
-static void dummy_task_kmod_set_label (void)
-{
- return;
-}
-
static void dummy_task_reparent_to_init (struct task_struct *p)
{
p->euid = p->fsuid = 0;
@@ -831,7 +821,6 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, inode_readlink);
set_to_dummy_if_null(ops, inode_follow_link);
set_to_dummy_if_null(ops, inode_permission);
- set_to_dummy_if_null(ops, inode_permission_lite);
set_to_dummy_if_null(ops, inode_setattr);
set_to_dummy_if_null(ops, inode_getattr);
set_to_dummy_if_null(ops, inode_delete);
@@ -871,7 +860,6 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, task_wait);
set_to_dummy_if_null(ops, task_kill);
set_to_dummy_if_null(ops, task_prctl);
- set_to_dummy_if_null(ops, task_kmod_set_label);
set_to_dummy_if_null(ops, task_reparent_to_init);
set_to_dummy_if_null(ops, task_to_inode);
set_to_dummy_if_null(ops, ipc_permission);
diff --git a/security/root_plug.c b/security/root_plug.c
index d705d43305c9..c683d6133321 100644
--- a/security/root_plug.c
+++ b/security/root_plug.c
@@ -94,7 +94,6 @@ static struct security_operations rootplug_security_ops = {
.bprm_set_security = cap_bprm_set_security,
.task_post_setuid = cap_task_post_setuid,
- .task_kmod_set_label = cap_task_kmod_set_label,
.task_reparent_to_init = cap_task_reparent_to_init,
.bprm_check_security = rootplug_bprm_check_security,
@@ -135,7 +134,7 @@ static void __exit rootplug_exit (void)
printk (KERN_INFO "Root Plug module removed\n");
}
-module_init (rootplug_init);
+security_initcall (rootplug_init);
module_exit (rootplug_exit);
MODULE_DESCRIPTION("Root Plug sample LSM module, written for Linux Journal article");
diff --git a/security/security.c b/security/security.c
index 4ea82dbc60b4..0fb1ad99cd3c 100644
--- a/security/security.c
+++ b/security/security.c
@@ -38,12 +38,22 @@ static inline int verify (struct security_operations *ops)
return 0;
}
+static void __init do_security_initcalls(void)
+{
+ initcall_t *call;
+ call = &__security_initcall_start;
+ while (call < &__security_initcall_end) {
+ (*call)();
+ call++;
+ }
+}
+
/**
* security_scaffolding_startup - initialzes the security scaffolding framework
*
* This should be called early in the kernel initialization sequence.
*/
-int security_scaffolding_startup (void)
+int __init security_scaffolding_startup (void)
{
printk (KERN_INFO "Security Scaffold v" SECURITY_SCAFFOLD_VERSION
" initialized\n");
@@ -55,6 +65,7 @@ int security_scaffolding_startup (void)
}
security_ops = &dummy_security_ops;
+ do_security_initcalls();
return 0;
}