Commit 92cabbc2 authored by Anton Altaparmakov's avatar Anton Altaparmakov

Merge cantab.net:/home/src/bklinux-2.6

into cantab.net:/home/src/ntfs-2.6-devel
parents ae3d2a18 f199195e
......@@ -100,8 +100,8 @@
<para>
I'd like to thank Jeff Garzik
<email>jgarzik@pobox.com</email> and Alexander Viro
<email>viro@math.psu.edu</email> for their input, Tim Waugh
<email>twaugh@redhat.com</email> for his <ulink
<email>viro@parcelfarce.linux.theplanet.co.uk</email> for their input,
Tim Waugh <email>twaugh@redhat.com</email> for his <ulink
url="http://people.redhat.com/twaugh/docbook/selfdocbook/">Selfdocbook</ulink>,
and Marc Joosen <email>marcj@historia.et.tudelft.nl</email> for
proofreading.
......
......@@ -82,7 +82,7 @@ lock might be used as follows for deletion and insertion:
list_for_each_entry(e, list, list) {
if (!audit_compare_rule(rule, &e->rule)) {
list_del(&e->list);
call_rcu(&e->rcu, audit_free_rule, e);
write_unlock(&auditsc_lock);
return 0;
}
}
......
......@@ -1632,7 +1632,7 @@ Changes for patch v177
- Fixed bugs in handling symlinks: could leak or cause Oops
- Cleaned up directory handling by separating fops
Thanks to Alexander Viro <viro@math.psu.edu>
Thanks to Alexander Viro <viro@parcelfarce.linux.theplanet.co.uk>
===============================================================================
Changes for patch v178
......
......@@ -701,7 +701,7 @@ running once the system is up.
[KNL,ACPI] Mark specific memory as reserved.
Region of memory to be used, from ss to ss+nn.
meye= [HW] Set MotionEye Camera parameters
meye.*= [HW] Set MotionEye Camera parameters
See Documentation/video4linux/meye.txt.
mga= [HW,DRM]
......@@ -866,6 +866,16 @@ running once the system is up.
order they are specified on the command
line, starting with parport0.
parport_init_mode=
[HW,PPT] Configure VIA parallel port to
operate in specific mode. This is
necessary on Pegasos computer where
firmware has no options for setting up
parallel port mode and sets it to
spp. Currently this function knows
686a and 8231 chips.
Format: [spp|ps2|epp|ecp|ecpepp]
pas2= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma16>,<sb_io>,<sb_irq>,<sb_dma>,<sb_dma16>
......@@ -1015,10 +1025,6 @@ running once the system is up.
New name for the ramdisk parameter.
See Documentation/ramdisk.txt.
ramdisk_start= [RAM] Starting block of RAM disk image (so you can
place it after the kernel image on a boot floppy).
See Documentation/ramdisk.txt.
reboot= [BUGS=IA-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
Format: <reboot_mode>[,<reboot_mode2>[,...]]
See arch/*/kernel/reboot.c.
......
The prio_tree.c code indexes vmas using 3 different indexes:
* heap_index = vm_pgoff + vm_size_in_pages : end_vm_pgoff
* radix_index = vm_pgoff : start_vm_pgoff
* size_index = vm_size_in_pages
A regular radix-priority-search-tree indexes vmas using only heap_index and
radix_index. The conditions for indexing are:
* ->heap_index >= ->left->heap_index &&
->heap_index >= ->right->heap_index
* if (->heap_index == ->left->heap_index)
then ->radix_index < ->left->radix_index;
* if (->heap_index == ->right->heap_index)
then ->radix_index < ->right->radix_index;
* nodes are hashed to left or right subtree using radix_index
similar to a pure binary radix tree.
A regular radix-priority-search-tree helps to store and query
intervals (vmas). However, a regular radix-priority-search-tree is only
suitable for storing vmas with different radix indices (vm_pgoff).
Therefore, the prio_tree.c extends the regular radix-priority-search-tree
to handle many vmas with the same vm_pgoff. Such vmas are handled in
2 different ways: 1) All vmas with the same radix _and_ heap indices are
linked using vm_set.list, 2) if there are many vmas with the same radix
index, but different heap indices and if the regular radix-priority-search
tree cannot index them all, we build an overflow-sub-tree that indexes such
vmas using heap and size indices instead of heap and radix indices. For
example, in the figure below some vmas with vm_pgoff = 0 (zero) are
indexed by regular radix-priority-search-tree whereas others are pushed
into an overflow-subtree. Note that all vmas in an overflow-sub-tree have
the same vm_pgoff (radix_index) and if necessary we build different
overflow-sub-trees to handle each possible radix_index. For example,
in figure we have 3 overflow-sub-trees corresponding to radix indices
0, 2, and 4.
In the final tree the first few (prio_tree_root->index_bits) levels
are indexed using heap and radix indices whereas the overflow-sub-trees below
those levels (i.e. levels prio_tree_root->index_bits + 1 and higher) are
indexed using heap and size indices. In overflow-sub-trees the size_index
is used for hashing the nodes to appropriate places.
Now, an example prio_tree:
vmas are represented [radix_index, size_index, heap_index]
i.e., [start_vm_pgoff, vm_size_in_pages, end_vm_pgoff]
level prio_tree_root->index_bits = 3
-----
_
0 [0,7,7] |
/ \ |
------------------ ------------ | Regular
/ \ | radix priority
1 [1,6,7] [4,3,7] | search tree
/ \ / \ |
------- ----- ------ ----- | heap-and-radix
/ \ / \ | indexed
2 [0,6,6] [2,5,7] [5,2,7] [6,1,7] |
/ \ / \ / \ / \ |
3 [0,5,5] [1,5,6] [2,4,6] [3,4,7] [4,2,6] [5,1,6] [6,0,6] [7,0,7] |
/ / / _
/ / / _
4 [0,4,4] [2,3,5] [4,1,5] |
/ / / |
5 [0,3,3] [2,2,4] [4,0,4] | Overflow-sub-trees
/ / |
6 [0,2,2] [2,1,3] | heap-and-size
/ / | indexed
7 [0,1,1] [2,0,2] |
/ |
8 [0,0,0] |
_
Note that we use prio_tree_root->index_bits to optimize the height
of the heap-and-radix indexed tree. Since prio_tree_root->index_bits is
set according to the maximum end_vm_pgoff mapped, we are sure that all
bits (in vm_pgoff) above prio_tree_root->index_bits are 0 (zero). Therefore,
we only use the first prio_tree_root->index_bits as radix_index.
Whenever index_bits is increased in prio_tree_expand, we shuffle the tree
to make sure that the first prio_tree_root->index_bits levels of the tree
is indexed properly using heap and radix indices.
We do not optimize the height of overflow-sub-trees using index_bits.
The reason is: there can be many such overflow-sub-trees and all of
them have to be suffled whenever the index_bits increases. This may involve
walking the whole prio_tree in prio_tree_insert->prio_tree_expand code
path which is not desirable. Hence, we do not optimize the height of the
heap-and-size indexed overflow-sub-trees using prio_tree->index_bits.
Instead the overflow sub-trees are indexed using full BITS_PER_LONG bits
of size_index. This may lead to skewed sub-trees because most of the
higher significant bits of the size_index are likely to be be 0 (zero). In
the example above, all 3 overflow-sub-trees are skewed. This may marginally
affect the performance. However, processes rarely map many vmas with the
same start_vm_pgoff but different end_vm_pgoffs. Therefore, we normally
do not require overflow-sub-trees to index all vmas.
From the above discussion it is clear that the maximum height of
a prio_tree can be prio_tree_root->index_bits + BITS_PER_LONG.
However, in most of the common cases we do not need overflow-sub-trees,
so the tree height in the common cases will be prio_tree_root->index_bits.
It is fair to mention here that the prio_tree_root->index_bits
is increased on demand, however, the index_bits is not decreased when
vmas are removed from the prio_tree. That's tricky to do. Hence, it's
left as a home work problem.
Sony Programmable I/O Control Device Driver Readme
--------------------------------------------------
Copyright (C) 2001-2003 Stelian Pop <stelian@popies.net>
Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
Copyright (C) 2001-2002 Alcôve <www.alcove.com>
Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp>
......@@ -23,10 +23,12 @@ generate, like:
Those events (see linux/sonypi.h) can be polled using the character device node
/dev/sonypi (major 10, minor auto allocated or specified as a option).
A simple daemon which translates the jogdial movements into mouse wheel events
can be downloaded at: <http://popies.net/sonypi/>
Another option to intercept the events is to get them directly through the
input layer.
This driver supports also some ioctl commands for setting the LCD screen
brightness and querying the batteries charge information (some more
commands may be added in the future).
......@@ -75,14 +77,15 @@ statically linked into the kernel). Those options are:
add this option and report to the author.
mask: event mask telling the driver what events will be
reported to the user. This parameter is required for some
Vaio models where the hardware reuses values used in
other Vaio models (like the FX series who does not
have a jogdial but reuses the jogdial events for
reported to the user. This parameter is required for
some Vaio models where the hardware reuses values
used in other Vaio models (like the FX series who does
not have a jogdial but reuses the jogdial events for
programmable keys events). The default event mask is
set to 0xffffffff, meaning that all possible events will be
tried. You can use the following bits to construct
your own event mask (from drivers/char/sonypi.h):
set to 0xffffffff, meaning that all possible events
will be tried. You can use the following bits to
construct your own event mask (from
drivers/char/sonypi.h):
SONYPI_JOGGER_MASK 0x0001
SONYPI_CAPTURE_MASK 0x0002
SONYPI_FNKEY_MASK 0x0004
......@@ -97,10 +100,10 @@ statically linked into the kernel). Those options are:
SONYPI_MEMORYSTICK_MASK 0x0800
SONYPI_BATTERY_MASK 0x1000
useinput: if set (which is the default) jogdial events are
forwarded to the input subsystem as mouse wheel
events.
useinput: if set (which is the default) two input devices are
created, one which interprets the jogdial events as
mouse events, the other one which acts like a
keyboard reporting the pressing of the special keys.
Module use:
-----------
......
......@@ -4,7 +4,7 @@
Author: Romain Lievin
Homepage: http://lpg.ticalc.org/prj_dev
Homepage: http://lpg.ticalc.org/prj_tidev/index.html
INTRODUCTION:
......@@ -12,31 +12,30 @@ INTRODUCTION:
This is a driver for the very common home-made parallel link cable, a cable
designed for connecting TI8x/9x graphing calculators (handhelds) to a computer
or workstation (Alpha, Sparc). Given that driver is built on parport, the
parallel port abstraction layer, this driver is independent of the platform.
parallel port abstraction layer, this driver is architecture-independent.
It can also be used with another device plugged on the same port (such as a
ZIP drive). I have a 100MB ZIP and both of them work fine !
ZIP drive). I have a 100MB ZIP and both of them work fine!
If you need more information, please visit the 'TI drivers' homepage at the URL
above.
WHAT YOU NEED:
A TI calculator of course and a program capable to communicate with your
calculator.
TiLP will work for sure (since I am his developer !). yal92 may be able to use
A TI calculator and a program capable of communicating with your calculator.
TiLP will work for sure (since I am its developer!). yal92 may be able to use
it by changing tidev for tipar (may require some hacking...).
HOW TO USE IT:
You must have first compiled parport support (CONFIG_PARPORT_DEV): either
compiled in your kernel, either as a module.
This driver supports the new device hierarchy (devfs).
Next, (as root) from your appropriate modules directory (lib/modules/2.5.XX):
Next, (as root):
modprobe parport
insmod tipar.o
modprobe tipar
If it is not already there (it usually is), create the device:
......@@ -47,14 +46,14 @@ If it is not already there (it usually is), create the device:
You will have to set permissions on this device to allow you to read/write
from it:
chmod 666 /dev/tipar?
chmod 666 /dev/tipar[0..2]
Now you are ready to run a linking program such as TiLP. Be sure to configure
it properly (RTFM).
MODULE PARAMETERS:
You can set these with: insmod tipar NAME=VALUE
You can set these with: modprobe tipar NAME=VALUE
There is currently no way to set these on a per-cable basis.
NAME: timeout
......@@ -66,11 +65,12 @@ MODULE PARAMETERS:
NAME: delay
TYPE: integer
DEFAULT: 10
DESC: Inter-bit delay in micro-seconds. An lower value gives an higher data
DESC: Inter-bit delay in micro-seconds. A lower value gives an higher data
rate but makes transmission less reliable.
These parameters can be changed at run time by any program via ioctl(2) calls
as listed in ./include/linux/ticable.h
as listed in ./include/linux/ticable.h.
Rather than write 50 pages describing the ioctl() and so on, it is
perhaps more useful you look at ticables library (dev_link.c) that demonstrates
how to use them, and demonstrates the features of the driver. This is
......
Vaio Picturebook Motion Eye Camera Driver Readme
------------------------------------------------
Copyright (C) 2001-2003 Stelian Pop <stelian@popies.net>
Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
Copyright (C) 2001-2002 Alcôve <www.alcove.com>
Copyright (C) 2000 Andrew Tridgell <tridge@samba.org>
......@@ -41,13 +41,12 @@ little information if any is available for this camera
Driver options:
---------------
Several options can be passed to the meye driver, either by adding them
to /etc/modprobe.conf file, when the driver is compiled as a module, or
by adding the following to the kernel command line (in your bootloader):
Several options can be passed to the meye driver using the standard
module argument syntax (<param>=<value> when passing the option to the
module or meye.<param>=<value> on the kernel boot line when meye is
statically linked into the kernel). Those options are:
meye=gbuffers[,gbufsize[,video_nr]]
where:
forcev4l1: force use of V4L1 API instead of V4L2
gbuffers: number of capture buffers, default is 2 (32 max)
......@@ -81,8 +80,9 @@ Usage:
Private API:
------------
The driver supports frame grabbing with the video4linux API, so
all video4linux tools (like xawtv) should work with this driver.
The driver supports frame grabbing with the video4linux API
(either v4l1 or v4l2), so all video4linux tools (like xawtv)
should work with this driver.
Besides the video4linux interface, the driver has a private interface
for accessing the Motion Eye extended parameters (camera sharpness,
......@@ -124,13 +124,7 @@ Private API:
Bugs / Todo:
------------
- overlay output is not supported (although the camera is capable of).
(it should not be too hard to to it, provided we found how...)
- mjpeg hardware playback doesn't work (depends on overlay...)
- the driver could be much cleaned up by removing the v4l1 support.
However, this means all v4l1-only applications will stop working.
- rewrite the driver to use some common video4linux API for snapshot
and mjpeg capture. Unfortunately, video4linux1 does not permit it,
the BUZ API seems to be targeted to TV cards only. The video4linux 2
API may be an option, if it goes into the kernel (maybe 2.5
material ?).
- 'motioneye' still uses the meye private v4l1 API extensions.
......@@ -831,7 +831,7 @@ S: Maintained
FILESYSTEMS (VFS and infrastructure)
P: Alexander Viro
M: viro@math.psu.edu
M: viro@parcelfarce.linux.theplanet.co.uk
S: Maintained
FIRMWARE LOADER (request_firmware)
......
......@@ -12,6 +12,7 @@
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/serial_8250.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
......@@ -313,6 +314,55 @@ static struct clps7500_timer = {
.offset = ioc_timer_gettimeoffset,
};
static struct plat_serial8250_port serial_platform_data[] = {
{
.mapbase = 0x03010fe0,
.irq = 10,
.uartclk = 1843200,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST,
},
{
.mapbase = 0x03010be0,
.irq = 0,
.uartclk = 1843200,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST,
},
{
.iobase = ISASLOT_IO + 0x2e8,
.irq = 41,
.uartclk = 1843200,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{
.iobase = ISASLOT_IO + 0x3e8,
.irq = 40,
.uartclk = 1843200,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{ },
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = 0,
.dev = {
.platform_data = serial_platform_data,
},
};
static int __init clps7500_init(void)
{
return platform_register_device(&serial_device);
}
MACHINE_START(CLPS7500, "CL-PS7500")
MAINTAINER("Philip Blundell")
BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
......
......@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/serial_8250.h>
#include <linux/init.h>
#include <asm/hardware.h>
......@@ -196,6 +197,41 @@ static struct sys_timer ebsa110_timer = {
.offset = ebsa110_gettimeoffset,
};
static struct plat_serial8250_port serial_platform_data[] = {
{
.iobase = 0x3f8,
.irq = 1,
.uartclk = 1843200,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{
.iobase = 0x2f8,
.irq = 2,
.uartclk = 1843200,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{ },
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = 0,
.dev = {
.platform_data = serial_platform_data,
},
};
static int __init ebsa110_init(void)
{
return platform_device_register(&serial_device);
}
arch_initcall(ebsa110_init);
MACHINE_START(EBSA110, "EBSA110")
MAINTAINER("Russell King")
BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000)
......
......@@ -20,6 +20,7 @@
*/
#include <linux/types.h>
#include <linux/init.h>
#include <linux/serial_8250.h>
#include <asm/hardware.h>
#include <asm/setup.h>
......@@ -27,6 +28,36 @@
#include <asm/mach/arch.h>
static struct plat_serial8250_port serial_platform_data[] = {
{
.iobase = 0x3f8,
.irq = IRQ_UARTINT0,
#error FIXME
.uartclk = 0,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{
.iobase = 0x2f8,
.irq = IRQ_UARTINT1,
#error FIXME
.uartclk = 0,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{ },
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = 0,
.dev = {
.platform_data = serial_platform_data,
},
};
extern void epxa10db_map_io(void);
extern void epxa10db_init_irq(void);
extern struct sys_timer epxa10db_timer;
......
......@@ -26,3 +26,5 @@ obj-$(CONFIG_ARCH_PERSONAL_SERVER) += personal.o dc21285-timer.o
obj-$(CONFIG_PCI) +=$(pci-y)
obj-$(CONFIG_LEDS) +=$(leds-y)
obj-$(CONFIG_ISA) += isa.o
/*
* linux/arch/arm/mach-footbridge/isa.c
*
* Copyright (C) 2004 Russell King.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/serial_8250.h>
#include <asm/irq.h>
static struct plat_serial8250_port serial_platform_data[] = {
{
.iobase = 0x3f8,
.irq = IRQ_ISA_UART,
.uartclk = 1843200,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{
.iobase = 0x2f8,
.irq = IRQ_ISA_UART2,
.uartclk = 1843200,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{ },
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = 0,
.dev = {
.platform_data = serial_platform_data,
},
};
static int __init footbridge_isa_init(void)
{
return platform_device_register(&serial_device);
}
arch_initcall(footbridge_isa_init);
/*
* linux/arch/arm/mach-h720x/common.h
*
* Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
* 2003 Robert Schwebel <r.schwebel@pengutronix.de>
* 2004 Sascha Hauer <s.hauer@pengutronix.de>
*
* Architecture specific stuff for Hynix GMS30C7201 development board
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
extern unsigned long h720x_gettimeoffset(void);
extern void __init h720x_init_irq (void);
extern void __init h720x_map_io(void);
#ifdef CONFIG_ARCH_H7202
extern struct sys_timer h7202_timer;
extern void __init init_hw_h7202(void);
extern void __init h7202_init_irq (void);
extern void __init h7202_init_time(void);
#endif
#ifdef CONFIG_ARCH_H7201
extern struct sys_timer h7201_timer;
#endif
......@@ -22,10 +22,7 @@
#include <asm/arch/irqs.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
extern unsigned long h720x_gettimeoffset(void);
extern void __init h720x_init_irq (void);
#include "common.h"
/*
* Timer interrupt handler
*/
......@@ -53,8 +50,6 @@ static struct irqaction h7201_timer_irq = {
*/
void __init h7201_init_time(void)
{
gettimeoffset = h720x_gettimeoffset;
CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
......@@ -62,3 +57,8 @@ void __init h7201_init_time(void)
setup_irq(IRQ_TIMER0, &h7201_timer_irq);
}
struct sys_timer h7201_timer = {
.init = h7201_init_time,
.offset = h720x_gettimeoffset,
};
......@@ -23,6 +23,8 @@
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <linux/device.h>
#include <linux/serial_8250.h>
#include "common.h"
static struct resource h7202ps2_resources[] = {
[0] = {
......@@ -44,13 +46,55 @@ static struct platform_device h7202ps2_device = {
.resource = h7202ps2_resources,
};
static struct plat_serial8250_port serial_platform_data[] = {
{
.membase = SERIAL0_BASE,
.irq = IRQ_UART0,
.uartclk = 2*1843200,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{
.membase = SERIAL1_BASE,
.irq = IRQ_UART1,
.uartclk = 2*1843200,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{
.membase = SERIAL2_BASE,
.irq = IRQ_UART2,
.uartclk = 2*1843200,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{
.membase = SERIAL3_BASE,
.irq = IRQ_UART3,
.uartclk = 2*1843200,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{ },
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = 0,
.dev = {
.platform_data = serial_platform_data,
},
};
static struct platform_device *devices[] __initdata = {
&h7202ps2_device,
&serial_device,
};
extern unsigned long h720x_gettimeoffset(void);
extern void __init h720x_init_irq (void);
/* Although we have two interrupt lines for the timers, we only have one
* status register which clears all pending timer interrupts on reading. So
* we have to handle all timer interrupts in one place.
......@@ -130,8 +174,6 @@ static struct irqaction h7202_timer_irq = {
*/
void __init h7202_init_time(void)
{
gettimeoffset = h720x_gettimeoffset;
CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
......@@ -140,6 +182,11 @@ void __init h7202_init_time(void)
setup_irq(IRQ_TIMER0, &h7202_timer_irq);
}
struct sys_timer h7202_timer = {
.init = h7202_init_time,
.offset = h720x_gettimeoffset,
};
void __init h7202_init_irq (void)
{
int irq;
......
......@@ -27,10 +27,7 @@
#include <asm/pgtable.h>
#include <asm/mach/arch.h>
#include <asm/hardware.h>
extern void h720x_init_irq (void);
extern void h7201_init_time(void);
extern void __init h720x_map_io(void);
#include "common.h"
MACHINE_START(H7201, "Hynix GMS30C7201")
MAINTAINER("Robert Schwebel, Pengutronix")
......@@ -38,5 +35,5 @@ MACHINE_START(H7201, "Hynix GMS30C7201")
BOOT_PARAMS(0xc0001000)
MAPIO(h720x_map_io)
INITIRQ(h720x_init_irq)
INITTIME(h7201_init_time)
.timer = &h7201_timer,
MACHINE_END
......@@ -27,11 +27,7 @@
#include <asm/pgtable.h>
#include <asm/mach/arch.h>
#include <asm/hardware.h>
extern void __init init_hw_h7202(void);
extern void __init h7202_init_irq (void);
extern void __init h7202_init_time(void);
extern void __init h720x_map_io(void);
#include "common.h"
static struct resource cirrus_resources[] = {
[0] = {
......@@ -80,6 +76,6 @@ MACHINE_START(H7202, "Hynix HMS30C7202")
BOOT_PARAMS(0x40000100)
MAPIO(h720x_map_io)
INITIRQ(h7202_init_irq)
INITTIME(h7202_init_time)
.timer = &h7202_timer,
INIT_MACHINE(init_eval_h7202)
MACHINE_END
......@@ -16,7 +16,7 @@
#include <linux/console.h>
#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
#include <asm/hardware.h>
......@@ -307,34 +307,36 @@ void omap_map_io(void)
_omap_map_io();
}
static inline unsigned int omap_serial_in(struct uart_port *up, int offset)
static inline unsigned int omap_serial_in(struct plat_serial8250_port *up,
int offset)
{
offset <<= up->regshift;
return (unsigned int)__raw_readb(up->membase + offset);
}
static inline void omap_serial_outp(struct uart_port *up, int offset, int value)
static inline void omap_serial_outp(struct plat_serial8250_port *p, int offset,
int value)
{
offset <<= up->regshift;
__raw_writeb(value, up->membase + offset);
offset <<= p->regshift;
__raw_writeb(value, p->membase + offset);
}
/*
* Internal UARTs need to be initialized for the 8250 autoconfig to work
* properly.
*/
static void __init omap_serial_reset(struct uart_port *up)
static void __init omap_serial_reset(struct plat_serial8250_port *p)
{
omap_serial_outp(up, UART_OMAP_MDR1, 0x07); /* disable UART */
omap_serial_outp(up, UART_OMAP_MDR1, 0x00); /* enable UART */
omap_serial_outp(p, UART_OMAP_MDR1, 0x07); /* disable UART */
omap_serial_outp(p, UART_OMAP_MDR1, 0x00); /* enable UART */
if (!cpu_is_omap1510()) {
omap_serial_outp(up, UART_OMAP_SYSC, 0x01);
while (!(omap_serial_in(up, UART_OMAP_SYSC) & 0x01));
omap_serial_outp(p, UART_OMAP_SYSC, 0x01);
while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01));
}
}
static struct uart_port omap_serial_ports[] = {
static struct plat_serial8250_port serial_platform_data[] = {
{
.membase = (char*)IO_ADDRESS(OMAP_UART1_BASE),
.mapbase = (unsigned long)OMAP_UART1_BASE,
......@@ -343,10 +345,8 @@ static struct uart_port omap_serial_ports[] = {
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = OMAP16XX_BASE_BAUD * 16,
.line = 0,
.type = PORT_16654,
.fifosize = 64
} , {
},
{
.membase = (char*)IO_ADDRESS(OMAP_UART2_BASE),
.mapbase = (unsigned long)OMAP_UART2_BASE,
.irq = INT_UART2,
......@@ -354,10 +354,8 @@ static struct uart_port omap_serial_ports[] = {
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = OMAP16XX_BASE_BAUD * 16,
.line = 1,
.type = PORT_16654,
.fifosize = 64
} , {
},
{
.membase = (char*)IO_ADDRESS(OMAP_UART3_BASE),
.mapbase = (unsigned long)OMAP_UART3_BASE,
.irq = INT_UART3,
......@@ -365,10 +363,16 @@ static struct uart_port omap_serial_ports[] = {
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = OMAP16XX_BASE_BAUD * 16,
.line = 2,
.type = PORT_16654,
.fifosize = 64
}
},
{ },
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = 0,
.dev = {
.platform_data = serial_platform_data,
},
};
/*
......@@ -381,23 +385,26 @@ void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS])
int i;
if (cpu_is_omap730()) {
omap_serial_ports[0].regshift = 0;
omap_serial_ports[1].regshift = 0;
omap_serial_ports[0].irq = INT_730_UART_MODEM_1;
omap_serial_ports[1].irq = INT_730_UART_MODEM_IRDA_2;
serial_platform_data[0].regshift = 0;
serial_platform_data[1].regshift = 0;
serial_platform_data[0].irq = INT_730_UART_MODEM_1;
serial_platform_data[1].irq = INT_730_UART_MODEM_IRDA_2;
}
if (cpu_is_omap1510()) {
omap_serial_ports[0].uartclk = OMAP1510_BASE_BAUD * 16;
omap_serial_ports[1].uartclk = OMAP1510_BASE_BAUD * 16;
omap_serial_ports[2].uartclk = OMAP1510_BASE_BAUD * 16;
serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16;
serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16;
serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16;
}
for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
unsigned char reg;
if (ports[i] != 1)
if (ports[i] == 0) {
serial_platform_data[i].membase = 0;
serial_platform_data[i].mapbase = 0;
continue;
}
switch (i) {
case 0:
......@@ -431,11 +438,16 @@ void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS])
}
break;
}
omap_serial_reset(&omap_serial_ports[i]);
early_serial_setup(&omap_serial_ports[i]);
omap_serial_reset(&serial_platform_data[i]);
}
}
static int __init omap_init(void)
{
return platform_device_register(&serial_device);
}
arch_initcall(omap_init);
#define NO_LENGTH_CHECK 0xffffffff
extern int omap_bootloader_tag_len;
......
......@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/serial_8250.h>
#include <asm/elf.h>
#include <asm/io.h>
......@@ -130,9 +131,30 @@ static struct platform_device kbd_device = {
},
};
static struct plat_serial8250_port serial_platform_data[] = {
{
.mapbase = 0x03010fe0,
.irq = 10,
.uartclk = 1843200,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST,
},
{ },
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = 0,
.dev = {
.platform_data = serial_platform_data,
},
};
static struct platform_device *devs[] __initdata = {
&iomd_device,
&kbd_device,
&serial_device,
&acornfb_device,
};
......
......@@ -20,6 +20,7 @@
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/serial_8250.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
......@@ -32,9 +33,6 @@
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm/mach/serial_sa1100.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <asm/arch/serial.h>
#include <asm/io.h>
#include <asm/irq.h>
......@@ -178,6 +176,34 @@ static void trizeps_power_off(void)
PMCR = PMCR_SF;
}
static struct plat_serial8250_port serial_platform_data[] = {
{
.mapbase = TRIZEPS_UART5,
.irq = IRQ_GPIO16,
.uartclk = 24000000,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{
.mapbase = TRIZEPS_UART6,
.irq = IRQ_GPIO17,
.uartclk = 24000000,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{ },
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = 0,
.dev = {
.platform_data = serial_platform_data,
},
};
static int __init trizeps_init(void)
{
if (!machine_is_trizeps())
......@@ -201,6 +227,8 @@ static int __init trizeps_init(void)
set_irq_type(IRQ_GPIO16, IRQT_RISING);
set_irq_type(IRQ_GPIO17, IRQT_RISING);
platform_device_register(&serial_device);
return 0;
}
......
......@@ -7,6 +7,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/serial_8250.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
......@@ -18,6 +19,46 @@
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
static struct plat_serial8250_port serial_platform_data[] = {
{
.iobase = 0x3f8,
.irq = 4,
.uartclk = 1843200,
.regshift = 2,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{
.iobase = 0x2f8,
.irq = 3,
.uartclk = 1843200,
.regshift = 2,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{ },
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = 0,
.dev = {
.platform_data = serial_platform_data,
},
};
static int __init shark_init(void)
{
int ret;
if (machine_is_shark())
ret = platform_device_register(&serial_device);
return ret;
}
arch_initcall(shark_init);
extern void shark_init_irq(void);
static struct map_desc shark_io_desc[] __initdata = {
......
......@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk
#
# Last update: Thu Sep 30 15:23:21 2004
# Last update: Sun Nov 7 13:20:41 2004
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
......@@ -595,8 +595,8 @@ pxa_dnp2110 MACH_PXA_DNP2110 PXA_DNP2110 584
xaeniax MACH_XAENIAX XAENIAX 585
somn4250 MACH_SOMN4250 SOMN4250 586
pleb2 MACH_PLEB2 PLEB2 587
cwl MACH_CWL CWL 588
gd MACH_GD GD 589
cornwallis MACH_CORNWALLIS CORNWALLIS 588
gurney_drv MACH_GURNEY_DRV GURNEY_DRV 589
chaffee MACH_CHAFFEE CHAFFEE 590
rms101 MACH_RMS101 RMS101 591
rx3715 MACH_RX3715 RX3715 592
......@@ -615,3 +615,22 @@ ixdpg425 MACH_IXDPG425 IXDPG425 604
tomtomgo MACH_TOMTOMGO TOMTOMGO 605
versatile_ab MACH_VERSATILE_AB VERSATILE_AB 606
edb9307 MACH_EDB9307 EDB9307 607
sg565 MACH_SG565 SG565 608
lpd79524 MACH_LPD79524 LPD79524 609
lpd79525 MACH_LPD79525 LPD79525 610
rms100 MACH_RMS100 RMS100 611
kb9200 MACH_KB9200 KB9200 612
sx1 MACH_SX1 SX1 613
hms39c7092 MACH_HMS39C7092 HMS39C7092 614
armadillo MACH_ARMADILLO ARMADILLO 615
ipcu MACH_IPCU IPCU 616
loox720 MACH_LOOX720 LOOX720 617
ixdp465 MACH_IXDP465 IXDP465 618
ixdp2351 MACH_IXDP2351 IXDP2351 619
adsvix MACH_ADSVIX ADSVIX 620
dm270 MACH_DM270 DM270 621
socltplus MACH_SOCLTPLUS SOCLTPLUS 622
ecia MACH_ECIA ECIA 623
cm4008 MACH_CM4008 CM4008 624
p2001 MACH_P2001 P2001 625
twister MACH_TWISTER TWISTER 626
......@@ -689,7 +689,7 @@ static int __init detect_init_APIC (void)
u32 h, l, features;
extern void get_cpu_vendor(struct cpuinfo_x86*);
/* Disabled by DMI scan or kernel option? */
/* Disabled by kernel option? */
if (enable_local_apic < 0)
return -1;
......@@ -703,8 +703,7 @@ static int __init detect_init_APIC (void)
break;
goto no_apic;
case X86_VENDOR_INTEL:
if (boot_cpu_data.x86 == 6 ||
(boot_cpu_data.x86 == 15 && (cpu_has_apic || enable_local_apic > 0)) ||
if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||
(boot_cpu_data.x86 == 5 && cpu_has_apic))
break;
goto no_apic;
......@@ -714,15 +713,20 @@ static int __init detect_init_APIC (void)
if (!cpu_has_apic) {
/*
* Over-ride BIOS and try to enable LAPIC
* only if "lapic" specified
* Over-ride BIOS and try to enable the local
* APIC only if "lapic" specified.
*/
if (enable_local_apic != 1)
goto no_apic;
if (enable_local_apic <= 0) {
apic_printk(APIC_VERBOSE,
"Local APIC disabled by BIOS -- "
"you can enable it with \"lapic\"\n");
return -1;
}
/*
* Some BIOSes disable the local APIC in the
* APIC_BASE MSR. This can only be done in
* software for Intel P6 and AMD K7 (Model > 1).
* software for Intel P6 or later and AMD K7
* (Model > 1) or later.
*/
rdmsr(MSR_IA32_APICBASE, l, h);
if (!(l & MSR_IA32_APICBASE_ENABLE)) {
......
......@@ -42,6 +42,7 @@ static struct pt_regs jprobe_saved_regs;
static long *jprobe_saved_esp;
/* copy of the kernel stack at the probe fire time */
static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
void jprobe_return_end(void);
/*
* returns non-zero if opcode modifies the interrupt flag.
......@@ -58,9 +59,14 @@ static inline int is_IF_modifier(kprobe_opcode_t opcode)
return 0;
}
void arch_prepare_kprobe(struct kprobe *p)
int arch_prepare_kprobe(struct kprobe *p)
{
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
return 0;
}
void arch_remove_kprobe(struct kprobe *p)
{
memcpy(p->insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
}
static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
......@@ -73,7 +79,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK;
regs->eip = (unsigned long)&p->insn;
regs->eip = (unsigned long)&p->ainsn.insn;
}
/*
......@@ -153,7 +159,7 @@ static inline int kprobe_handler(struct pt_regs *regs)
* instruction. To avoid the SMP problems that can occur when we
* temporarily put back the original opcode to single-step, we
* single-stepped a copy of the instruction. The address of this
* copy is p->insn.
* copy is p->ainsn.insn.
*
* This function prepares to return from the post-single-step
* interrupt. We have to fix up the stack as follows:
......@@ -173,10 +179,10 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs)
{
unsigned long *tos = (unsigned long *)&regs->esp;
unsigned long next_eip = 0;
unsigned long copy_eip = (unsigned long)&p->insn;
unsigned long copy_eip = (unsigned long)&p->ainsn.insn;
unsigned long orig_eip = (unsigned long)p->addr;
switch (p->insn[0]) {
switch (p->ainsn.insn[0]) {
case 0x9c: /* pushfl */
*tos &= ~(TF_MASK | IF_MASK);
*tos |= kprobe_old_eflags;
......@@ -185,13 +191,13 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs)
*tos = orig_eip + (*tos - copy_eip);
break;
case 0xff:
if ((p->insn[1] & 0x30) == 0x10) {
if ((p->ainsn.insn[1] & 0x30) == 0x10) {
/* call absolute, indirect */
/* Fix return addr; eip is correct. */
next_eip = regs->eip;
*tos = orig_eip + (*tos - copy_eip);
} else if (((p->insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
((p->insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */
} else if (((p->ainsn.insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
((p->ainsn.insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */
/* eip is correct. */
next_eip = regs->eip;
}
......@@ -315,12 +321,12 @@ void jprobe_return(void)
{
preempt_enable_no_resched();
asm volatile (" xchgl %%ebx,%%esp \n"
" int3 \n"::"b"
" int3 \n"
" .globl jprobe_return_end \n"
" jprobe_return_end: \n"
" nop \n"::"b"
(jprobe_saved_esp):"memory");
}
void jprobe_return_end(void)
{
};
int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
......
......@@ -344,6 +344,36 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if(addr < (long) &dummy->u_debugreg[4] &&
((unsigned long) data) >= TASK_SIZE-3) break;
/* Sanity-check data. Take one half-byte at once with
* check = (val >> (16 + 4*i)) & 0xf. It contains the
* R/Wi and LENi bits; bits 0 and 1 are R/Wi, and bits
* 2 and 3 are LENi. Given a list of invalid values,
* we do mask |= 1 << invalid_value, so that
* (mask >> check) & 1 is a correct test for invalid
* values.
*
* R/Wi contains the type of the breakpoint /
* watchpoint, LENi contains the length of the watched
* data in the watchpoint case.
*
* The invalid values are:
* - LENi == 0x10 (undefined), so mask |= 0x0f00.
* - R/Wi == 0x10 (break on I/O reads or writes), so
* mask |= 0x4444.
* - R/Wi == 0x00 && LENi != 0x00, so we have mask |=
* 0x1110.
*
* Finally, mask = 0x0f00 | 0x4444 | 0x1110 == 0x5f54.
*
* See the Intel Manual "System Programming Guide",
* 15.2.4
*
* Note that LENi == 0x10 is defined on x86_64 in long
* mode (i.e. even for 32-bit userspace software, but
* 64-bit kernel), so the x86_64 mask value is 0x5454.
* See the AMD manual no. 24593 (AMD64 System
* Programming)*/
if(addr == (long) &dummy->u_debugreg[7]) {
data &= ~DR_CONTROL_RESERVED;
for(i=0; i<4; i++)
......
......@@ -583,7 +583,11 @@ void die_nmi (struct pt_regs *regs, const char *msg)
static void default_do_nmi(struct pt_regs * regs)
{
unsigned char reason = get_nmi_reason();
unsigned char reason = 0;
/* Only the BSP gets external NMIs from the system. */
if (!smp_processor_id())
reason = get_nmi_reason();
if (!(reason & 0xc0)) {
if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
......
......@@ -208,7 +208,6 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
*/
__flush_tlb_all();
}
EXPORT_SYMBOL(kernel_map_pages);
#endif
EXPORT_SYMBOL(change_page_attr);
......
......@@ -15,7 +15,7 @@
#include <asm/io.h>
#include <asm/byteorder.h>
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
#include <linux/types.h>
#define M32R_PCC_IOMAP_SIZE 0x1000
......@@ -27,7 +27,7 @@
extern void pcc_ioread(int, unsigned long, void *, size_t, size_t, int);
extern void pcc_iowrite(int, unsigned long, void *, size_t, size_t, int);
#endif /* CONFIG_PCMCIA && CONFIG_M32RPCC */
#endif /* CONFIG_PCMCIA && CONFIG_M32R_PCC */
#define PORT2ADDR(port) _port2addr(port)
......@@ -80,7 +80,7 @@ unsigned char _inb(unsigned long port)
if (port >= 0x300 && port < 0x320)
return _ne_inb(PORT2ADDR_NE(port));
else
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
unsigned char b;
pcc_ioread(0, port, &b, sizeof(b), 1, 0);
......@@ -100,7 +100,7 @@ unsigned short _inw(unsigned long port)
if (port >= 0x300 && port < 0x320)
return _ne_inw(PORT2ADDR_NE(port));
else
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
unsigned short w;
pcc_ioread(0, port, &w, sizeof(w), 1, 0);
......@@ -116,7 +116,7 @@ unsigned short _inw(unsigned long port)
unsigned long _inl(unsigned long port)
{
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
unsigned long l;
pcc_ioread(0, port, &l, sizeof(l), 1, 0);
......@@ -137,7 +137,7 @@ unsigned char _inb_p(unsigned long port)
if (port >= 0x300 && port < 0x320)
v = _ne_inb(PORT2ADDR_NE(port));
else
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
unsigned char b;
pcc_ioread(0, port, &b, sizeof(b), 1, 0);
......@@ -161,7 +161,7 @@ unsigned short _inw_p(unsigned long port)
if (port >= 0x300 && port < 0x320)
v = _ne_inw(PORT2ADDR_NE(port));
else
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
unsigned short w;
pcc_ioread(0, port, &w, sizeof(w), 1, 0);
......@@ -192,7 +192,7 @@ void _outb(unsigned char b, unsigned long port)
if (port >= 0x300 && port < 0x320)
_ne_outb(b, PORT2ADDR_NE(port));
else
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_iowrite(0, port, &b, sizeof(b), 1, 0);
} else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
......@@ -207,7 +207,7 @@ void _outw(unsigned short w, unsigned long port)
if (port >= 0x300 && port < 0x320)
_ne_outw(w, PORT2ADDR_NE(port));
else
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_iowrite(0, port, &w, sizeof(w), 1, 0);
} else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
......@@ -219,7 +219,7 @@ void _outw(unsigned short w, unsigned long port)
void _outl(unsigned long l, unsigned long port)
{
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_iowrite(0, port, &l, sizeof(l), 1, 0);
} else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
......@@ -234,7 +234,7 @@ void _outb_p(unsigned char b, unsigned long port)
if (port >= 0x300 && port < 0x320)
_ne_outb(b, PORT2ADDR_NE(port));
else
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_iowrite(0, port, &b, sizeof(b), 1, 0);
} else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
......@@ -251,7 +251,7 @@ void _outw_p(unsigned short w, unsigned long port)
if (port >= 0x300 && port < 0x320)
_ne_outw(w, PORT2ADDR_NE(port));
else
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_iowrite(0, port, &w, sizeof(w), 1, 0);
} else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
......@@ -277,7 +277,7 @@ void _insb(unsigned int port, void * addr, unsigned long count)
if (port >= 0x300 && port < 0x320){
portp = PORT2ADDR_NE(port);
while(count--) *buf++ = *(volatile unsigned char *)portp;
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_ioread(0, port, (void *)addr, sizeof(unsigned char), count, 1);
} else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
......@@ -297,7 +297,7 @@ void _insw(unsigned int port, void * addr, unsigned long count)
if (port >= 0x300 && port < 0x320) {
portp = PORT2ADDR_NE(port);
while (count--) *buf++ = _ne_inw(portp);
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_ioread(0, port, (void *)addr, sizeof(unsigned short), count, 1);
} else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
......@@ -326,7 +326,7 @@ void _outsb(unsigned int port, const void * addr, unsigned long count)
if (port >= 0x300 && port < 0x320) {
portp = PORT2ADDR_NE(port);
while (count--) _ne_outb(*buf++, portp);
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_iowrite(0, port, (void *)addr, sizeof(unsigned char), count, 1);
} else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
......@@ -346,7 +346,7 @@ void _outsw(unsigned int port, const void * addr, unsigned long count)
if (port >= 0x300 && port < 0x320) {
portp = PORT2ADDR_NE(port);
while (count--) _ne_outw(*buf++, portp);
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_iowrite(0, port, (void *)addr, sizeof(unsigned short), count, 1);
} else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
......
......@@ -140,7 +140,7 @@ void __init init_IRQ(void)
disable_mappi_irq(M32R_IRQ_SIO1_S);
#endif /* CONFIG_SERIAL_M32R_SIO */
#if defined(CONFIG_M32RPCC)
#if defined(CONFIG_M32R_PCC)
/* INT1 : pccard0 interrupt */
irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
irq_desc[M32R_IRQ_INT1].handler = &mappi_irq_type;
......
......@@ -70,16 +70,18 @@ qword_set_loop:
st r1, @+r4
bnc qword_set_loop || cmpz r2
jc r14
word_set_wrap:
set_remainder:
cmpui r2, #4
bc byte_set
bc byte_set_wrap1
addi r2, #-4
bra word_set_loop
byte_set_wrap:
addi r2, #4
addi r4, #4 || cmpz r2
cmpz r2
jc r14
byte_set_wrap1:
addi r4, #4
#if defined(CONFIG_ISA_M32R2)
byte_set:
addi r2, #-1 || stb r1, @r4+
......@@ -153,18 +155,19 @@ qword_set_loop:
st r1, @+r4
st r1, @+r4
bnc qword_set_loop
bnez r2, word_set_wrap
bnez r2, set_remainder
jmp r14
word_set_wrap:
set_remainder:
cmpui r2, #4
bc byte_set
bc byte_set_wrap1
addi r2, #-4
bra word_set_loop
byte_set_wrap:
addi r2, #4
addi r4, #4
beqz r2, end_memset
byte_set_wrap1:
addi r4, #4
byte_set:
addi r2, #-1
stb r1, @r4
......
......@@ -17,6 +17,7 @@
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
#include <asm/serial.h>
#include <asm/io.h>
#include <asm/time.h>
#if MPC52xx_PF_CONSOLE_PORT == 0
......
......@@ -145,13 +145,13 @@ static void __init ocotea_set_emacdata(void)
}
#define PCIX_READW(offset) \
(readw((u32)pcix_reg_base+offset))
(readw(pcix_reg_base+offset))
#define PCIX_WRITEW(value, offset) \
(writew(value, (u32)pcix_reg_base+offset))
(writew(value, pcix_reg_base+offset))
#define PCIX_WRITEL(value, offset) \
(writel(value, (u32)pcix_reg_base+offset))
(writel(value, pcix_reg_base+offset))
/*
* FIXME: This is only here to "make it work". This will move
......@@ -321,6 +321,11 @@ ocotea_setup_arch(void)
printk("IBM Ocotea port (MontaVista Software, Inc. <source@mvista.com>)\n");
}
static void __init ocotea_init(void)
{
ibm440gx_l2c_setup(&clocks);
}
void __init platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7)
{
......@@ -342,12 +347,11 @@ void __init platform_init(unsigned long r3, unsigned long r4,
ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
ocp_sys_info.opb_bus_freq = clocks.opb;
/*
* Always disable L2 cache. All revs/speeds of silicon
* have parity error problems despite errata claims to
* the contrary.
/* XXX Fix L2C IRQ triggerring setting (edge-sensitive).
* Firmware (at least PIBS v1.72 OCT/28/2003) sets it incorrectly
* --ebs
*/
ibm440gx_l2c_disable();
mtdcr(DCRN_UIC_TR(UIC2), mfdcr(DCRN_UIC_TR(UIC2)) | 0x00000100);
ibm44x_platform_init();
......@@ -365,4 +369,5 @@ void __init platform_init(unsigned long r3, unsigned long r4,
#ifdef CONFIG_KGDB
ppc_md.early_serial_map = ocotea_early_serial_map;
#endif
ppc_md.init = ocotea_init;
}
......@@ -60,11 +60,6 @@
* of the amount of memory in the system. Once a method of determining
* what version of DINK initializes the system for us, if applicable, is
* found, we can hopefully stop hardcoding 32MB of RAM.
*
* It is important to note that this code only supports the Sandpoint X3
* (all flavors) platform, and it does not support the X2 anymore. Code
* that at one time worked on the X2 can be found at:
* ftp://source.mvista.com/pub/linuxppc/obsolete/sandpoint/
*/
#include <linux/config.h>
......@@ -107,9 +102,13 @@
#include "sandpoint.h"
/* Set non-zero if an X2 Sandpoint detected. */
static int sandpoint_is_x2;
unsigned char __res[sizeof(bd_t)];
static void sandpoint_halt(void);
static void sandpoint_probe_type(void);
/*
* Define all of the IRQ senses and polarities. Taken from the
......@@ -129,7 +128,7 @@ static u_char sandpoint_openpic_initsenses[] __initdata = {
* Motorola SPS Sandpoint interrupt routing.
*/
static inline int
sandpoint_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
x3_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
{
static char pci_irq_table[][4] =
/*
......@@ -149,6 +148,27 @@ sandpoint_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
return PCI_IRQ_TABLE_LOOKUP;
}
static inline int
x2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
{
static char pci_irq_table[][4] =
/*
* PCI IDSEL/INTPIN->INTLINE
* A B C D
*/
{
{ 18, 0, 0, 0 }, /* IDSEL 11 - i8259 on Windbond */
{ 0, 0, 0, 0 }, /* IDSEL 12 - unused */
{ 16, 17, 18, 19 }, /* IDSEL 13 - PCI slot 1 */
{ 17, 18, 19, 16 }, /* IDSEL 14 - PCI slot 2 */
{ 18, 19, 16, 17 }, /* IDSEL 15 - PCI slot 3 */
{ 19, 16, 17, 18 }, /* IDSEL 16 - PCI slot 4 */
};
const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
return PCI_IRQ_TABLE_LOOKUP;
}
static void __init
sandpoint_setup_winbond_83553(struct pci_controller *hose)
{
......@@ -216,6 +236,18 @@ sandpoint_setup_winbond_83553(struct pci_controller *hose)
return;
}
/* On the sandpoint X2, we must avoid sending configuration cycles to
* device #12 (IDSEL addr = AD12).
*/
static int
x2_exclude_device(u_char bus, u_char devfn)
{
if ((bus == 0) && (PCI_SLOT(devfn) == SANDPOINT_HOST_BRIDGE_IDSEL))
return PCIBIOS_DEVICE_NOT_FOUND;
else
return PCIBIOS_SUCCESSFUL;
}
static void __init
sandpoint_find_bridges(void)
{
......@@ -241,7 +273,11 @@ sandpoint_find_bridges(void)
ppc_md.pcibios_fixup = NULL;
ppc_md.pcibios_fixup_bus = NULL;
ppc_md.pci_swizzle = common_swizzle;
ppc_md.pci_map_irq = sandpoint_map_irq;
if (sandpoint_is_x2) {
ppc_md.pci_map_irq = x2_map_irq;
ppc_md.pci_exclude_device = x2_exclude_device;
} else
ppc_md.pci_map_irq = x3_map_irq;
}
else {
if (ppc_md.progress)
......@@ -255,6 +291,11 @@ sandpoint_find_bridges(void)
static void __init
sandpoint_setup_arch(void)
{
/* Probe for Sandpoint model */
sandpoint_probe_type();
if (sandpoint_is_x2)
epic_serial_mode = 0;
loops_per_jiffy = 100000000 / HZ;
#ifdef CONFIG_BLK_DEV_INITRD
......@@ -318,14 +359,49 @@ sandpoint_setup_arch(void)
SANDPOINT_87308_CFG_OUTB(0x30, 0x01); \
}
/*
* To probe the Sandpoint type, we need to check for a connection between GPIO
* pins 6 and 7 on the NS87308 SuperIO.
*/
static void __init sandpoint_probe_type(void)
{
u8 x;
/* First, ensure that the GPIO pins are enabled. */
SANDPOINT_87308_SELECT_DEV(0x07); /* Select GPIO logical device */
SANDPOINT_87308_CFG_OUTB(0x60, 0x07); /* Base address 0x700 */
SANDPOINT_87308_CFG_OUTB(0x61, 0x00);
SANDPOINT_87308_CFG_OUTB(0x30, 0x01); /* Enable */
/* Now, set pin 7 to output and pin 6 to input. */
outb((inb(0x701) | 0x80) & 0xbf, 0x701);
/* Set push-pull output */
outb(inb(0x702) | 0x80, 0x702);
/* Set pull-up on input */
outb(inb(0x703) | 0x40, 0x703);
/* Set output high and check */
x = inb(0x700);
outb(x | 0x80, 0x700);
x = inb(0x700);
sandpoint_is_x2 = ! (x & 0x40);
if (ppc_md.progress && sandpoint_is_x2)
ppc_md.progress("High output says X2", 0);
/* Set output low and check */
outb(x & 0x7f, 0x700);
sandpoint_is_x2 |= inb(0x700) & 0x40;
if (ppc_md.progress && sandpoint_is_x2)
ppc_md.progress("Low output says X2", 0);
if (ppc_md.progress && ! sandpoint_is_x2)
ppc_md.progress("Sandpoint is X3", 0);
}
/*
* Fix IDE interrupts.
*/
static int __init
sandpoint_fix_winbond_83553(void)
{
/* Make all 8259 interrupt level sensitive */
outb(0xf8, 0x4d0);
/* Make some 8259 interrupt level sensitive */
outb(0xe0, 0x4d0);
outb(0xde, 0x4d1);
return 0;
......@@ -398,7 +474,7 @@ sandpoint_init_IRQ(void)
OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses);
mpc10x_set_openpic();
openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
openpic_hookup_cascade(sandpoint_is_x2 ? 17 : NUM_8259_INTERRUPTS, "82c59 cascade",
i8259_irq);
/*
......
......@@ -4,7 +4,7 @@
* PPC440GX system library
*
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
* Copyright (c) 2003 Zultys Technologies
* Copyright (c) 2003, 2004 Zultys Technologies
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
......@@ -14,6 +14,7 @@
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <asm/ibm44x.h>
#include <asm/mmu.h>
#include <asm/processor.h>
......@@ -97,10 +98,51 @@ void __init ibm440gx_get_clocks(struct ibm44x_clocks* p, unsigned int sys_clk,
p->uart1 = p->plb / __fix_zero(uart1 & 0xff, 256);
}
/* Enable L2 cache (call with IRQs disabled) */
/* Issue L2C diagnostic command */
static inline u32 l2c_diag(u32 addr)
{
mtdcr(DCRN_L2C0_ADDR, addr);
mtdcr(DCRN_L2C0_CMD, L2C_CMD_DIAG);
while (!(mfdcr(DCRN_L2C0_SR) & L2C_SR_CC)) ;
return mfdcr(DCRN_L2C0_DATA);
}
static irqreturn_t l2c_error_handler(int irq, void* dev, struct pt_regs* regs)
{
u32 sr = mfdcr(DCRN_L2C0_SR);
if (sr & L2C_SR_CPE){
/* Read cache trapped address */
u32 addr = l2c_diag(0x42000000);
printk(KERN_EMERG "L2C: Cache Parity Error, addr[16:26] = 0x%08x\n", addr);
}
if (sr & L2C_SR_TPE){
/* Read tag trapped address */
u32 addr = l2c_diag(0x82000000) >> 16;
printk(KERN_EMERG "L2C: Tag Parity Error, addr[16:26] = 0x%08x\n", addr);
}
/* Clear parity errors */
if (sr & (L2C_SR_CPE | L2C_SR_TPE)){
mtdcr(DCRN_L2C0_ADDR, 0);
mtdcr(DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
} else
printk(KERN_EMERG "L2C: LRU error\n");
return IRQ_HANDLED;
}
/* Enable L2 cache */
void __init ibm440gx_l2c_enable(void){
u32 r;
unsigned long flags;
/* Install error handler */
if (request_irq(87, l2c_error_handler, SA_INTERRUPT, "L2C", 0) < 0){
printk(KERN_ERR "Cannot install L2C error handler, cache is not enabled\n");
return;
}
local_irq_save(flags);
asm volatile ("sync" ::: "memory");
/* Disable SRAM */
......@@ -137,20 +179,22 @@ void __init ibm440gx_l2c_enable(void){
/* Enable ICU/DCU ports */
r = mfdcr(DCRN_L2C0_CFG);
r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM
| L2C_CFG_PMUX_MASK | L2C_CFG_PMIM | L2C_CFG_TPEI | L2C_CFG_CPEI
| L2C_CFG_NAM | L2C_CFG_NBRM);
r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM | L2C_CFG_TPEI
| L2C_CFG_CPEI | L2C_CFG_NAM | L2C_CFG_NBRM);
r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN
| L2C_CFG_SMCM;
| L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM | L2C_CFG_SMCM;
mtdcr(DCRN_L2C0_CFG, r);
asm volatile ("sync; isync" ::: "memory");
local_irq_restore(flags);
}
/* Disable L2 cache (call with IRQs disabled) */
/* Disable L2 cache */
void __init ibm440gx_l2c_disable(void){
u32 r;
unsigned long flags;
local_irq_save(flags);
asm volatile ("sync" ::: "memory");
/* Disable L2C mode */
......@@ -169,6 +213,7 @@ void __init ibm440gx_l2c_disable(void){
SRAM_SBCR_BAS3 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
asm volatile ("sync; isync" ::: "memory");
local_irq_restore(flags);
}
void __init ibm440gx_l2c_setup(struct ibm44x_clocks* p)
......
......@@ -43,7 +43,7 @@
#ifdef CONFIG_MPC10X_OPENPIC
#ifdef CONFIG_EPIC_SERIAL_MODE
#define EPIC_IRQ_BASE 16
#define EPIC_IRQ_BASE (epic_serial_mode ? 16 : 5)
#else
#define EPIC_IRQ_BASE 5
#endif
......@@ -69,20 +69,16 @@ static struct ocp_def mpc10x_i2c_ocp = {
.vendor = OCP_VENDOR_MOTOROLA,
.function = OCP_FUNC_IIC,
.index = 0,
.irq = MPC10X_I2C_IRQ,
.additions = &mpc10x_i2c_data
};
static struct ocp_def mpc10x_dma_ocp[2] = {
{ .vendor = OCP_VENDOR_MOTOROLA,
.function = OCP_FUNC_DMA,
.index = 0,
.irq = MPC10X_DMA0_IRQ
},
.index = 0 },
{ .vendor = OCP_VENDOR_MOTOROLA,
.function = OCP_FUNC_DMA,
.index = 1,
.irq = MPC10X_DMA1_IRQ }
.index = 1 }
};
/* Set resources to match bridge memory map */
......@@ -292,12 +288,15 @@ mpc10x_bridge_init(struct pci_controller *hose,
MPC10X_EUMB_EPIC_SIZE);
#endif
mpc10x_i2c_ocp.paddr = phys_eumb_base + MPC10X_EUMB_I2C_OFFSET;
mpc10x_i2c_ocp.irq = MPC10X_I2C_IRQ;
ocp_add_one_device(&mpc10x_i2c_ocp);
mpc10x_dma_ocp[0].paddr = phys_eumb_base +
MPC10X_EUMB_DMA_OFFSET + 0x100;
mpc10x_dma_ocp[0].irq = MPC10X_DMA0_IRQ;
ocp_add_one_device(&mpc10x_dma_ocp[0]);
mpc10x_dma_ocp[1].paddr = phys_eumb_base +
MPC10X_EUMB_DMA_OFFSET + 0x200;
mpc10x_dma_ocp[1].irq = MPC10X_DMA1_IRQ;
ocp_add_one_device(&mpc10x_dma_ocp[1]);
}
......
......@@ -19,6 +19,7 @@
#include <linux/config.h>
#include <asm/io.h>
#include <asm/time.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
......
......@@ -261,6 +261,9 @@ static void openpic_safe_writefield_IPI(volatile u_int *addr, u_int mask, u_int
#endif /* CONFIG_SMP */
#ifdef CONFIG_EPIC_SERIAL_MODE
/* On platforms that may use EPIC serial mode, the default is enabled. */
int epic_serial_mode = 1;
static void __init openpic_eicr_set_clk(u_int clkval)
{
openpic_writefield(&OpenPIC->Global.Global_Configuration1,
......@@ -415,8 +418,10 @@ void __init openpic_init(int offset)
openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
openpic_disable_8259_pass_through();
#ifdef CONFIG_EPIC_SERIAL_MODE
if (epic_serial_mode) {
openpic_eicr_set_clk(7); /* Slowest value until we know better */
openpic_enable_sie();
}
#endif
openpic_set_priority(0);
......
......@@ -18,6 +18,7 @@
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/bcd.h>
#include <linux/mc146818rtc.h>
#include <asm/machdep.h>
#include <asm/io.h>
......@@ -48,8 +49,6 @@
* --MAG
*/
extern spinlock_t rtc_lock;
/*
* 'todc_info' should be initialized in your *_setup.c file to
* point to a fully initialized 'todc_info_t' structure.
......
......@@ -25,30 +25,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/ppcdebug.h>
#include <linux/list.h>
#include <asm/iSeries/HvCallXm.h>
#include <asm/iSeries/LparData.h>
#include <asm/iommu.h>
#include <asm/pci-bridge.h>
#include <asm/iSeries/iSeries_pci.h>
#include <asm/machdep.h>
#include "pci.h"
#include <asm/iSeries/HvCallXm.h>
#include <asm/iSeries/iSeries_pci.h>
extern struct list_head iSeries_Global_Device_List;
......@@ -76,12 +60,11 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
tce.te_bits.tb_pciwr = 1;
}
rc = HvCallXm_setTce((u64)tbl->it_index,
(u64)index,
rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index,
tce.te_word);
if (rc)
panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc);
panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
rc);
index++;
uaddr += PAGE_SIZE;
}
......@@ -90,20 +73,14 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
{
u64 rc;
union tce_entry tce;
while (npages--) {
tce.te_word = 0;
rc = HvCallXm_setTce((u64)tbl->it_index,
(u64)index,
tce.te_word);
rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0);
if (rc)
panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc);
panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
rc);
index++;
}
}
......@@ -115,17 +92,14 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
{
struct iSeries_Device_Node *dp;
for (dp = (struct iSeries_Device_Node *)iSeries_Global_Device_List.next;
dp != (struct iSeries_Device_Node *)&iSeries_Global_Device_List;
dp = (struct iSeries_Device_Node *)dp->Device_List.next)
if (dp->iommu_table != NULL &&
dp->iommu_table->it_type == TCE_PCI &&
dp->iommu_table->it_offset == tbl->it_offset &&
dp->iommu_table->it_index == tbl->it_index &&
dp->iommu_table->it_size == tbl->it_size)
list_for_each_entry(dp, &iSeries_Global_Device_List, Device_List) {
if ((dp->iommu_table != NULL) &&
(dp->iommu_table->it_type == TCE_PCI) &&
(dp->iommu_table->it_offset == tbl->it_offset) &&
(dp->iommu_table->it_index == tbl->it_index) &&
(dp->iommu_table->it_size == tbl->it_size))
return dp->iommu_table;
}
return NULL;
}
......@@ -143,8 +117,7 @@ static void iommu_table_getparms(struct iSeries_Device_Node* dn,
{
struct iommu_table_cb *parms;
parms = (struct iommu_table_cb*)kmalloc(sizeof(*parms), GFP_KERNEL);
parms = kmalloc(sizeof(*parms), GFP_KERNEL);
if (parms == NULL)
panic("PCI_DMA: TCE Table Allocation failed.");
......@@ -171,22 +144,20 @@ static void iommu_table_getparms(struct iSeries_Device_Node* dn,
}
void iommu_devnode_init(struct iSeries_Device_Node *dn) {
void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn)
{
struct iommu_table *tbl;
tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
iommu_table_getparms(dn, tbl);
/* Look for existing tce table */
dn->iommu_table = iommu_table_find(tbl);
if (dn->iommu_table == NULL)
dn->iommu_table = iommu_init_table(tbl);
else
kfree(tbl);
return;
}
......
......@@ -312,8 +312,7 @@ void __init iSeries_pci_final_fixup(void)
mf_displaySrc(0xC9000100);
printk("pcibios_final_fixup\n");
while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))
!= NULL) {
for_each_pci_dev(pdev) {
node = find_Device_Node(pdev->bus->number, pdev->devfn);
printk("pci dev %p (%x.%x), node %p\n", pdev,
pdev->bus->number, pdev->devfn, node);
......@@ -329,7 +328,7 @@ void __init iSeries_pci_final_fixup(void)
iSeries_Device_Information(pdev, Buffer,
sizeof(Buffer));
printk("%d. %s\n", DeviceCount, Buffer);
iommu_devnode_init(node);
iommu_devnode_init_iSeries(node);
} else
printk("PCI: Device Tree not found for 0x%016lX\n",
(unsigned long)pdev);
......
......@@ -425,6 +425,39 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl)
return tbl;
}
void iommu_free_table(struct device_node *dn)
{
struct iommu_table *tbl = dn->iommu_table;
unsigned long bitmap_sz, i;
unsigned int order;
if (!tbl || !tbl->it_map) {
printk(KERN_ERR "%s: expected TCE map for %s\n", __FUNCTION__,
dn->full_name);
return;
}
/* verify that table contains no entries */
/* it_mapsize is in entries, and we're examining 64 at a time */
for (i = 0; i < (tbl->it_mapsize/64); i++) {
if (tbl->it_map[i] != 0) {
printk(KERN_WARNING "%s: Unexpected TCEs for %s\n",
__FUNCTION__, dn->full_name);
break;
}
}
/* calculate bitmap size in bytes */
bitmap_sz = (tbl->it_mapsize + 7) / 8;
/* free bitmap */
order = get_order(bitmap_sz);
free_pages((unsigned long) tbl->it_map, order);
/* free table */
kfree(tbl);
}
/* Creates TCEs for a user provided buffer. The user buffer must be
* contiguous real kernel storage (not vmalloc). The address of the buffer
* passed here is the kernel (virtual) address of the buffer. The buffer
......
......@@ -276,7 +276,7 @@ static void iommu_buses_init(void)
first_phb = 0;
for (dn = first_dn; dn != NULL; dn = dn->sibling)
iommu_devnode_init(dn);
iommu_devnode_init_pSeries(dn);
}
}
......@@ -298,7 +298,7 @@ static void iommu_buses_init_lpar(struct list_head *bus_list)
* Do it now because iommu_table_setparms_lpar needs it.
*/
busdn->bussubno = bus->number;
iommu_devnode_init(busdn);
iommu_devnode_init_pSeries(busdn);
}
/* look for a window on a bridge even if the PHB had one */
......@@ -397,7 +397,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
}
void iommu_devnode_init(struct device_node *dn)
void iommu_devnode_init_pSeries(struct device_node *dn)
{
struct iommu_table *tbl;
......@@ -412,39 +412,6 @@ void iommu_devnode_init(struct device_node *dn)
dn->iommu_table = iommu_init_table(tbl);
}
void iommu_free_table(struct device_node *dn)
{
struct iommu_table *tbl = dn->iommu_table;
unsigned long bitmap_sz, i;
unsigned int order;
if (!tbl || !tbl->it_map) {
printk(KERN_ERR "%s: expected TCE map for %s\n", __FUNCTION__,
dn->full_name);
return;
}
/* verify that table contains no entries */
/* it_mapsize is in entries, and we're examining 64 at a time */
for (i = 0; i < (tbl->it_mapsize/64); i++) {
if (tbl->it_map[i] != 0) {
printk(KERN_WARNING "%s: Unexpected TCEs for %s\n",
__FUNCTION__, dn->full_name);
break;
}
}
/* calculate bitmap size in bytes */
bitmap_sz = (tbl->it_mapsize + 7) / 8;
/* free bitmap */
order = get_order(bitmap_sz);
free_pages((unsigned long) tbl->it_map, order);
/* free table */
kfree(tbl);
}
void iommu_setup_pSeries(void)
{
struct pci_dev *dev = NULL;
......@@ -459,7 +426,7 @@ void iommu_setup_pSeries(void)
* pci device_node. This means get_iommu_table() won't need to search
* up the device tree to find it.
*/
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
for_each_pci_dev(dev) {
mydn = dn = PCI_GET_DN(dev);
while (dn && dn->iommu_table == NULL)
......@@ -469,7 +436,6 @@ void iommu_setup_pSeries(void)
}
}
/* These are called very early. */
void tce_init_pSeries(void)
{
......
......@@ -548,7 +548,7 @@ void __init pSeries_final_fixup(void)
check_s7a();
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
for_each_pci_dev(dev) {
pci_read_irq_line(dev);
if (s7a_workaround) {
if (dev->irq > 16) {
......
......@@ -663,7 +663,7 @@ void __init pmac_pcibios_fixup(void)
{
struct pci_dev *dev = NULL;
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
for_each_pci_dev(dev)
pci_read_irq_line(dev);
pci_fix_bus_sysdata();
......
......@@ -1740,7 +1740,7 @@ static int of_finish_dynamic_node(struct device_node *node)
if (strcmp(node->name, "pci") == 0 &&
get_property(node, "ibm,dma-window", NULL)) {
node->bussubno = node->busno;
iommu_devnode_init(node);
iommu_devnode_init_pSeries(node);
} else
node->iommu_table = parent->iommu_table;
#endif /* CONFIG_PPC_PSERIES */
......@@ -1801,6 +1801,15 @@ int of_add_node(const char *path, struct property *proplist)
return 0;
}
/*
* Prepare an OF node for removal from system
*/
static void of_cleanup_node(struct device_node *np)
{
if (np->iommu_table && get_property(np, "ibm,dma-window", NULL))
iommu_free_table(np);
}
/*
* Remove an OF device node from the system.
* Caller should have already "gotten" np.
......@@ -1818,13 +1827,7 @@ int of_remove_node(struct device_node *np)
return -EBUSY;
}
/* XXX This is a layering violation, should be moved to the caller
* --BenH.
*/
#ifdef CONFIG_PPC_PSERIES
if (np->iommu_table)
iommu_free_table(np);
#endif /* CONFIG_PPC_PSERIES */
of_cleanup_node(np);
write_lock(&devtree_lock);
OF_MARK_STALE(np);
......
......@@ -291,7 +291,7 @@ void iommu_setup_u3(void)
/* We only have one iommu table on the mac for now, which makes
* things simple. Setup all PCI devices to point to this table
*/
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
for_each_pci_dev(dev) {
/* We must use pci_device_to_OF_node() to make sure that
* we get the real "final" pointer to the device in the
* pci_dev sysdata and not the temporary PHB one
......
......@@ -521,24 +521,7 @@ static struct iommu_table * vio_build_iommu_table(struct vio_dev *dev)
newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
/* RPA docs say that #address-cells is always 1 for virtual
devices, but some older boxes' OF returns 2. This should
be removed by GA, unless there is legacy OFs that still
have 2 for #address-cells */
size = ((dma_window[1+vio_num_address_cells] >> PAGE_SHIFT) << 3)
>> PAGE_SHIFT;
/* This is just an ugly kludge. Remove as soon as the OF for all
machines actually follow the spec and encodes the offset field
as phys-encode (that is, #address-cells wide)*/
if (dma_window_property_size == 12) {
size = ((dma_window[1] >> PAGE_SHIFT) << 3) >> PAGE_SHIFT;
} else if (dma_window_property_size == 20) {
size = ((dma_window[4] >> PAGE_SHIFT) << 3) >> PAGE_SHIFT;
} else {
printk(KERN_WARNING "vio_build_iommu_table: Invalid size of ibm,my-dma-window=%i, using 0x80 for size\n", dma_window_property_size);
size = 0x80;
}
/* There should be some code to extract the phys-encoded offset
using prom_n_addr_cells(). However, according to a comment
......
......@@ -112,11 +112,16 @@ static int op_ppc64_create_files(struct super_block *sb, struct dentry *root)
oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
&sys.backtrace_spinlocks);
/* Default to tracing both kernel and user */
sys.enable_kernel = 1;
sys.enable_user = 1;
/* Turn on backtracing through spinlocks by default */
sys.backtrace_spinlocks = 1;
return 0;
}
......
......@@ -71,6 +71,7 @@ struct op_system_config {
unsigned long mmcra;
unsigned long enable_kernel;
unsigned long enable_user;
unsigned long backtrace_spinlocks;
};
/* Per-arch configuration */
......
......@@ -32,6 +32,13 @@ static u32 mmcr0_val;
static u64 mmcr1_val;
static u32 mmcra_val;
/*
* Since we do not have an NMI, backtracing through spinlocks is
* only a best guess. In light of this, allow it to be disabled at
* runtime.
*/
static int backtrace_spinlocks;
static void power4_reg_setup(struct op_counter_config *ctr,
struct op_system_config *sys,
int num_ctrs)
......@@ -59,6 +66,8 @@ static void power4_reg_setup(struct op_counter_config *ctr,
mmcr1_val = sys->mmcr1;
mmcra_val = sys->mmcra;
backtrace_spinlocks = sys->backtrace_spinlocks;
for (i = 0; i < num_counters; ++i)
reset_value[i] = 0x80000000UL - ctr[i].count;
......@@ -170,19 +179,38 @@ static void __attribute_used__ kernel_unknown_bucket(void)
{
}
static unsigned long check_spinlock_pc(struct pt_regs *regs,
unsigned long profile_pc)
{
unsigned long pc = instruction_pointer(regs);
/*
* If both the SIAR (sampled instruction) and the perfmon exception
* occurred in a spinlock region then we account the sample to the
* calling function. This isnt 100% correct, we really need soft
* IRQ disable so we always get the perfmon exception at the
* point at which the SIAR is set.
*/
if (backtrace_spinlocks && in_lock_functions(pc) &&
in_lock_functions(profile_pc))
return regs->link;
else
return profile_pc;
}
/*
* On GQ and newer the MMCRA stores the HV and PR bits at the time
* the SIAR was sampled. We use that to work out if the SIAR was sampled in
* the hypervisor, our exception vectors or RTAS.
*/
static unsigned long get_pc(void)
static unsigned long get_pc(struct pt_regs *regs)
{
unsigned long pc = mfspr(SPRN_SIAR);
unsigned long mmcra;
/* Cant do much about it */
if (!mmcra_has_sihv)
return pc;
return check_spinlock_pc(regs, pc);
mmcra = mfspr(SPRN_MMCRA);
......@@ -196,10 +224,6 @@ static unsigned long get_pc(void)
if (mmcra & MMCRA_SIPR)
return pc;
/* Were we in our exception vectors? */
if (pc < 0x4000UL)
return (unsigned long)__va(pc);
#ifdef CONFIG_PPC_PSERIES
/* Were we in RTAS? */
if (pc >= rtas.base && pc < (rtas.base + rtas.size))
......@@ -207,12 +231,16 @@ static unsigned long get_pc(void)
return *((unsigned long *)rtas_bucket);
#endif
/* Were we in our exception vectors or SLB real mode miss handler? */
if (pc < 0x1000000UL)
return (unsigned long)__va(pc);
/* Not sure where we were */
if (pc < KERNELBASE)
/* function descriptor madness */
return *((unsigned long *)kernel_unknown_bucket);
return pc;
return check_spinlock_pc(regs, pc);
}
static int get_kernel(unsigned long pc)
......@@ -239,7 +267,7 @@ static void power4_handle_interrupt(struct pt_regs *regs,
unsigned int cpu = smp_processor_id();
unsigned int mmcr0;
pc = get_pc();
pc = get_pc(regs);
is_kernel = get_kernel(pc);
/* set the PMM bit (see comment below) */
......
......@@ -75,7 +75,7 @@ sys_call_table:
/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
/*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
/*280*/ .long sys_setaltroot, sys_add_key, sys_request_key, sys_keyctl
/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
#ifdef CONFIG_SUNOS_EMUL
/* Now the SunOS syscall table. */
......
......@@ -5,7 +5,8 @@
ARCH_DIR = arch/um
OS := $(shell uname -s)
#We require it or things break.
# We require bash because the vmlinux link and loader script cpp use bash
# features.
SHELL := /bin/bash
filechk_gen_header = $<
......@@ -62,16 +63,18 @@ ifeq ($(CONFIG_MODE_SKAS), y)
$(SYS_HEADERS) : $(ARCH_DIR)/include/skas_ptregs.h
endif
.PHONY: linux
all: linux
linux: vmlinux
$(RM) $@
ln $< $@
ln -f $< $@
define archhelp
echo '* linux - Binary kernel image (./linux) - for backward'
echo ' compatibility only: now you can simply run'
echo ' the vmlinux binary you find in the kernel root.'
echo ' compatibility only, this creates a hard link to the'
echo ' real kernel binary, the the "vmlinux" binary you'
echo ' find in the kernel root.'
endef
prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) \
......@@ -117,7 +120,8 @@ define cmd_vmlinux__
-Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
-Wl,--start-group $(vmlinux-main) -Wl,--end-group \
-L/usr/lib -lutil \
$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) \
FORCE ,$^) ; rm -f linux
endef
USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
......
......@@ -27,14 +27,26 @@ int generic_console_write(int fd, const char *buf, int n, void *unused)
int err;
if(isatty(fd)){
tcgetattr(fd, &save);
CATCH_EINTR(err = tcgetattr(fd, &save));
if (err)
goto error;
new = save;
/* The terminal becomes a bit less raw, to handle \n also as
* "Carriage Return", not only as "New Line". Otherwise, the new
* line won't start at the first column.*/
new.c_oflag |= OPOST;
tcsetattr(fd, TCSAFLUSH, &new);
CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &new));
if (err)
goto error;
}
err = generic_write(fd, buf, n, NULL);
if(isatty(fd)) tcsetattr(fd, TCSAFLUSH, &save);
/* Restore raw mode, in any case; we *must* ignore any error apart
* EINTR, except for debug.*/
if(isatty(fd))
CATCH_EINTR(tcsetattr(fd, TCSAFLUSH, &save));
return(err);
error:
return(-errno);
}
static void winch_handler(int sig)
......
......@@ -119,12 +119,98 @@ void mconsole_log(struct mc_request *req)
mconsole_reply(req, "", 0, 0);
}
/* This is a more convoluted version of mconsole_proc, which has some stability
* problems; however, we need it fixed, because it is expected that UML users
* mount HPPFS instead of procfs on /proc. And we want mconsole_proc to still
* show the real procfs content, not the ones from hppfs.*/
#if 0
void mconsole_proc(struct mc_request *req)
{
struct nameidata nd;
struct file_system_type *proc;
struct super_block *super;
struct file *file;
int n, err;
char *ptr = req->request.data, *buf;
ptr += strlen("proc");
while(isspace(*ptr)) ptr++;
proc = get_fs_type("proc");
if(proc == NULL){
mconsole_reply(req, "procfs not registered", 1, 0);
goto out;
}
super = (*proc->get_sb)(proc, 0, NULL, NULL);
put_filesystem(proc);
if(super == NULL){
mconsole_reply(req, "Failed to get procfs superblock", 1, 0);
goto out;
}
up_write(&super->s_umount);
nd.dentry = super->s_root;
nd.mnt = NULL;
nd.flags = O_RDONLY + 1;
nd.last_type = LAST_ROOT;
/* START: it was experienced that the stability problems are closed
* if commenting out these two calls + the below read cycle. To
* make UML crash again, it was enough to readd either one.*/
err = link_path_walk(ptr, &nd);
if(err){
mconsole_reply(req, "Failed to look up file", 1, 0);
goto out_kill;
}
file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
if(IS_ERR(file)){
mconsole_reply(req, "Failed to open file", 1, 0);
goto out_kill;
}
/*END*/
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if(buf == NULL){
mconsole_reply(req, "Failed to allocate buffer", 1, 0);
goto out_fput;
}
if((file->f_op != NULL) && (file->f_op->read != NULL)){
do {
n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1,
&file->f_pos);
if(n >= 0){
buf[n] = '\0';
mconsole_reply(req, buf, 0, (n > 0));
}
else {
mconsole_reply(req, "Read of file failed",
1, 0);
goto out_free;
}
} while(n > 0);
}
else mconsole_reply(req, "", 0, 0);
out_free:
kfree(buf);
out_fput:
fput(file);
out_kill:
deactivate_super(super);
out: ;
}
#endif
void mconsole_proc(struct mc_request *req)
{
char path[64];
char *buf;
int len;
int fd;
int first_chunk = 1;
char *ptr = req->request.data;
ptr += strlen("proc");
......@@ -149,7 +235,13 @@ void mconsole_proc(struct mc_request *req)
if (len < 0) {
mconsole_reply(req, "Read of file failed", 1, 0);
goto out_free;
} else if (len == PAGE_SIZE-1) {
}
/*Begin the file content on his own line.*/
if (first_chunk) {
mconsole_reply(req, "\n", 0, 1);
first_chunk = 0;
}
if (len == PAGE_SIZE-1) {
buf[len] = '\0';
mconsole_reply(req, buf, 0, 1);
} else {
......
......@@ -123,12 +123,18 @@ struct chan_ops port_ops = {
int port_listen_fd(int port)
{
struct sockaddr_in addr;
int fd, err;
int fd, err, arg;
fd = socket(PF_INET, SOCK_STREAM, 0);
if(fd == -1)
return(-errno);
arg = 1;
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0){
err = -errno;
goto out;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
......
......@@ -67,6 +67,7 @@ extern void map_memory(unsigned long virt, unsigned long phys,
extern int protect_memory(unsigned long addr, unsigned long len,
int r, int w, int x, int must_succeed);
extern unsigned long get_kmem_end(void);
extern void check_tmpexec(void);
#endif
......
......@@ -9,11 +9,11 @@
#include "uml-config.h"
#ifdef UML_CONFIG_MODE_TT
#include "../kernel/tt/include/mode.h"
#include "mode-tt.h"
#endif
#ifdef UML_CONFIG_MODE_SKAS
#include "../kernel/skas/include/mode.h"
#include "mode-skas.h"
#endif
#endif
......
......@@ -9,11 +9,11 @@
#include "linux/config.h"
#ifdef CONFIG_MODE_TT
#include "../kernel/tt/include/mode_kern.h"
#include "mode_kern-tt.h"
#endif
#ifdef CONFIG_MODE_SKAS
#include "../kernel/skas/include/mode_kern.h"
#include "mode_kern-skas.h"
#endif
#endif
......
......@@ -157,6 +157,7 @@ extern unsigned long os_process_pc(int pid);
extern int os_process_parent(int pid);
extern void os_stop_process(int pid);
extern void os_kill_process(int pid, int reap_child);
extern void os_kill_ptraced_process(int pid, int reap_child);
extern void os_usr1_process(int pid);
extern int os_getpid(void);
......
......@@ -15,4 +15,15 @@ extern void arch_enter_kernel(void *task, int pid);
extern void arch_leave_kernel(void *task, int pid);
extern void ptrace_pokeuser(unsigned long addr, unsigned long data);
/* syscall emulation path in ptrace */
#ifndef PTRACE_SYSEMU
#define PTRACE_SYSEMU 31
#endif
void set_using_sysemu(int value);
int get_using_sysemu(void);
extern int sysemu_supported;
#endif
......@@ -10,11 +10,11 @@
#include "choose-mode.h"
#ifdef CONFIG_MODE_TT
#include "../kernel/tt/include/mmu.h"
#include "mmu-tt.h"
#endif
#ifdef CONFIG_MODE_SKAS
#include "../kernel/skas/include/mmu.h"
#include "mmu-skas.h"
#endif
typedef union {
......
......@@ -10,11 +10,11 @@
#include "choose-mode.h"
#ifdef CONFIG_MODE_TT
#include "../kernel/tt/include/uaccess.h"
#include "uaccess-tt.h"
#endif
#ifdef CONFIG_MODE_SKAS
#include "../kernel/skas/include/uaccess.h"
#include "uaccess-skas.h"
#endif
#define access_ok(type, addr, size) \
......
......@@ -8,7 +8,7 @@
#include "sysdep/ptrace.h"
#define CATCH_EINTR(expr) while (((expr) < 0) && (errno == EINTR))
#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
extern int mode_tt;
......
......@@ -17,6 +17,8 @@
#include "kern_util.h"
#include "mem_user.h"
#include "signal_user.h"
#include "time_user.h"
#include "irq_user.h"
#include "user.h"
#include "init.h"
#include "mode.h"
......
......@@ -83,6 +83,26 @@ static int create_tmp_file(unsigned long len)
return(fd);
}
void check_tmpexec(void)
{
void *addr;
int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
addr = mmap(NULL, UM_KERN_PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
printf("Checking PROT_EXEC mmap in /tmp...");
fflush(stdout);
if(addr == MAP_FAILED){
err = errno;
perror("failed");
if(err == EPERM)
printf("/tmp must be not mounted noexec\n");
exit(1);
}
printf("OK\n");
munmap(addr, UM_KERN_PAGE_SIZE);
}
static int have_devanon = 0;
void check_devanon(void)
......@@ -111,7 +131,7 @@ static int create_anon_file(unsigned long len)
exit(1);
}
addr = mmap(NULL, len, PROT_READ | PROT_WRITE , MAP_PRIVATE, fd, 0);
addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if(addr == MAP_FAILED){
os_print_error((int) addr, "mapping physmem file");
exit(1);
......@@ -208,6 +228,39 @@ int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
return(0);
}
#if 0
/* Debugging facility for dumping stuff out to the host, avoiding the timing
* problems that come with printf and breakpoints.
* Enable in case of emergency.
*/
int logging = 1;
int logging_fd = -1;
int logging_line = 0;
char logging_buf[512];
void log(char *fmt, ...)
{
va_list ap;
struct timeval tv;
struct openflags flags;
if(logging == 0) return;
if(logging_fd < 0){
flags = of_create(of_trunc(of_rdwr(OPENFLAGS())));
logging_fd = os_open_file("log", flags, 0644);
}
gettimeofday(&tv, NULL);
sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec,
tv.tv_usec);
va_start(ap, fmt);
vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap);
va_end(ap);
write(logging_fd, logging_buf, strlen(logging_buf));
}
#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
......
......@@ -137,14 +137,31 @@ int start_fork_tramp(void *thread_arg, unsigned long temp_stack,
static int ptrace_child(void *arg)
{
int pid = os_getpid();
int ret;
int pid = os_getpid(), ppid = getppid();
int sc_result;
if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
perror("ptrace");
os_kill_process(pid, 0);
}
os_stop_process(pid);
_exit(os_getpid() == pid);
/*This syscall will be intercepted by the parent. Don't call more than
* once, please.*/
sc_result = os_getpid();
if (sc_result == pid)
ret = 1; /*Nothing modified by the parent, we are running
normally.*/
else if (sc_result == ppid)
ret = 0; /*Expected in check_ptrace and check_sysemu when they
succeed in modifying the stack frame*/
else
ret = 2; /*Serious trouble! This could be caused by a bug in
host 2.6 SKAS3/2.6 patch before release -V6, together
with a bug in the UML code itself.*/
_exit(ret);
}
static int start_ptraced_child(void **stack_out)
......@@ -172,18 +189,36 @@ static int start_ptraced_child(void **stack_out)
return(pid);
}
static void stop_ptraced_child(int pid, void *stack, int exitcode)
/* When testing for SYSEMU support, if it is one of the broken versions, we must
* just avoid using sysemu, not panic, but only if SYSEMU features are broken.
* So only for SYSEMU features we test mustpanic, while normal host features
* must work anyway!*/
static int stop_ptraced_child(int pid, void *stack, int exitcode, int mustpanic)
{
int status, n;
int status, n, ret = 0;
if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
panic("check_ptrace : ptrace failed, errno = %d", errno);
CATCH_EINTR(n = waitpid(pid, &status, 0));
if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode))
panic("check_ptrace : child exited with status 0x%x", status);
if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
int exit_with = WEXITSTATUS(status);
if (exit_with == 2)
printk("check_ptrace : child exited with status 2. "
"Serious trouble happening! Try updating your "
"host skas patch!\nDisabling SYSEMU support.");
printk("check_ptrace : child exited with exitcode %d, while "
"expecting %d; status 0x%x", exit_with,
exitcode, status);
if (mustpanic)
panic("\n");
else
printk("\n");
ret = -1;
}
if(munmap(stack, PAGE_SIZE) < 0)
panic("check_ptrace : munmap failed, errno = %d", errno);
return ret;
}
static int force_sysemu_disabled = 0;
......@@ -200,63 +235,46 @@ __uml_setup("nosysemu", nosysemu_cmd_param,
" SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n"
" behaviour of ptrace() and helps reducing host context switch rate.\n"
" To make it working, you need a kernel patch for your host, too.\n"
" See http://perso.wanadoo.fr/laurent.vivier/UML/ for further information.\n");
/* Ugly hack for now... --cw */
#ifndef PTRACE_SYSEMU
#define PTRACE_SYSEMU 31
#endif
" See http://perso.wanadoo.fr/laurent.vivier/UML/ for further information.\n\n");
static void __init check_sysemu(void)
{
void *stack;
int pid, n, status;
if (mode_tt)
return;
printk("Checking syscall emulation patch for ptrace...");
#ifdef CONFIG_MODE_SKAS
sysemu_supported = 0;
#endif /* CONFIG_MODE_SKAS */
pid = start_ptraced_child(&stack);
if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) {
struct user_regs_struct regs;
if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0)
goto fail;
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if (n < 0)
panic("check_ptrace : wait failed, errno = %d", errno);
panic("check_sysemu : wait failed, errno = %d", errno);
if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
panic("check_ptrace : expected SIGTRAP, "
panic("check_sysemu : expected SIGTRAP, "
"got status = %d", status);
if (ptrace(PTRACE_GETREGS, pid, 0, &regs) < 0)
panic("check_ptrace : failed to read child "
"registers, errno = %d", errno);
regs.orig_eax = pid;
if (ptrace(PTRACE_SETREGS, pid, 0, &regs) < 0)
panic("check_ptrace : failed to modify child "
"registers, errno = %d", errno);
n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
os_getpid());
if(n < 0)
panic("check_sysemu : failed to modify system "
"call return, errno = %d", errno);
stop_ptraced_child(pid, stack, 0);
if (stop_ptraced_child(pid, stack, 0, 0) < 0)
goto fail_stopped;
#ifdef CONFIG_MODE_SKAS
sysemu_supported = 1;
#endif /* CONFIG_MODE_SKAS */
printk("found\n");
}
else
{
stop_ptraced_child(pid, stack, 1);
#ifdef CONFIG_MODE_SKAS
printk("OK\n");
set_using_sysemu(!force_sysemu_disabled);
return;
fail:
stop_ptraced_child(pid, stack, 1, 0);
fail_stopped:
sysemu_supported = 0;
#endif /* CONFIG_MODE_SKAS */
printk("missing\n");
}
#ifdef CONFIG_MODE_SKAS
set_using_sysemu(!force_sysemu_disabled);
#endif
}
void __init check_ptrace(void)
......@@ -289,7 +307,7 @@ void __init check_ptrace(void)
break;
}
}
stop_ptraced_child(pid, stack, 0);
stop_ptraced_child(pid, stack, 0, 1);
printk("OK\n");
check_sysemu();
}
......@@ -337,7 +355,7 @@ int can_do_skas(void)
else printf("found\n");
init_registers(pid);
stop_ptraced_child(pid, stack, 1);
stop_ptraced_child(pid, stack, 1, 1);
printf("Checking for /proc/mm...");
if(os_access("/proc/mm", OS_ACC_W_OK) < 0){
......
......@@ -18,6 +18,8 @@
#include "linux/capability.h"
#include "linux/vmalloc.h"
#include "linux/spinlock.h"
#include "linux/proc_fs.h"
#include "linux/ptrace.h"
#include "asm/unistd.h"
#include "asm/mman.h"
#include "asm/segment.h"
......@@ -398,6 +400,74 @@ int cpu(void)
return(current_thread->cpu);
}
static atomic_t using_sysemu = ATOMIC_INIT(0);
int sysemu_supported;
void set_using_sysemu(int value)
{
atomic_set(&using_sysemu, sysemu_supported && value);
}
int get_using_sysemu(void)
{
return atomic_read(&using_sysemu);
}
static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
{
if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
*eof = 1;
return strlen(buf);
}
static int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data)
{
char tmp[2];
if (copy_from_user(tmp, buf, 1))
return -EFAULT;
if (tmp[0] == '0' || tmp[0] == '1')
set_using_sysemu(tmp[0] - '0');
return count; /*We use the first char, but pretend to write everything*/
}
int __init make_proc_sysemu(void)
{
struct proc_dir_entry *ent;
if (!sysemu_supported)
return 0;
ent = create_proc_entry("sysemu", 0600, &proc_root);
if (ent == NULL)
{
printk("Failed to register /proc/sysemu\n");
return(0);
}
ent->read_proc = proc_read_sysemu;
ent->write_proc = proc_write_sysemu;
return 0;
}
late_initcall(make_proc_sysemu);
int singlestepping(void * t)
{
struct task_struct *task = t ? t : current;
if ( ! (task->ptrace & PT_DTRACE) )
return(0);
if (task->thread.singlestep_syscall)
return(0);
return 1;
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
......
......@@ -22,6 +22,8 @@
*/
void ptrace_disable(struct task_struct *child)
{
child->ptrace &= ~PT_DTRACE;
child->thread.singlestep_syscall = 0;
}
int sys_ptrace(long request, long pid, long addr, long data)
......@@ -139,6 +141,9 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
if ((unsigned long) data > _NSIG)
break;
child->ptrace &= ~PT_DTRACE;
child->thread.singlestep_syscall = 0;
if (request == PTRACE_SYSCALL) {
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
}
......@@ -160,6 +165,9 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = 0;
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
child->ptrace &= ~PT_DTRACE;
child->thread.singlestep_syscall = 0;
child->exit_code = SIGKILL;
wake_up_process(child);
break;
......@@ -171,6 +179,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->ptrace |= PT_DTRACE;
child->thread.singlestep_syscall = 0;
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
......@@ -299,6 +308,9 @@ int sys_ptrace(long request, long pid, long addr, long data)
void syscall_trace(union uml_pt_regs *regs, int entryexit)
{
int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit;
int tracesysgood;
if (unlikely(current->audit_context)) {
if (!entryexit)
audit_syscall_entry(current, regs->orig_eax,
......@@ -308,18 +320,20 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
audit_syscall_exit(current, regs->eax);
}
if (!test_thread_flag(TIF_SYSCALL_TRACE))
if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_singlestep)
return;
if (!(current->ptrace & PT_PTRACED))
return;
/* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0));
tracesysgood = (current->ptrace & PT_TRACESYSGOOD) && !is_singlestep;
ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0));
/* force do_signal() --> is_syscall() */
set_thread_flag(TIF_SIGPENDING);
/*
* this isn't the same as continuing with a signal, but it will do
/* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
......
......@@ -38,16 +38,17 @@ EXPORT_SYMBOL(unblock_signals);
/*
* OK, we're invoking a handler
*/
static int handle_signal(struct pt_regs *regs, unsigned long signr,
static void handle_signal(struct pt_regs *regs, unsigned long signr,
struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, int error)
sigset_t *oldset)
{
__sighandler_t handler;
void (*restorer)(void);
unsigned long sp;
sigset_t save;
int err, ret;
int error, err, ret;
error = PT_REGS_SYSCALL_RET(&current->thread.regs);
ret = 0;
/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
......@@ -109,31 +110,25 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
else
err = setup_signal_stack_sc(sp, signr, (unsigned long) handler,
restorer, regs, &save);
if(err) goto segv;
return(0);
segv:
if(err)
force_sigsegv(signr, current);
return(1);
}
static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
{
struct k_sigaction ka_copy;
siginfo_t info;
int err, sig;
int sig;
if (!oldset)
oldset = &current->blocked;
sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL);
if(sig == 0)
return(0);
if(sig > 0){
/* Whee! Actually deliver the signal. */
err = handle_signal(regs, sig, &ka_copy, &info, oldset, error);
if(!err)
handle_signal(regs, sig, &ka_copy, &info, oldset);
return(1);
}
/* Did we come from a system call? */
if(PT_REGS_SYSCALL_NR(regs) >= 0){
......@@ -157,15 +152,15 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
* on the host. The tracing thread will check this flag and
* PTRACE_SYSCALL if necessary.
*/
if((current->ptrace & PT_DTRACE) &&
is_syscall(PT_REGS_IP(&current->thread.regs)))
(void) CHOOSE_MODE(current->thread.mode.tt.singlestep_syscall = 1, 0);
if(current->ptrace & PT_DTRACE)
current->thread.singlestep_syscall =
is_syscall(PT_REGS_IP(&current->thread.regs));
return(0);
}
int do_signal(int error)
{
return(kern_do_signal(&current->thread.regs, NULL, error));
return(kern_do_signal(&current->thread.regs, NULL));
}
/*
......@@ -182,10 +177,11 @@ int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if(kern_do_signal(&current->thread.regs, &saveset, -EINTR))
if(kern_do_signal(&current->thread.regs, &saveset))
return(-EINTR);
}
}
......@@ -208,10 +204,11 @@ int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (kern_do_signal(&current->thread.regs, &saveset, -EINTR))
if (kern_do_signal(&current->thread.regs, &saveset))
return(-EINTR);
}
}
......
......@@ -57,6 +57,10 @@ int change_sig(int signal, int on)
return(!sigismember(&old, signal));
}
/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
* disable profiling; it's safe because the profiling code does not interact
* with the kernel code at all.*/
static void change_signals(int type)
{
sigset_t mask;
......@@ -65,7 +69,6 @@ static void change_signals(int type)
sigaddset(&mask, SIGVTALRM);
sigaddset(&mask, SIGALRM);
sigaddset(&mask, SIGIO);
sigaddset(&mask, SIGPROF);
if(sigprocmask(type, &mask, NULL) < 0)
panic("Failed to change signal mask - errno = %d", errno);
}
......
......@@ -12,7 +12,7 @@
#include "asm/mmu_context.h"
#include "tlb.h"
#include "skas.h"
#include "mmu.h"
#include "um_mmu.h"
#include "os.h"
void flush_thread_skas(void)
......
......@@ -6,9 +6,6 @@
#ifndef __SKAS_MMU_H
#define __SKAS_MMU_H
#include "linux/list.h"
#include "linux/spinlock.h"
struct mmu_context_skas {
int mm_fd;
};
......
......@@ -6,6 +6,8 @@
#ifndef __MODE_SKAS_H__
#define __MODE_SKAS_H__
#include <sysdep/ptrace.h>
extern unsigned long exec_regs[];
extern unsigned long exec_fp_regs[];
extern unsigned long exec_fpx_regs[];
......
......@@ -10,16 +10,6 @@
#ifdef UML_CONFIG_MODE_SKAS
/* syscall emulation path in ptrace */
#ifndef PTRACE_SYSEMU
#define PTRACE_SYSEMU 31
#endif
void set_using_sysemu(int value);
int get_using_sysemu(void);
extern int sysemu_supported;
#include "skas_ptregs.h"
#define HOST_FRAME_SIZE 17
......
......@@ -28,7 +28,6 @@ extern int unmap(int fd, void *addr, int len);
extern int protect(int fd, unsigned long addr, unsigned long len,
int r, int w, int x, int must_succeed);
extern void user_signal(int sig, union uml_pt_regs *regs);
extern int singlestepping_skas(void);
extern int new_mm(int from);
extern void save_registers(union uml_pt_regs *regs);
extern void restore_registers(union uml_pt_regs *regs);
......
......@@ -139,17 +139,16 @@ void start_userspace(int cpu)
void userspace(union uml_pt_regs *regs)
{
int err, status, op, pid = userspace_pid[0];
int err, status, op, pt_syscall_parm, pid = userspace_pid[0];
int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
restore_registers(regs);
local_using_sysemu = get_using_sysemu();
if (local_using_sysemu)
err = ptrace(PTRACE_SYSEMU, pid, 0, 0);
else
err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
err = ptrace(pt_syscall_parm, pid, 0, 0);
if(err)
panic("userspace - PTRACE_%s failed, errno = %d\n",
local_using_sysemu ? "SYSEMU" : "SYSCALL", errno);
......@@ -189,13 +188,10 @@ void userspace(union uml_pt_regs *regs)
/*Now we ended the syscall, so re-read local_using_sysemu.*/
local_using_sysemu = get_using_sysemu();
pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
if (local_using_sysemu)
op = singlestepping_skas() ? PTRACE_SINGLESTEP :
PTRACE_SYSEMU;
else
op = singlestepping_skas() ? PTRACE_SINGLESTEP :
PTRACE_SYSCALL;
op = singlestepping(NULL) ? PTRACE_SINGLESTEP :
pt_syscall_parm;
err = ptrace(op, pid, 0, 0);
if(err)
......@@ -389,7 +385,7 @@ void switch_mm_skas(int mm_fd)
void kill_off_processes_skas(void)
{
#warning need to loop over userspace_pids in kill_off_processes_skas
os_kill_process(userspace_pid[0], 1);
os_kill_ptraced_process(userspace_pid[0], 1);
}
void init_registers(int pid)
......
......@@ -24,69 +24,6 @@
#include "mode.h"
#include "proc_mm.h"
static atomic_t using_sysemu;
int sysemu_supported;
void set_using_sysemu(int value)
{
atomic_set(&using_sysemu, sysemu_supported && value);
}
int get_using_sysemu(void)
{
return atomic_read(&using_sysemu);
}
int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
{
if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
*eof = 1;
return strlen(buf);
}
int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data)
{
char tmp[2];
if (copy_from_user(tmp, buf, 1))
return -EFAULT;
if (tmp[0] == '0' || tmp[0] == '1')
set_using_sysemu(tmp[0] - '0');
return count; /*We use the first char, but pretend to write everything*/
}
int __init make_proc_sysemu(void)
{
struct proc_dir_entry *ent;
if (mode_tt || !sysemu_supported)
return 0;
ent = create_proc_entry("sysemu", 0600, &proc_root);
if (ent == NULL)
{
printk("Failed to register /proc/sysemu\n");
return(0);
}
ent->read_proc = proc_read_sysemu;
ent->write_proc = proc_write_sysemu;
return 0;
}
late_initcall(make_proc_sysemu);
int singlestepping_skas(void)
{
int ret = current->ptrace & PT_DTRACE;
current->ptrace &= ~PT_DTRACE;
return(ret);
}
void *switch_to_skas(void *prev, void *next)
{
struct task_struct *from, *to;
......
......@@ -4,6 +4,7 @@
*/
#include "linux/sys.h"
#include "linux/ptrace.h"
#include "asm/errno.h"
#include "asm/unistd.h"
#include "asm/ptrace.h"
......
......@@ -22,7 +22,7 @@ void handle_syscall(union uml_pt_regs *regs)
index = record_syscall_start(UPT_SYSCALL_NR(regs));
syscall_trace(regs, 1);
syscall_trace(regs, 0);
result = execute_syscall(regs);
REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
......@@ -30,7 +30,7 @@ void handle_syscall(union uml_pt_regs *regs)
(result == -ERESTARTNOINTR))
do_signal(result);
syscall_trace(regs, 0);
syscall_trace(regs, 1);
record_syscall_end(index, result);
}
......
......@@ -14,23 +14,23 @@
void show_trace(unsigned long * stack)
{
int i;
/* XXX: Copy the CONFIG_FRAME_POINTER stack-walking backtrace from
* arch/i386/kernel/traps.c. */
unsigned long addr;
if (!stack)
stack = (unsigned long*) &stack;
printk("Call Trace:\n");
i = 1;
printk("Call Trace: \n");
while (((long) stack & (THREAD_SIZE-1)) != 0) {
addr = *stack++;
if (__kernel_text_address(addr)) {
printk("[<%08lx>] ", addr);
print_symbol("%s", addr);
printk(" [<%08lx>]", addr);
print_symbol(" %s", addr);
printk("\n");
i++;
}
}
printk("\n");
}
/*
......@@ -48,4 +48,3 @@ void show_stack(struct task_struct *task, unsigned long *sp)
{
show_trace(sp);
}
......@@ -4,6 +4,7 @@
#
extra-y := unmap_fin.o
clean-files := unmap_tmp.o
obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
......@@ -20,10 +21,9 @@ UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS))
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
$(O_TARGET) : $(obj)/unmap_fin.o
$(obj)/unmap.o: $(src)/unmap.c
$(CC) $(UNMAP_CFLAGS) -c -o $@ $<
$(obj)/unmap_fin.o : $(src)/unmap.o
ld -r -o $@ $< -lc -L/usr/lib
$(obj)/unmap_fin.o : $(obj)/unmap.o
ld -r -o $(obj)/unmap_tmp.o $< -lc -L/usr/lib
objcopy $(obj)/unmap_tmp.o $@ -G switcheroo
......@@ -24,11 +24,9 @@ extern void set_init_pid(int pid);
extern int set_user_mode(void *task);
extern void set_tracing(void *t, int tracing);
extern int is_tracing(void *task);
extern int singlestepping_tt(void *t);
extern void clear_singlestep(void *t);
extern void syscall_handler(int sig, union uml_pt_regs *regs);
extern void exit_kernel(int pid, void *task);
extern int do_syscall(void *task, int pid);
extern int do_syscall(void *task, int pid, int local_using_sysemu);
extern int is_valid_pid(int pid);
extern void remap_data(void *segment_start, void *segment_end, int w);
......
......@@ -82,7 +82,7 @@ void *switch_to_tt(void *prev, void *next, void *last)
prev_sched = current->thread.prev_sched;
if((prev_sched->exit_state == EXIT_ZOMBIE) ||
(prev_sched->exit_state == EXIT_DEAD))
os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);
os_kill_ptraced_process(prev_sched->thread.mode.tt.extern_pid, 1);
/* This works around a nasty race with 'jail'. If we are switching
* between two threads of a threaded app and the incoming process
......@@ -523,22 +523,6 @@ void set_init_pid(int pid)
-err);
}
int singlestepping_tt(void *t)
{
struct task_struct *task = t;
if(task->thread.mode.tt.singlestep_syscall)
return(0);
return(task->ptrace & PT_DTRACE);
}
void clear_singlestep(void *t)
{
struct task_struct *task = t;
task->ptrace &= ~PT_DTRACE;
}
int start_uml_tt(void)
{
void *sp;
......
......@@ -123,12 +123,6 @@ long execute_syscall_tt(void *r)
set_fs(USER_DS);
if(current->thread.mode.tt.singlestep_syscall){
current->thread.mode.tt.singlestep_syscall = 0;
current->ptrace &= ~PT_DTRACE;
force_sig(SIGTRAP, current);
}
return(res);
}
......
......@@ -33,7 +33,7 @@ void syscall_handler_tt(int sig, union uml_pt_regs *regs)
SC_START_SYSCALL(sc);
index = record_syscall_start(syscall);
syscall_trace(regs, 1);
syscall_trace(regs, 0);
result = execute_syscall(regs);
/* regs->sc may have changed while the system call ran (there may
......@@ -46,11 +46,11 @@ void syscall_handler_tt(int sig, union uml_pt_regs *regs)
(result == -ERESTARTNOINTR))
do_signal(result);
syscall_trace(regs, 0);
syscall_trace(regs, 1);
record_syscall_end(index, result);
}
int do_syscall(void *task, int pid)
int do_syscall(void *task, int pid, int local_using_sysemu)
{
unsigned long proc_regs[FRAME_SIZE];
union uml_pt_regs *regs;
......@@ -70,6 +70,9 @@ int do_syscall(void *task, int pid)
((unsigned long *) PT_IP(proc_regs) <= &_etext))
tracer_panic("I'm tracing myself and I can't get out");
if(local_using_sysemu)
return(1);
if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
__NR_getpid) < 0)
tracer_panic("do_syscall : Nullifying syscall failed, "
......
......@@ -184,6 +184,7 @@ int tracer(int (*init_proc)(void *), void *sp)
unsigned long eip = 0;
int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0;
int pt_syscall_parm, local_using_sysemu;
capture_signal_stack();
signal(SIGPIPE, SIG_IGN);
......@@ -297,6 +298,9 @@ int tracer(int (*init_proc)(void *), void *sp)
tracing = is_tracing(task);
old_tracing = tracing;
local_using_sysemu = get_using_sysemu();
pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
switch(sig){
case SIGUSR1:
sig = 0;
......@@ -330,9 +334,8 @@ int tracer(int (*init_proc)(void *), void *sp)
continue;
}
tracing = 0;
if(do_syscall(task, pid))
if(do_syscall(task, pid, local_using_sysemu))
sig = SIGUSR2;
else clear_singlestep(task);
break;
case SIGPROF:
if(tracing) sig = 0;
......@@ -349,6 +352,7 @@ int tracer(int (*init_proc)(void *), void *sp)
case SIGBUS:
case SIGILL:
case SIGWINCH:
default:
tracing = 0;
break;
......@@ -368,9 +372,9 @@ int tracer(int (*init_proc)(void *), void *sp)
}
if(tracing){
if(singlestepping_tt(task))
if(singlestepping(task))
cont_type = PTRACE_SINGLESTEP;
else cont_type = PTRACE_SYSCALL;
else cont_type = pt_syscall_parm;
}
else cont_type = PTRACE_CONT;
......
......@@ -23,6 +23,13 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
unprotect_kernel_mem();
/* This is done because to allow SIGSEGV to be delivered inside a SEGV
* handler. This can happen in copy_user, and if SEGV is disabled,
* the process will die.
*/
if(sig == SIGSEGV)
change_sig(SIGSEGV, 1);
/* This is done because to allow SIGSEGV to be delivered inside a SEGV
* handler. This can happen in copy_user, and if SEGV is disabled,
* the process will die.
......
......@@ -205,6 +205,8 @@ static int __init set_tty_log_fd(char *name, int *add)
printf("set_tty_log_fd - strtoul failed on '%s'\n", name);
tty_log_fd = -1;
}
*add = 0;
return 0;
}
......
......@@ -321,6 +321,11 @@ int linux_main(int argc, char **argv)
uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
&host_task_size, &task_size);
/* Need to check this early because mmapping happens before the
* kernel is running.
*/
check_tmpexec();
brk_start = (unsigned long) sbrk(0);
CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
/* Increase physical memory size for exec-shield users
......@@ -400,9 +405,9 @@ extern int uml_exitcode;
static int panic_exit(struct notifier_block *self, unsigned long unused1,
void *unused2)
{
#ifdef CONFIG_MAGIC_SYSRQ
handle_sysrq('p', &current->thread.regs, NULL);
#endif
bust_spinlocks(1);
show_regs(&(current->thread.regs));
bust_spinlocks(0);
uml_exitcode = 1;
machine_halt();
return(0);
......
......@@ -54,6 +54,7 @@ static int __init set_umid(char *name, int is_random,
static int __init set_umid_arg(char *name, int *add)
{
*add = 0;
return(set_umid(name, 0, printf));
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment