Merge ../linux-2.6/
Conflicts: drivers/scsi/aacraid/comminit.c Fixed up by removing the now renamed CONFIG_IOMMU option from aacraid Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
5
CREDITS
5
CREDITS
@@ -24,6 +24,11 @@ S: C. Negri 6, bl. D3
|
|||||||
S: Iasi 6600
|
S: Iasi 6600
|
||||||
S: Romania
|
S: Romania
|
||||||
|
|
||||||
|
N: Mark Adler
|
||||||
|
E: madler@alumni.caltech.edu
|
||||||
|
W: http://alumnus.caltech.edu/~madler/
|
||||||
|
D: zlib decompression
|
||||||
|
|
||||||
N: Monalisa Agrawal
|
N: Monalisa Agrawal
|
||||||
E: magrawal@nortelnetworks.com
|
E: magrawal@nortelnetworks.com
|
||||||
D: Basic Interphase 5575 driver with UBR and ABR support.
|
D: Basic Interphase 5575 driver with UBR and ABR support.
|
||||||
|
@@ -1590,7 +1590,7 @@ the amount of locking which needs to be done.
|
|||||||
<para>
|
<para>
|
||||||
Our final dilemma is this: when can we actually destroy the
|
Our final dilemma is this: when can we actually destroy the
|
||||||
removed element? Remember, a reader might be stepping through
|
removed element? Remember, a reader might be stepping through
|
||||||
this element in the list right now: it we free this element and
|
this element in the list right now: if we free this element and
|
||||||
the <symbol>next</symbol> pointer changes, the reader will jump
|
the <symbol>next</symbol> pointer changes, the reader will jump
|
||||||
off into garbage and crash. We need to wait until we know that
|
off into garbage and crash. We need to wait until we know that
|
||||||
all the readers who were traversing the list when we deleted the
|
all the readers who were traversing the list when we deleted the
|
||||||
|
@@ -7,7 +7,7 @@ The CONFIG_RCU_TORTURE_TEST config option is available for all RCU
|
|||||||
implementations. It creates an rcutorture kernel module that can
|
implementations. It creates an rcutorture kernel module that can
|
||||||
be loaded to run a torture test. The test periodically outputs
|
be loaded to run a torture test. The test periodically outputs
|
||||||
status messages via printk(), which can be examined via the dmesg
|
status messages via printk(), which can be examined via the dmesg
|
||||||
command (perhaps grepping for "rcutorture"). The test is started
|
command (perhaps grepping for "torture"). The test is started
|
||||||
when the module is loaded, and stops when the module is unloaded.
|
when the module is loaded, and stops when the module is unloaded.
|
||||||
|
|
||||||
However, actually setting this config option to "y" results in the system
|
However, actually setting this config option to "y" results in the system
|
||||||
@@ -35,6 +35,19 @@ stat_interval The number of seconds between output of torture
|
|||||||
be printed -only- when the module is unloaded, and this
|
be printed -only- when the module is unloaded, and this
|
||||||
is the default.
|
is the default.
|
||||||
|
|
||||||
|
shuffle_interval
|
||||||
|
The number of seconds to keep the test threads affinitied
|
||||||
|
to a particular subset of the CPUs. Used in conjunction
|
||||||
|
with test_no_idle_hz.
|
||||||
|
|
||||||
|
test_no_idle_hz Whether or not to test the ability of RCU to operate in
|
||||||
|
a kernel that disables the scheduling-clock interrupt to
|
||||||
|
idle CPUs. Boolean parameter, "1" to test, "0" otherwise.
|
||||||
|
|
||||||
|
torture_type The type of RCU to test: "rcu" for the rcu_read_lock()
|
||||||
|
API, "rcu_bh" for the rcu_read_lock_bh() API, and "srcu"
|
||||||
|
for the "srcu_read_lock()" API.
|
||||||
|
|
||||||
verbose Enable debug printk()s. Default is disabled.
|
verbose Enable debug printk()s. Default is disabled.
|
||||||
|
|
||||||
|
|
||||||
@@ -42,14 +55,14 @@ OUTPUT
|
|||||||
|
|
||||||
The statistics output is as follows:
|
The statistics output is as follows:
|
||||||
|
|
||||||
rcutorture: --- Start of test: nreaders=16 stat_interval=0 verbose=0
|
rcu-torture: --- Start of test: nreaders=16 stat_interval=0 verbose=0
|
||||||
rcutorture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915
|
rcu-torture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915
|
||||||
rcutorture: Reader Pipe: 1466408 9747 0 0 0 0 0 0 0 0 0
|
rcu-torture: Reader Pipe: 1466408 9747 0 0 0 0 0 0 0 0 0
|
||||||
rcutorture: Reader Batch: 1464477 11678 0 0 0 0 0 0 0 0
|
rcu-torture: Reader Batch: 1464477 11678 0 0 0 0 0 0 0 0
|
||||||
rcutorture: Free-Block Circulation: 1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0
|
rcu-torture: Free-Block Circulation: 1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0
|
||||||
rcutorture: --- End of test
|
rcu-torture: --- End of test
|
||||||
|
|
||||||
The command "dmesg | grep rcutorture:" will extract this information on
|
The command "dmesg | grep torture:" will extract this information on
|
||||||
most systems. On more esoteric configurations, it may be necessary to
|
most systems. On more esoteric configurations, it may be necessary to
|
||||||
use other commands to access the output of the printk()s used by
|
use other commands to access the output of the printk()s used by
|
||||||
the RCU torture test. The printk()s use KERN_ALERT, so they should
|
the RCU torture test. The printk()s use KERN_ALERT, so they should
|
||||||
@@ -115,8 +128,9 @@ The following script may be used to torture RCU:
|
|||||||
modprobe rcutorture
|
modprobe rcutorture
|
||||||
sleep 100
|
sleep 100
|
||||||
rmmod rcutorture
|
rmmod rcutorture
|
||||||
dmesg | grep rcutorture:
|
dmesg | grep torture:
|
||||||
|
|
||||||
The output can be manually inspected for the error flag of "!!!".
|
The output can be manually inspected for the error flag of "!!!".
|
||||||
One could of course create a more elaborate script that automatically
|
One could of course create a more elaborate script that automatically
|
||||||
checked for such errors.
|
checked for such errors. The "rmmod" command forces a "SUCCESS" or
|
||||||
|
"FAILURE" indication to be printk()ed.
|
||||||
|
@@ -7,11 +7,13 @@ Introduction
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
|
The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
|
||||||
by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 and
|
by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
|
||||||
the S3C2440 are supported CPUs.
|
S3C2440 and S3C2442 devices are supported.
|
||||||
|
|
||||||
Support for the S3C2400 series is in progress.
|
Support for the S3C2400 series is in progress.
|
||||||
|
|
||||||
|
Support for the S3C2412 and S3C2413 CPUs is being merged.
|
||||||
|
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
@@ -43,9 +45,18 @@ Machines
|
|||||||
|
|
||||||
Samsung's own development board, geared for PDA work.
|
Samsung's own development board, geared for PDA work.
|
||||||
|
|
||||||
|
Samsung/Aiji SMDK2412
|
||||||
|
|
||||||
|
The S3C2412 version of the SMDK2440.
|
||||||
|
|
||||||
|
Samsung/Aiji SMDK2413
|
||||||
|
|
||||||
|
The S3C2412 version of the SMDK2440.
|
||||||
|
|
||||||
Samsung/Meritech SMDK2440
|
Samsung/Meritech SMDK2440
|
||||||
|
|
||||||
The S3C2440 compatible version of the SMDK2440
|
The S3C2440 compatible version of the SMDK2440, which has the
|
||||||
|
option of an S3C2440 or S3C2442 CPU module.
|
||||||
|
|
||||||
Thorcom VR1000
|
Thorcom VR1000
|
||||||
|
|
||||||
@@ -211,24 +222,6 @@ Port Contributors
|
|||||||
Lucas Correia Villa Real (S3C2400 port)
|
Lucas Correia Villa Real (S3C2400 port)
|
||||||
|
|
||||||
|
|
||||||
Document Changes
|
|
||||||
----------------
|
|
||||||
|
|
||||||
05 Sep 2004 - BJD - Added Document Changes section
|
|
||||||
05 Sep 2004 - BJD - Added Klaus Fetscher to list of contributors
|
|
||||||
25 Oct 2004 - BJD - Added Dimitry Andric to list of contributors
|
|
||||||
25 Oct 2004 - BJD - Updated the MTD from the 2.6.9 merge
|
|
||||||
21 Jan 2005 - BJD - Added rx3715, added Shannon to contributors
|
|
||||||
10 Feb 2005 - BJD - Added Guillaume Gourat to contributors
|
|
||||||
02 Mar 2005 - BJD - Added SMDK2440 to list of machines
|
|
||||||
06 Mar 2005 - BJD - Added Christer Weinigel
|
|
||||||
08 Mar 2005 - BJD - Added LCVR to list of people, updated introduction
|
|
||||||
08 Mar 2005 - BJD - Added section on adding machines
|
|
||||||
09 Sep 2005 - BJD - Added section on platform data
|
|
||||||
11 Feb 2006 - BJD - Added I2C, RTC and Watchdog sections
|
|
||||||
11 Feb 2006 - BJD - Added Osiris machine, and S3C2400 information
|
|
||||||
|
|
||||||
|
|
||||||
Document Author
|
Document Author
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
120
Documentation/arm/Samsung-S3C24XX/S3C2412.txt
Normal file
120
Documentation/arm/Samsung-S3C24XX/S3C2412.txt
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
S3C2412 ARM Linux Overview
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
The S3C2412 is part of the S3C24XX range of ARM9 System-on-Chip CPUs
|
||||||
|
from Samsung. This part has an ARM926-EJS core, capable of running up
|
||||||
|
to 266MHz (see data-sheet for more information)
|
||||||
|
|
||||||
|
|
||||||
|
Clock
|
||||||
|
-----
|
||||||
|
|
||||||
|
The core clock code provides a set of clocks to the drivers, and allows
|
||||||
|
for source selection and a number of other features.
|
||||||
|
|
||||||
|
|
||||||
|
Power
|
||||||
|
-----
|
||||||
|
|
||||||
|
No support for suspend/resume to RAM in the current system.
|
||||||
|
|
||||||
|
|
||||||
|
DMA
|
||||||
|
---
|
||||||
|
|
||||||
|
No current support for DMA.
|
||||||
|
|
||||||
|
|
||||||
|
GPIO
|
||||||
|
----
|
||||||
|
|
||||||
|
There is support for setting the GPIO to input/output/special function
|
||||||
|
and reading or writing to them.
|
||||||
|
|
||||||
|
|
||||||
|
UART
|
||||||
|
----
|
||||||
|
|
||||||
|
The UART hardware is similar to the S3C2440, and is supported by the
|
||||||
|
s3c2410 driver in the drivers/serial directory.
|
||||||
|
|
||||||
|
|
||||||
|
NAND
|
||||||
|
----
|
||||||
|
|
||||||
|
The NAND hardware is similar to the S3C2440, and is supported by the
|
||||||
|
s3c2410 driver in the drivers/mtd/nand directory.
|
||||||
|
|
||||||
|
|
||||||
|
USB Host
|
||||||
|
--------
|
||||||
|
|
||||||
|
The USB hardware is similar to the S3C2410, with extended clock source
|
||||||
|
control. The OHCI portion is supported by the ohci-s3c2410 driver, and
|
||||||
|
the clock control selection is supported by the core clock code.
|
||||||
|
|
||||||
|
|
||||||
|
USB Device
|
||||||
|
----------
|
||||||
|
|
||||||
|
No current support in the kernel
|
||||||
|
|
||||||
|
|
||||||
|
IRQs
|
||||||
|
----
|
||||||
|
|
||||||
|
All the standard, and external interrupt sources are supported. The
|
||||||
|
extra sub-sources are not yet supported.
|
||||||
|
|
||||||
|
|
||||||
|
RTC
|
||||||
|
---
|
||||||
|
|
||||||
|
The RTC hardware is similar to the S3C2410, and is supported by the
|
||||||
|
s3c2410-rtc driver.
|
||||||
|
|
||||||
|
|
||||||
|
Watchdog
|
||||||
|
--------
|
||||||
|
|
||||||
|
The watchdog harware is the same as the S3C2410, and is supported by
|
||||||
|
the s3c2410_wdt driver.
|
||||||
|
|
||||||
|
|
||||||
|
MMC/SD/SDIO
|
||||||
|
-----------
|
||||||
|
|
||||||
|
No current support for the MMC/SD/SDIO block.
|
||||||
|
|
||||||
|
IIC
|
||||||
|
---
|
||||||
|
|
||||||
|
The IIC hardware is the same as the S3C2410, and is supported by the
|
||||||
|
i2c-s3c24xx driver.
|
||||||
|
|
||||||
|
|
||||||
|
IIS
|
||||||
|
---
|
||||||
|
|
||||||
|
No current support for the IIS interface.
|
||||||
|
|
||||||
|
|
||||||
|
SPI
|
||||||
|
---
|
||||||
|
|
||||||
|
No current support for the SPI interfaces.
|
||||||
|
|
||||||
|
|
||||||
|
ATA
|
||||||
|
---
|
||||||
|
|
||||||
|
No current support for the on-board ATA block.
|
||||||
|
|
||||||
|
|
||||||
|
Document Author
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Ben Dooks, (c) 2006 Simtec Electronics
|
21
Documentation/arm/Samsung-S3C24XX/S3C2413.txt
Normal file
21
Documentation/arm/Samsung-S3C24XX/S3C2413.txt
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
S3C2413 ARM Linux Overview
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
The S3C2413 is an extended version of the S3C2412, with an camera
|
||||||
|
interface and mobile DDR memory support. See the S3C2412 support
|
||||||
|
documentation for more information.
|
||||||
|
|
||||||
|
|
||||||
|
Camera Interface
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This block is currently not supported.
|
||||||
|
|
||||||
|
|
||||||
|
Document Author
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Ben Dooks, (c) 2006 Simtec Electronics
|
@@ -157,13 +157,13 @@ For example, smp_mb__before_atomic_dec() can be used like so:
|
|||||||
smp_mb__before_atomic_dec();
|
smp_mb__before_atomic_dec();
|
||||||
atomic_dec(&obj->ref_count);
|
atomic_dec(&obj->ref_count);
|
||||||
|
|
||||||
It makes sure that all memory operations preceeding the atomic_dec()
|
It makes sure that all memory operations preceding the atomic_dec()
|
||||||
call are strongly ordered with respect to the atomic counter
|
call are strongly ordered with respect to the atomic counter
|
||||||
operation. In the above example, it guarentees that the assignment of
|
operation. In the above example, it guarantees that the assignment of
|
||||||
"1" to obj->dead will be globally visible to other cpus before the
|
"1" to obj->dead will be globally visible to other cpus before the
|
||||||
atomic counter decrement.
|
atomic counter decrement.
|
||||||
|
|
||||||
Without the explicitl smp_mb__before_atomic_dec() call, the
|
Without the explicit smp_mb__before_atomic_dec() call, the
|
||||||
implementation could legally allow the atomic counter update visible
|
implementation could legally allow the atomic counter update visible
|
||||||
to other cpus before the "obj->dead = 1;" assignment.
|
to other cpus before the "obj->dead = 1;" assignment.
|
||||||
|
|
||||||
@@ -173,11 +173,11 @@ ordering with respect to memory operations after an atomic_dec() call
|
|||||||
(smp_mb__{before,after}_atomic_inc()).
|
(smp_mb__{before,after}_atomic_inc()).
|
||||||
|
|
||||||
A missing memory barrier in the cases where they are required by the
|
A missing memory barrier in the cases where they are required by the
|
||||||
atomic_t implementation above can have disasterous results. Here is
|
atomic_t implementation above can have disastrous results. Here is
|
||||||
an example, which follows a pattern occuring frequently in the Linux
|
an example, which follows a pattern occurring frequently in the Linux
|
||||||
kernel. It is the use of atomic counters to implement reference
|
kernel. It is the use of atomic counters to implement reference
|
||||||
counting, and it works such that once the counter falls to zero it can
|
counting, and it works such that once the counter falls to zero it can
|
||||||
be guarenteed that no other entity can be accessing the object:
|
be guaranteed that no other entity can be accessing the object:
|
||||||
|
|
||||||
static void obj_list_add(struct obj *obj)
|
static void obj_list_add(struct obj *obj)
|
||||||
{
|
{
|
||||||
@@ -291,9 +291,9 @@ to the size of an "unsigned long" C data type, and are least of that
|
|||||||
size. The endianness of the bits within each "unsigned long" are the
|
size. The endianness of the bits within each "unsigned long" are the
|
||||||
native endianness of the cpu.
|
native endianness of the cpu.
|
||||||
|
|
||||||
void set_bit(unsigned long nr, volatils unsigned long *addr);
|
void set_bit(unsigned long nr, volatile unsigned long *addr);
|
||||||
void clear_bit(unsigned long nr, volatils unsigned long *addr);
|
void clear_bit(unsigned long nr, volatile unsigned long *addr);
|
||||||
void change_bit(unsigned long nr, volatils unsigned long *addr);
|
void change_bit(unsigned long nr, volatile unsigned long *addr);
|
||||||
|
|
||||||
These routines set, clear, and change, respectively, the bit number
|
These routines set, clear, and change, respectively, the bit number
|
||||||
indicated by "nr" on the bit mask pointed to by "ADDR".
|
indicated by "nr" on the bit mask pointed to by "ADDR".
|
||||||
@@ -301,9 +301,9 @@ indicated by "nr" on the bit mask pointed to by "ADDR".
|
|||||||
They must execute atomically, yet there are no implicit memory barrier
|
They must execute atomically, yet there are no implicit memory barrier
|
||||||
semantics required of these interfaces.
|
semantics required of these interfaces.
|
||||||
|
|
||||||
int test_and_set_bit(unsigned long nr, volatils unsigned long *addr);
|
int test_and_set_bit(unsigned long nr, volatile unsigned long *addr);
|
||||||
int test_and_clear_bit(unsigned long nr, volatils unsigned long *addr);
|
int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr);
|
||||||
int test_and_change_bit(unsigned long nr, volatils unsigned long *addr);
|
int test_and_change_bit(unsigned long nr, volatile unsigned long *addr);
|
||||||
|
|
||||||
Like the above, except that these routines return a boolean which
|
Like the above, except that these routines return a boolean which
|
||||||
indicates whether the changed bit was set _BEFORE_ the atomic bit
|
indicates whether the changed bit was set _BEFORE_ the atomic bit
|
||||||
@@ -335,7 +335,7 @@ subsequent memory operation is made visible. For example:
|
|||||||
/* ... */;
|
/* ... */;
|
||||||
obj->killed = 1;
|
obj->killed = 1;
|
||||||
|
|
||||||
The implementation of test_and_set_bit() must guarentee that
|
The implementation of test_and_set_bit() must guarantee that
|
||||||
"obj->dead = 1;" is visible to cpus before the atomic memory operation
|
"obj->dead = 1;" is visible to cpus before the atomic memory operation
|
||||||
done by test_and_set_bit() becomes visible. Likewise, the atomic
|
done by test_and_set_bit() becomes visible. Likewise, the atomic
|
||||||
memory operation done by test_and_set_bit() must become visible before
|
memory operation done by test_and_set_bit() must become visible before
|
||||||
@@ -474,7 +474,7 @@ Now, as far as memory barriers go, as long as spin_lock()
|
|||||||
strictly orders all subsequent memory operations (including
|
strictly orders all subsequent memory operations (including
|
||||||
the cas()) with respect to itself, things will be fine.
|
the cas()) with respect to itself, things will be fine.
|
||||||
|
|
||||||
Said another way, _atomic_dec_and_lock() must guarentee that
|
Said another way, _atomic_dec_and_lock() must guarantee that
|
||||||
a counter dropping to zero is never made visible before the
|
a counter dropping to zero is never made visible before the
|
||||||
spinlock being acquired.
|
spinlock being acquired.
|
||||||
|
|
||||||
|
144
Documentation/console/console.txt
Normal file
144
Documentation/console/console.txt
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
Console Drivers
|
||||||
|
===============
|
||||||
|
|
||||||
|
The linux kernel has 2 general types of console drivers. The first type is
|
||||||
|
assigned by the kernel to all the virtual consoles during the boot process.
|
||||||
|
This type will be called 'system driver', and only one system driver is allowed
|
||||||
|
to exist. The system driver is persistent and it can never be unloaded, though
|
||||||
|
it may become inactive.
|
||||||
|
|
||||||
|
The second type has to be explicitly loaded and unloaded. This will be called
|
||||||
|
'modular driver' by this document. Multiple modular drivers can coexist at
|
||||||
|
any time with each driver sharing the console with other drivers including
|
||||||
|
the system driver. However, modular drivers cannot take over the console
|
||||||
|
that is currently occupied by another modular driver. (Exception: Drivers that
|
||||||
|
call take_over_console() will succeed in the takeover regardless of the type
|
||||||
|
of driver occupying the consoles.) They can only take over the console that is
|
||||||
|
occupied by the system driver. In the same token, if the modular driver is
|
||||||
|
released by the console, the system driver will take over.
|
||||||
|
|
||||||
|
Modular drivers, from the programmer's point of view, has to call:
|
||||||
|
|
||||||
|
take_over_console() - load and bind driver to console layer
|
||||||
|
give_up_console() - unbind and unload driver
|
||||||
|
|
||||||
|
In newer kernels, the following are also available:
|
||||||
|
|
||||||
|
register_con_driver()
|
||||||
|
unregister_con_driver()
|
||||||
|
|
||||||
|
If sysfs is enabled, the contents of /sys/class/vtconsole can be
|
||||||
|
examined. This shows the console backends currently registered by the
|
||||||
|
system which are named vtcon<n> where <n> is an integer fro 0 to 15. Thus:
|
||||||
|
|
||||||
|
ls /sys/class/vtconsole
|
||||||
|
. .. vtcon0 vtcon1
|
||||||
|
|
||||||
|
Each directory in /sys/class/vtconsole has 3 files:
|
||||||
|
|
||||||
|
ls /sys/class/vtconsole/vtcon0
|
||||||
|
. .. bind name uevent
|
||||||
|
|
||||||
|
What do these files signify?
|
||||||
|
|
||||||
|
1. bind - this is a read/write file. It shows the status of the driver if
|
||||||
|
read, or acts to bind or unbind the driver to the virtual consoles
|
||||||
|
when written to. The possible values are:
|
||||||
|
|
||||||
|
0 - means the driver is not bound and if echo'ed, commands the driver
|
||||||
|
to unbind
|
||||||
|
|
||||||
|
1 - means the driver is bound and if echo'ed, commands the driver to
|
||||||
|
bind
|
||||||
|
|
||||||
|
2. name - read-only file. Shows the name of the driver in this format:
|
||||||
|
|
||||||
|
cat /sys/class/vtconsole/vtcon0/name
|
||||||
|
(S) VGA+
|
||||||
|
|
||||||
|
'(S)' stands for a (S)ystem driver, ie, it cannot be directly
|
||||||
|
commanded to bind or unbind
|
||||||
|
|
||||||
|
'VGA+' is the name of the driver
|
||||||
|
|
||||||
|
cat /sys/class/vtconsole/vtcon1/name
|
||||||
|
(M) frame buffer device
|
||||||
|
|
||||||
|
In this case, '(M)' stands for a (M)odular driver, one that can be
|
||||||
|
directly commanded to bind or unbind.
|
||||||
|
|
||||||
|
3. uevent - ignore this file
|
||||||
|
|
||||||
|
When unbinding, the modular driver is detached first, and then the system
|
||||||
|
driver takes over the consoles vacated by the driver. Binding, on the other
|
||||||
|
hand, will bind the driver to the consoles that are currently occupied by a
|
||||||
|
system driver.
|
||||||
|
|
||||||
|
NOTE1: Binding and binding must be selected in Kconfig. It's under:
|
||||||
|
|
||||||
|
Device Drivers -> Character devices -> Support for binding and unbinding
|
||||||
|
console drivers
|
||||||
|
|
||||||
|
NOTE2: If any of the virtual consoles are in KD_GRAPHICS mode, then binding or
|
||||||
|
unbinding will not succeed. An example of an application that sets the console
|
||||||
|
to KD_GRAPHICS is X.
|
||||||
|
|
||||||
|
How useful is this feature? This is very useful for console driver
|
||||||
|
developers. By unbinding the driver from the console layer, one can unload the
|
||||||
|
driver, make changes, recompile, reload and rebind the driver without any need
|
||||||
|
for rebooting the kernel. For regular users who may want to switch from
|
||||||
|
framebuffer console to VGA console and vice versa, this feature also makes
|
||||||
|
this possible. (NOTE NOTE NOTE: Please read fbcon.txt under Documentation/fb
|
||||||
|
for more details).
|
||||||
|
|
||||||
|
Notes for developers:
|
||||||
|
=====================
|
||||||
|
|
||||||
|
take_over_console() is now broken up into:
|
||||||
|
|
||||||
|
register_con_driver()
|
||||||
|
bind_con_driver() - private function
|
||||||
|
|
||||||
|
give_up_console() is a wrapper to unregister_con_driver(), and a driver must
|
||||||
|
be fully unbound for this call to succeed. con_is_bound() will check if the
|
||||||
|
driver is bound or not.
|
||||||
|
|
||||||
|
Guidelines for console driver writers:
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
In order for binding to and unbinding from the console to properly work,
|
||||||
|
console drivers must follow these guidelines:
|
||||||
|
|
||||||
|
1. All drivers, except system drivers, must call either register_con_driver()
|
||||||
|
or take_over_console(). register_con_driver() will just add the driver to
|
||||||
|
the console's internal list. It won't take over the
|
||||||
|
console. take_over_console(), as it name implies, will also take over (or
|
||||||
|
bind to) the console.
|
||||||
|
|
||||||
|
2. All resources allocated during con->con_init() must be released in
|
||||||
|
con->con_deinit().
|
||||||
|
|
||||||
|
3. All resources allocated in con->con_startup() must be released when the
|
||||||
|
driver, which was previously bound, becomes unbound. The console layer
|
||||||
|
does not have a complementary call to con->con_startup() so it's up to the
|
||||||
|
driver to check when it's legal to release these resources. Calling
|
||||||
|
con_is_bound() in con->con_deinit() will help. If the call returned
|
||||||
|
false(), then it's safe to release the resources. This balance has to be
|
||||||
|
ensured because con->con_startup() can be called again when a request to
|
||||||
|
rebind the driver to the console arrives.
|
||||||
|
|
||||||
|
4. Upon exit of the driver, ensure that the driver is totally unbound. If the
|
||||||
|
condition is satisfied, then the driver must call unregister_con_driver()
|
||||||
|
or give_up_console().
|
||||||
|
|
||||||
|
5. unregister_con_driver() can also be called on conditions which make it
|
||||||
|
impossible for the driver to service console requests. This can happen
|
||||||
|
with the framebuffer console that suddenly lost all of its drivers.
|
||||||
|
|
||||||
|
The current crop of console drivers should still work correctly, but binding
|
||||||
|
and unbinding them may cause problems. With minimal fixes, these drivers can
|
||||||
|
be made to work correctly.
|
||||||
|
|
||||||
|
==========================
|
||||||
|
Antonino Daplas <adaplas@pol.net>
|
||||||
|
|
@@ -18,7 +18,7 @@ Traditional driver models implemented some sort of tree-like structure
|
|||||||
(sometimes just a list) for the devices they control. There wasn't any
|
(sometimes just a list) for the devices they control. There wasn't any
|
||||||
uniformity across the different bus types.
|
uniformity across the different bus types.
|
||||||
|
|
||||||
The current driver model provides a comon, uniform data model for describing
|
The current driver model provides a common, uniform data model for describing
|
||||||
a bus and the devices that can appear under the bus. The unified bus
|
a bus and the devices that can appear under the bus. The unified bus
|
||||||
model includes a set of common attributes which all busses carry, and a set
|
model includes a set of common attributes which all busses carry, and a set
|
||||||
of common callbacks, such as device discovery during bus probing, bus
|
of common callbacks, such as device discovery during bus probing, bus
|
||||||
|
@@ -135,10 +135,10 @@ C. Boot options
|
|||||||
|
|
||||||
The angle can be changed anytime afterwards by 'echoing' the same
|
The angle can be changed anytime afterwards by 'echoing' the same
|
||||||
numbers to any one of the 2 attributes found in
|
numbers to any one of the 2 attributes found in
|
||||||
/sys/class/graphics/fb{x}
|
/sys/class/graphics/fbcon
|
||||||
|
|
||||||
con_rotate - rotate the display of the active console
|
rotate - rotate the display of the active console
|
||||||
con_rotate_all - rotate the display of all consoles
|
rotate_all - rotate the display of all consoles
|
||||||
|
|
||||||
Console rotation will only become available if Console Rotation
|
Console rotation will only become available if Console Rotation
|
||||||
Support is compiled in your kernel.
|
Support is compiled in your kernel.
|
||||||
@@ -148,5 +148,177 @@ C. Boot options
|
|||||||
Actually, the underlying fb driver is totally ignorant of console
|
Actually, the underlying fb driver is totally ignorant of console
|
||||||
rotation.
|
rotation.
|
||||||
|
|
||||||
---
|
C. Attaching, Detaching and Unloading
|
||||||
|
|
||||||
|
Before going on on how to attach, detach and unload the framebuffer console, an
|
||||||
|
illustration of the dependencies may help.
|
||||||
|
|
||||||
|
The console layer, as with most subsystems, needs a driver that interfaces with
|
||||||
|
the hardware. Thus, in a VGA console:
|
||||||
|
|
||||||
|
console ---> VGA driver ---> hardware.
|
||||||
|
|
||||||
|
Assuming the VGA driver can be unloaded, one must first unbind the VGA driver
|
||||||
|
from the console layer before unloading the driver. The VGA driver cannot be
|
||||||
|
unloaded if it is still bound to the console layer. (See
|
||||||
|
Documentation/console/console.txt for more information).
|
||||||
|
|
||||||
|
This is more complicated in the case of the the framebuffer console (fbcon),
|
||||||
|
because fbcon is an intermediate layer between the console and the drivers:
|
||||||
|
|
||||||
|
console ---> fbcon ---> fbdev drivers ---> hardware
|
||||||
|
|
||||||
|
The fbdev drivers cannot be unloaded if it's bound to fbcon, and fbcon cannot
|
||||||
|
be unloaded if it's bound to the console layer.
|
||||||
|
|
||||||
|
So to unload the fbdev drivers, one must first unbind fbcon from the console,
|
||||||
|
then unbind the fbdev drivers from fbcon. Fortunately, unbinding fbcon from
|
||||||
|
the console layer will automatically unbind framebuffer drivers from
|
||||||
|
fbcon. Thus, there is no need to explicitly unbind the fbdev drivers from
|
||||||
|
fbcon.
|
||||||
|
|
||||||
|
So, how do we unbind fbcon from the console? Part of the answer is in
|
||||||
|
Documentation/console/console.txt. To summarize:
|
||||||
|
|
||||||
|
Echo a value to the bind file that represents the framebuffer console
|
||||||
|
driver. So assuming vtcon1 represents fbcon, then:
|
||||||
|
|
||||||
|
echo 1 > sys/class/vtconsole/vtcon1/bind - attach framebuffer console to
|
||||||
|
console layer
|
||||||
|
echo 0 > sys/class/vtconsole/vtcon1/bind - detach framebuffer console from
|
||||||
|
console layer
|
||||||
|
|
||||||
|
If fbcon is detached from the console layer, your boot console driver (which is
|
||||||
|
usually VGA text mode) will take over. A few drivers (rivafb and i810fb) will
|
||||||
|
restore VGA text mode for you. With the rest, before detaching fbcon, you
|
||||||
|
must take a few additional steps to make sure that your VGA text mode is
|
||||||
|
restored properly. The following is one of the several methods that you can do:
|
||||||
|
|
||||||
|
1. Download or install vbetool. This utility is included with most
|
||||||
|
distributions nowadays, and is usually part of the suspend/resume tool.
|
||||||
|
|
||||||
|
2. In your kernel configuration, ensure that CONFIG_FRAMEBUFFER_CONSOLE is set
|
||||||
|
to 'y' or 'm'. Enable one or more of your favorite framebuffer drivers.
|
||||||
|
|
||||||
|
3. Boot into text mode and as root run:
|
||||||
|
|
||||||
|
vbetool vbestate save > <vga state file>
|
||||||
|
|
||||||
|
The above command saves the register contents of your graphics
|
||||||
|
hardware to <vga state file>. You need to do this step only once as
|
||||||
|
the state file can be reused.
|
||||||
|
|
||||||
|
4. If fbcon is compiled as a module, load fbcon by doing:
|
||||||
|
|
||||||
|
modprobe fbcon
|
||||||
|
|
||||||
|
5. Now to detach fbcon:
|
||||||
|
|
||||||
|
vbetool vbestate restore < <vga state file> && \
|
||||||
|
echo 0 > /sys/class/vtconsole/vtcon1/bind
|
||||||
|
|
||||||
|
6. That's it, you're back to VGA mode. And if you compiled fbcon as a module,
|
||||||
|
you can unload it by 'rmmod fbcon'
|
||||||
|
|
||||||
|
7. To reattach fbcon:
|
||||||
|
|
||||||
|
echo 1 > /sys/class/vtconsole/vtcon1/bind
|
||||||
|
|
||||||
|
8. Once fbcon is unbound, all drivers registered to the system will also
|
||||||
|
become unbound. This means that fbcon and individual framebuffer drivers
|
||||||
|
can be unloaded or reloaded at will. Reloading the drivers or fbcon will
|
||||||
|
automatically bind the console, fbcon and the drivers together. Unloading
|
||||||
|
all the drivers without unloading fbcon will make it impossible for the
|
||||||
|
console to bind fbcon.
|
||||||
|
|
||||||
|
Notes for vesafb users:
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Unfortunately, if your bootline includes a vga=xxx parameter that sets the
|
||||||
|
hardware in graphics mode, such as when loading vesafb, vgacon will not load.
|
||||||
|
Instead, vgacon will replace the default boot console with dummycon, and you
|
||||||
|
won't get any display after detaching fbcon. Your machine is still alive, so
|
||||||
|
you can reattach vesafb. However, to reattach vesafb, you need to do one of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
Variation 1:
|
||||||
|
|
||||||
|
a. Before detaching fbcon, do
|
||||||
|
|
||||||
|
vbetool vbemode save > <vesa state file> # do once for each vesafb mode,
|
||||||
|
# the file can be reused
|
||||||
|
|
||||||
|
b. Detach fbcon as in step 5.
|
||||||
|
|
||||||
|
c. Attach fbcon
|
||||||
|
|
||||||
|
vbetool vbestate restore < <vesa state file> && \
|
||||||
|
echo 1 > /sys/class/vtconsole/vtcon1/bind
|
||||||
|
|
||||||
|
Variation 2:
|
||||||
|
|
||||||
|
a. Before detaching fbcon, do:
|
||||||
|
echo <ID> > /sys/class/tty/console/bind
|
||||||
|
|
||||||
|
|
||||||
|
vbetool vbemode get
|
||||||
|
|
||||||
|
b. Take note of the mode number
|
||||||
|
|
||||||
|
b. Detach fbcon as in step 5.
|
||||||
|
|
||||||
|
c. Attach fbcon:
|
||||||
|
|
||||||
|
vbetool vbemode set <mode number> && \
|
||||||
|
echo 1 > /sys/class/vtconsole/vtcon1/bind
|
||||||
|
|
||||||
|
Samples:
|
||||||
|
========
|
||||||
|
|
||||||
|
Here are 2 sample bash scripts that you can use to bind or unbind the
|
||||||
|
framebuffer console driver if you are in an X86 box:
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
#!/bin/bash
|
||||||
|
# Unbind fbcon
|
||||||
|
|
||||||
|
# Change this to where your actual vgastate file is located
|
||||||
|
# Or Use VGASTATE=$1 to indicate the state file at runtime
|
||||||
|
VGASTATE=/tmp/vgastate
|
||||||
|
|
||||||
|
# path to vbetool
|
||||||
|
VBETOOL=/usr/local/bin
|
||||||
|
|
||||||
|
|
||||||
|
for (( i = 0; i < 16; i++))
|
||||||
|
do
|
||||||
|
if test -x /sys/class/vtconsole/vtcon$i; then
|
||||||
|
if [ `cat /sys/class/vtconsole/vtcon$i/name | grep -c "frame buffer"` \
|
||||||
|
= 1 ]; then
|
||||||
|
if test -x $VBETOOL/vbetool; then
|
||||||
|
echo Unbinding vtcon$i
|
||||||
|
$VBETOOL/vbetool vbestate restore < $VGASTATE
|
||||||
|
echo 0 > /sys/class/vtconsole/vtcon$i/bind
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
#!/bin/bash
|
||||||
|
# Bind fbcon
|
||||||
|
|
||||||
|
for (( i = 0; i < 16; i++))
|
||||||
|
do
|
||||||
|
if test -x /sys/class/vtconsole/vtcon$i; then
|
||||||
|
if [ `cat /sys/class/vtconsole/vtcon$i/name | grep -c "frame buffer"` \
|
||||||
|
= 1 ]; then
|
||||||
|
echo Unbinding vtcon$i
|
||||||
|
echo 1 > /sys/class/vtconsole/vtcon$i/bind
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
Antonino Daplas <adaplas@pol.net>
|
Antonino Daplas <adaplas@pol.net>
|
||||||
|
@@ -113,6 +113,14 @@ noquota
|
|||||||
grpquota
|
grpquota
|
||||||
usrquota
|
usrquota
|
||||||
|
|
||||||
|
bh (*) ext3 associates buffer heads to data pages to
|
||||||
|
nobh (a) cache disk block mapping information
|
||||||
|
(b) link pages into transaction to provide
|
||||||
|
ordering guarantees.
|
||||||
|
"bh" option forces use of buffer heads.
|
||||||
|
"nobh" option tries to avoid associating buffer
|
||||||
|
heads (supported only for "writeback" mode).
|
||||||
|
|
||||||
|
|
||||||
Specification
|
Specification
|
||||||
=============
|
=============
|
||||||
|
@@ -1123,6 +1123,14 @@ The top Makefile exports the following variables:
|
|||||||
$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE). The user may
|
$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE). The user may
|
||||||
override this value on the command line if desired.
|
override this value on the command line if desired.
|
||||||
|
|
||||||
|
INSTALL_MOD_STRIP
|
||||||
|
|
||||||
|
If this variable is specified, will cause modules to be stripped
|
||||||
|
after they are installed. If INSTALL_MOD_STRIP is '1', then the
|
||||||
|
default option --strip-debug will be used. Otherwise,
|
||||||
|
INSTALL_MOD_STRIP will used as the option(s) to the strip command.
|
||||||
|
|
||||||
|
|
||||||
=== 8 Makefile language
|
=== 8 Makefile language
|
||||||
|
|
||||||
The kernel Makefiles are designed to run with GNU Make. The Makefiles
|
The kernel Makefiles are designed to run with GNU Make. The Makefiles
|
||||||
|
@@ -175,7 +175,7 @@ end
|
|||||||
document trapinfo
|
document trapinfo
|
||||||
Run info threads and lookup pid of thread #1
|
Run info threads and lookup pid of thread #1
|
||||||
'trapinfo <pid>' will tell you by which trap & possibly
|
'trapinfo <pid>' will tell you by which trap & possibly
|
||||||
addresthe kernel paniced.
|
address the kernel panicked.
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@@ -61,6 +61,7 @@ parameter is applicable:
|
|||||||
MTD MTD support is enabled.
|
MTD MTD support is enabled.
|
||||||
NET Appropriate network support is enabled.
|
NET Appropriate network support is enabled.
|
||||||
NUMA NUMA support is enabled.
|
NUMA NUMA support is enabled.
|
||||||
|
GENERIC_TIME The generic timeofday code is enabled.
|
||||||
NFS Appropriate NFS support is enabled.
|
NFS Appropriate NFS support is enabled.
|
||||||
OSS OSS sound support is enabled.
|
OSS OSS sound support is enabled.
|
||||||
PARIDE The ParIDE subsystem is enabled.
|
PARIDE The ParIDE subsystem is enabled.
|
||||||
@@ -179,6 +180,11 @@ running once the system is up.
|
|||||||
override platform specific driver.
|
override platform specific driver.
|
||||||
See also Documentation/acpi-hotkey.txt.
|
See also Documentation/acpi-hotkey.txt.
|
||||||
|
|
||||||
|
acpi_pm_good [IA-32,X86-64]
|
||||||
|
Override the pmtimer bug detection: force the kernel
|
||||||
|
to assume that this machine's pmtimer latches its value
|
||||||
|
and always returns good values.
|
||||||
|
|
||||||
enable_timer_pin_1 [i386,x86-64]
|
enable_timer_pin_1 [i386,x86-64]
|
||||||
Enable PIN 1 of APIC timer
|
Enable PIN 1 of APIC timer
|
||||||
Can be useful to work around chipset bugs
|
Can be useful to work around chipset bugs
|
||||||
@@ -341,10 +347,11 @@ running once the system is up.
|
|||||||
Value can be changed at runtime via
|
Value can be changed at runtime via
|
||||||
/selinux/checkreqprot.
|
/selinux/checkreqprot.
|
||||||
|
|
||||||
clock= [BUGS=IA-32,HW] gettimeofday timesource override.
|
clock= [BUGS=IA-32, HW] gettimeofday clocksource override.
|
||||||
Forces specified timesource (if avaliable) to be used
|
[Deprecated]
|
||||||
when calculating gettimeofday(). If specicified
|
Forces specified clocksource (if avaliable) to be used
|
||||||
timesource is not avalible, it defaults to PIT.
|
when calculating gettimeofday(). If specified
|
||||||
|
clocksource is not avalible, it defaults to PIT.
|
||||||
Format: { pit | tsc | cyclone | pmtmr }
|
Format: { pit | tsc | cyclone | pmtmr }
|
||||||
|
|
||||||
disable_8254_timer
|
disable_8254_timer
|
||||||
@@ -1617,6 +1624,10 @@ running once the system is up.
|
|||||||
|
|
||||||
time Show timing data prefixed to each printk message line
|
time Show timing data prefixed to each printk message line
|
||||||
|
|
||||||
|
clocksource= [GENERIC_TIME] Override the default clocksource
|
||||||
|
Override the default clocksource and use the clocksource
|
||||||
|
with the name specified.
|
||||||
|
|
||||||
tipar.timeout= [HW,PPT]
|
tipar.timeout= [HW,PPT]
|
||||||
Set communications timeout in tenths of a second
|
Set communications timeout in tenths of a second
|
||||||
(default 15).
|
(default 15).
|
||||||
@@ -1658,6 +1669,10 @@ running once the system is up.
|
|||||||
usbhid.mousepoll=
|
usbhid.mousepoll=
|
||||||
[USBHID] The interval which mice are to be polled at.
|
[USBHID] The interval which mice are to be polled at.
|
||||||
|
|
||||||
|
vdso= [IA-32]
|
||||||
|
vdso=1: enable VDSO (default)
|
||||||
|
vdso=0: disable VDSO mapping
|
||||||
|
|
||||||
video= [FB] Frame buffer configuration
|
video= [FB] Frame buffer configuration
|
||||||
See Documentation/fb/modedb.txt.
|
See Documentation/fb/modedb.txt.
|
||||||
|
|
||||||
|
@@ -241,25 +241,30 @@ The security class "key" has been added to SELinux so that mandatory access
|
|||||||
controls can be applied to keys created within various contexts. This support
|
controls can be applied to keys created within various contexts. This support
|
||||||
is preliminary, and is likely to change quite significantly in the near future.
|
is preliminary, and is likely to change quite significantly in the near future.
|
||||||
Currently, all of the basic permissions explained above are provided in SELinux
|
Currently, all of the basic permissions explained above are provided in SELinux
|
||||||
as well; SE Linux is simply invoked after all basic permission checks have been
|
as well; SELinux is simply invoked after all basic permission checks have been
|
||||||
performed.
|
performed.
|
||||||
|
|
||||||
Each key is labeled with the same context as the task to which it belongs.
|
The value of the file /proc/self/attr/keycreate influences the labeling of
|
||||||
Typically, this is the same task that was running when the key was created.
|
newly-created keys. If the contents of that file correspond to an SELinux
|
||||||
The default keyrings are handled differently, but in a way that is very
|
security context, then the key will be assigned that context. Otherwise, the
|
||||||
intuitive:
|
key will be assigned the current context of the task that invoked the key
|
||||||
|
creation request. Tasks must be granted explicit permission to assign a
|
||||||
|
particular context to newly-created keys, using the "create" permission in the
|
||||||
|
key security class.
|
||||||
|
|
||||||
(*) The user and user session keyrings that are created when the user logs in
|
The default keyrings associated with users will be labeled with the default
|
||||||
are currently labeled with the context of the login manager.
|
context of the user if and only if the login programs have been instrumented to
|
||||||
|
properly initialize keycreate during the login process. Otherwise, they will
|
||||||
(*) The keyrings associated with new threads are each labeled with the context
|
be labeled with the context of the login program itself.
|
||||||
of their associated thread, and both session and process keyrings are
|
|
||||||
handled similarly.
|
|
||||||
|
|
||||||
Note, however, that the default keyrings associated with the root user are
|
Note, however, that the default keyrings associated with the root user are
|
||||||
labeled with the default kernel context, since they are created early in the
|
labeled with the default kernel context, since they are created early in the
|
||||||
boot process, before root has a chance to log in.
|
boot process, before root has a chance to log in.
|
||||||
|
|
||||||
|
The keyrings associated with new threads are each labeled with the context of
|
||||||
|
their associated thread, and both session and process keyrings are handled
|
||||||
|
similarly.
|
||||||
|
|
||||||
|
|
||||||
================
|
================
|
||||||
NEW PROCFS FILES
|
NEW PROCFS FILES
|
||||||
@@ -270,9 +275,17 @@ about the status of the key service:
|
|||||||
|
|
||||||
(*) /proc/keys
|
(*) /proc/keys
|
||||||
|
|
||||||
This lists all the keys on the system, giving information about their
|
This lists the keys that are currently viewable by the task reading the
|
||||||
type, description and permissions. The payload of the key is not available
|
file, giving information about their type, description and permissions.
|
||||||
this way:
|
It is not possible to view the payload of the key this way, though some
|
||||||
|
information about it may be given.
|
||||||
|
|
||||||
|
The only keys included in the list are those that grant View permission to
|
||||||
|
the reading process whether or not it possesses them. Note that LSM
|
||||||
|
security checks are still performed, and may further filter out keys that
|
||||||
|
the current process is not authorised to view.
|
||||||
|
|
||||||
|
The contents of the file look like this:
|
||||||
|
|
||||||
SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY
|
SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY
|
||||||
00000001 I----- 39 perm 1f3f0000 0 0 keyring _uid_ses.0: 1/4
|
00000001 I----- 39 perm 1f3f0000 0 0 keyring _uid_ses.0: 1/4
|
||||||
@@ -300,7 +313,7 @@ about the status of the key service:
|
|||||||
(*) /proc/key-users
|
(*) /proc/key-users
|
||||||
|
|
||||||
This file lists the tracking data for each user that has at least one key
|
This file lists the tracking data for each user that has at least one key
|
||||||
on the system. Such data includes quota information and statistics:
|
on the system. Such data includes quota information and statistics:
|
||||||
|
|
||||||
[root@andromeda root]# cat /proc/key-users
|
[root@andromeda root]# cat /proc/key-users
|
||||||
0: 46 45/45 1/100 13/10000
|
0: 46 45/45 1/100 13/10000
|
||||||
|
@@ -200,6 +200,17 @@ All md devices contain:
|
|||||||
This can be written only while the array is being assembled, not
|
This can be written only while the array is being assembled, not
|
||||||
after it is started.
|
after it is started.
|
||||||
|
|
||||||
|
layout
|
||||||
|
The "layout" for the array for the particular level. This is
|
||||||
|
simply a number that is interpretted differently by different
|
||||||
|
levels. It can be written while assembling an array.
|
||||||
|
|
||||||
|
resync_start
|
||||||
|
The point at which resync should start. If no resync is needed,
|
||||||
|
this will be a very large number. At array creation it will
|
||||||
|
default to 0, though starting the array as 'clean' will
|
||||||
|
set it much larger.
|
||||||
|
|
||||||
new_dev
|
new_dev
|
||||||
This file can be written but not read. The value written should
|
This file can be written but not read. The value written should
|
||||||
be a block device number as major:minor. e.g. 8:0
|
be a block device number as major:minor. e.g. 8:0
|
||||||
@@ -207,6 +218,54 @@ All md devices contain:
|
|||||||
available. It will then appear at md/dev-XXX (depending on the
|
available. It will then appear at md/dev-XXX (depending on the
|
||||||
name of the device) and further configuration is then possible.
|
name of the device) and further configuration is then possible.
|
||||||
|
|
||||||
|
safe_mode_delay
|
||||||
|
When an md array has seen no write requests for a certain period
|
||||||
|
of time, it will be marked as 'clean'. When another write
|
||||||
|
request arrive, the array is marked as 'dirty' before the write
|
||||||
|
commenses. This is known as 'safe_mode'.
|
||||||
|
The 'certain period' is controlled by this file which stores the
|
||||||
|
period as a number of seconds. The default is 200msec (0.200).
|
||||||
|
Writing a value of 0 disables safemode.
|
||||||
|
|
||||||
|
array_state
|
||||||
|
This file contains a single word which describes the current
|
||||||
|
state of the array. In many cases, the state can be set by
|
||||||
|
writing the word for the desired state, however some states
|
||||||
|
cannot be explicitly set, and some transitions are not allowed.
|
||||||
|
|
||||||
|
clear
|
||||||
|
No devices, no size, no level
|
||||||
|
Writing is equivalent to STOP_ARRAY ioctl
|
||||||
|
inactive
|
||||||
|
May have some settings, but array is not active
|
||||||
|
all IO results in error
|
||||||
|
When written, doesn't tear down array, but just stops it
|
||||||
|
suspended (not supported yet)
|
||||||
|
All IO requests will block. The array can be reconfigured.
|
||||||
|
Writing this, if accepted, will block until array is quiessent
|
||||||
|
readonly
|
||||||
|
no resync can happen. no superblocks get written.
|
||||||
|
write requests fail
|
||||||
|
read-auto
|
||||||
|
like readonly, but behaves like 'clean' on a write request.
|
||||||
|
|
||||||
|
clean - no pending writes, but otherwise active.
|
||||||
|
When written to inactive array, starts without resync
|
||||||
|
If a write request arrives then
|
||||||
|
if metadata is known, mark 'dirty' and switch to 'active'.
|
||||||
|
if not known, block and switch to write-pending
|
||||||
|
If written to an active array that has pending writes, then fails.
|
||||||
|
active
|
||||||
|
fully active: IO and resync can be happening.
|
||||||
|
When written to inactive array, starts with resync
|
||||||
|
|
||||||
|
write-pending
|
||||||
|
clean, but writes are blocked waiting for 'active' to be written.
|
||||||
|
|
||||||
|
active-idle
|
||||||
|
like active, but no writes have been seen for a while (safe_mode_delay).
|
||||||
|
|
||||||
|
|
||||||
sync_speed_min
|
sync_speed_min
|
||||||
sync_speed_max
|
sync_speed_max
|
||||||
This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
|
This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
|
||||||
@@ -250,10 +309,18 @@ Each directory contains:
|
|||||||
faulty - device has been kicked from active use due to
|
faulty - device has been kicked from active use due to
|
||||||
a detected fault
|
a detected fault
|
||||||
in_sync - device is a fully in-sync member of the array
|
in_sync - device is a fully in-sync member of the array
|
||||||
|
writemostly - device will only be subject to read
|
||||||
|
requests if there are no other options.
|
||||||
|
This applies only to raid1 arrays.
|
||||||
spare - device is working, but not a full member.
|
spare - device is working, but not a full member.
|
||||||
This includes spares that are in the process
|
This includes spares that are in the process
|
||||||
of being recoverred to
|
of being recoverred to
|
||||||
This list make grow in future.
|
This list make grow in future.
|
||||||
|
This can be written to.
|
||||||
|
Writing "faulty" simulates a failure on the device.
|
||||||
|
Writing "remove" removes the device from the array.
|
||||||
|
Writing "writemostly" sets the writemostly flag.
|
||||||
|
Writing "-writemostly" clears the writemostly flag.
|
||||||
|
|
||||||
errors
|
errors
|
||||||
An approximate count of read errors that have been detected on
|
An approximate count of read errors that have been detected on
|
||||||
|
121
Documentation/pi-futex.txt
Normal file
121
Documentation/pi-futex.txt
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
Lightweight PI-futexes
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
We are calling them lightweight for 3 reasons:
|
||||||
|
|
||||||
|
- in the user-space fastpath a PI-enabled futex involves no kernel work
|
||||||
|
(or any other PI complexity) at all. No registration, no extra kernel
|
||||||
|
calls - just pure fast atomic ops in userspace.
|
||||||
|
|
||||||
|
- even in the slowpath, the system call and scheduling pattern is very
|
||||||
|
similar to normal futexes.
|
||||||
|
|
||||||
|
- the in-kernel PI implementation is streamlined around the mutex
|
||||||
|
abstraction, with strict rules that keep the implementation
|
||||||
|
relatively simple: only a single owner may own a lock (i.e. no
|
||||||
|
read-write lock support), only the owner may unlock a lock, no
|
||||||
|
recursive locking, etc.
|
||||||
|
|
||||||
|
Priority Inheritance - why?
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The short reply: user-space PI helps achieving/improving determinism for
|
||||||
|
user-space applications. In the best-case, it can help achieve
|
||||||
|
determinism and well-bound latencies. Even in the worst-case, PI will
|
||||||
|
improve the statistical distribution of locking related application
|
||||||
|
delays.
|
||||||
|
|
||||||
|
The longer reply:
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Firstly, sharing locks between multiple tasks is a common programming
|
||||||
|
technique that often cannot be replaced with lockless algorithms. As we
|
||||||
|
can see it in the kernel [which is a quite complex program in itself],
|
||||||
|
lockless structures are rather the exception than the norm - the current
|
||||||
|
ratio of lockless vs. locky code for shared data structures is somewhere
|
||||||
|
between 1:10 and 1:100. Lockless is hard, and the complexity of lockless
|
||||||
|
algorithms often endangers to ability to do robust reviews of said code.
|
||||||
|
I.e. critical RT apps often choose lock structures to protect critical
|
||||||
|
data structures, instead of lockless algorithms. Furthermore, there are
|
||||||
|
cases (like shared hardware, or other resource limits) where lockless
|
||||||
|
access is mathematically impossible.
|
||||||
|
|
||||||
|
Media players (such as Jack) are an example of reasonable application
|
||||||
|
design with multiple tasks (with multiple priority levels) sharing
|
||||||
|
short-held locks: for example, a highprio audio playback thread is
|
||||||
|
combined with medium-prio construct-audio-data threads and low-prio
|
||||||
|
display-colory-stuff threads. Add video and decoding to the mix and
|
||||||
|
we've got even more priority levels.
|
||||||
|
|
||||||
|
So once we accept that synchronization objects (locks) are an
|
||||||
|
unavoidable fact of life, and once we accept that multi-task userspace
|
||||||
|
apps have a very fair expectation of being able to use locks, we've got
|
||||||
|
to think about how to offer the option of a deterministic locking
|
||||||
|
implementation to user-space.
|
||||||
|
|
||||||
|
Most of the technical counter-arguments against doing priority
|
||||||
|
inheritance only apply to kernel-space locks. But user-space locks are
|
||||||
|
different, there we cannot disable interrupts or make the task
|
||||||
|
non-preemptible in a critical section, so the 'use spinlocks' argument
|
||||||
|
does not apply (user-space spinlocks have the same priority inversion
|
||||||
|
problems as other user-space locking constructs). Fact is, pretty much
|
||||||
|
the only technique that currently enables good determinism for userspace
|
||||||
|
locks (such as futex-based pthread mutexes) is priority inheritance:
|
||||||
|
|
||||||
|
Currently (without PI), if a high-prio and a low-prio task shares a lock
|
||||||
|
[this is a quite common scenario for most non-trivial RT applications],
|
||||||
|
even if all critical sections are coded carefully to be deterministic
|
||||||
|
(i.e. all critical sections are short in duration and only execute a
|
||||||
|
limited number of instructions), the kernel cannot guarantee any
|
||||||
|
deterministic execution of the high-prio task: any medium-priority task
|
||||||
|
could preempt the low-prio task while it holds the shared lock and
|
||||||
|
executes the critical section, and could delay it indefinitely.
|
||||||
|
|
||||||
|
Implementation:
|
||||||
|
---------------
|
||||||
|
|
||||||
|
As mentioned before, the userspace fastpath of PI-enabled pthread
|
||||||
|
mutexes involves no kernel work at all - they behave quite similarly to
|
||||||
|
normal futex-based locks: a 0 value means unlocked, and a value==TID
|
||||||
|
means locked. (This is the same method as used by list-based robust
|
||||||
|
futexes.) Userspace uses atomic ops to lock/unlock these mutexes without
|
||||||
|
entering the kernel.
|
||||||
|
|
||||||
|
To handle the slowpath, we have added two new futex ops:
|
||||||
|
|
||||||
|
FUTEX_LOCK_PI
|
||||||
|
FUTEX_UNLOCK_PI
|
||||||
|
|
||||||
|
If the lock-acquire fastpath fails, [i.e. an atomic transition from 0 to
|
||||||
|
TID fails], then FUTEX_LOCK_PI is called. The kernel does all the
|
||||||
|
remaining work: if there is no futex-queue attached to the futex address
|
||||||
|
yet then the code looks up the task that owns the futex [it has put its
|
||||||
|
own TID into the futex value], and attaches a 'PI state' structure to
|
||||||
|
the futex-queue. The pi_state includes an rt-mutex, which is a PI-aware,
|
||||||
|
kernel-based synchronization object. The 'other' task is made the owner
|
||||||
|
of the rt-mutex, and the FUTEX_WAITERS bit is atomically set in the
|
||||||
|
futex value. Then this task tries to lock the rt-mutex, on which it
|
||||||
|
blocks. Once it returns, it has the mutex acquired, and it sets the
|
||||||
|
futex value to its own TID and returns. Userspace has no other work to
|
||||||
|
perform - it now owns the lock, and futex value contains
|
||||||
|
FUTEX_WAITERS|TID.
|
||||||
|
|
||||||
|
If the unlock side fastpath succeeds, [i.e. userspace manages to do a
|
||||||
|
TID -> 0 atomic transition of the futex value], then no kernel work is
|
||||||
|
triggered.
|
||||||
|
|
||||||
|
If the unlock fastpath fails (because the FUTEX_WAITERS bit is set),
|
||||||
|
then FUTEX_UNLOCK_PI is called, and the kernel unlocks the futex on the
|
||||||
|
behalf of userspace - and it also unlocks the attached
|
||||||
|
pi_state->rt_mutex and thus wakes up any potential waiters.
|
||||||
|
|
||||||
|
Note that under this approach, contrary to previous PI-futex approaches,
|
||||||
|
there is no prior 'registration' of a PI-futex. [which is not quite
|
||||||
|
possible anyway, due to existing ABI properties of pthread mutexes.]
|
||||||
|
|
||||||
|
Also, under this scheme, 'robustness' and 'PI' are two orthogonal
|
||||||
|
properties of futexes, and all four combinations are possible: futex,
|
||||||
|
robust-futex, PI-futex, robust+PI-futex.
|
||||||
|
|
||||||
|
More details about priority inheritance can be found in
|
||||||
|
Documentation/rtmutex.txt.
|
@@ -95,7 +95,7 @@ comparison. If the thread has registered a list, then normally the list
|
|||||||
is empty. If the thread/process crashed or terminated in some incorrect
|
is empty. If the thread/process crashed or terminated in some incorrect
|
||||||
way then the list might be non-empty: in this case the kernel carefully
|
way then the list might be non-empty: in this case the kernel carefully
|
||||||
walks the list [not trusting it], and marks all locks that are owned by
|
walks the list [not trusting it], and marks all locks that are owned by
|
||||||
this thread with the FUTEX_OWNER_DEAD bit, and wakes up one waiter (if
|
this thread with the FUTEX_OWNER_DIED bit, and wakes up one waiter (if
|
||||||
any).
|
any).
|
||||||
|
|
||||||
The list is guaranteed to be private and per-thread at do_exit() time,
|
The list is guaranteed to be private and per-thread at do_exit() time,
|
||||||
|
781
Documentation/rt-mutex-design.txt
Normal file
781
Documentation/rt-mutex-design.txt
Normal file
@@ -0,0 +1,781 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2006 Steven Rostedt
|
||||||
|
# Licensed under the GNU Free Documentation License, Version 1.2
|
||||||
|
#
|
||||||
|
|
||||||
|
RT-mutex implementation design
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
This document tries to describe the design of the rtmutex.c implementation.
|
||||||
|
It doesn't describe the reasons why rtmutex.c exists. For that please see
|
||||||
|
Documentation/rt-mutex.txt. Although this document does explain problems
|
||||||
|
that happen without this code, but that is in the concept to understand
|
||||||
|
what the code actually is doing.
|
||||||
|
|
||||||
|
The goal of this document is to help others understand the priority
|
||||||
|
inheritance (PI) algorithm that is used, as well as reasons for the
|
||||||
|
decisions that were made to implement PI in the manner that was done.
|
||||||
|
|
||||||
|
|
||||||
|
Unbounded Priority Inversion
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Priority inversion is when a lower priority process executes while a higher
|
||||||
|
priority process wants to run. This happens for several reasons, and
|
||||||
|
most of the time it can't be helped. Anytime a high priority process wants
|
||||||
|
to use a resource that a lower priority process has (a mutex for example),
|
||||||
|
the high priority process must wait until the lower priority process is done
|
||||||
|
with the resource. This is a priority inversion. What we want to prevent
|
||||||
|
is something called unbounded priority inversion. That is when the high
|
||||||
|
priority process is prevented from running by a lower priority process for
|
||||||
|
an undetermined amount of time.
|
||||||
|
|
||||||
|
The classic example of unbounded priority inversion is were you have three
|
||||||
|
processes, let's call them processes A, B, and C, where A is the highest
|
||||||
|
priority process, C is the lowest, and B is in between. A tries to grab a lock
|
||||||
|
that C owns and must wait and lets C run to release the lock. But in the
|
||||||
|
meantime, B executes, and since B is of a higher priority than C, it preempts C,
|
||||||
|
but by doing so, it is in fact preempting A which is a higher priority process.
|
||||||
|
Now there's no way of knowing how long A will be sleeping waiting for C
|
||||||
|
to release the lock, because for all we know, B is a CPU hog and will
|
||||||
|
never give C a chance to release the lock. This is called unbounded priority
|
||||||
|
inversion.
|
||||||
|
|
||||||
|
Here's a little ASCII art to show the problem.
|
||||||
|
|
||||||
|
grab lock L1 (owned by C)
|
||||||
|
|
|
||||||
|
A ---+
|
||||||
|
C preempted by B
|
||||||
|
|
|
||||||
|
C +----+
|
||||||
|
|
||||||
|
B +-------->
|
||||||
|
B now keeps A from running.
|
||||||
|
|
||||||
|
|
||||||
|
Priority Inheritance (PI)
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
There are several ways to solve this issue, but other ways are out of scope
|
||||||
|
for this document. Here we only discuss PI.
|
||||||
|
|
||||||
|
PI is where a process inherits the priority of another process if the other
|
||||||
|
process blocks on a lock owned by the current process. To make this easier
|
||||||
|
to understand, let's use the previous example, with processes A, B, and C again.
|
||||||
|
|
||||||
|
This time, when A blocks on the lock owned by C, C would inherit the priority
|
||||||
|
of A. So now if B becomes runnable, it would not preempt C, since C now has
|
||||||
|
the high priority of A. As soon as C releases the lock, it loses its
|
||||||
|
inherited priority, and A then can continue with the resource that C had.
|
||||||
|
|
||||||
|
Terminology
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Here I explain some terminology that is used in this document to help describe
|
||||||
|
the design that is used to implement PI.
|
||||||
|
|
||||||
|
PI chain - The PI chain is an ordered series of locks and processes that cause
|
||||||
|
processes to inherit priorities from a previous process that is
|
||||||
|
blocked on one of its locks. This is described in more detail
|
||||||
|
later in this document.
|
||||||
|
|
||||||
|
mutex - In this document, to differentiate from locks that implement
|
||||||
|
PI and spin locks that are used in the PI code, from now on
|
||||||
|
the PI locks will be called a mutex.
|
||||||
|
|
||||||
|
lock - In this document from now on, I will use the term lock when
|
||||||
|
referring to spin locks that are used to protect parts of the PI
|
||||||
|
algorithm. These locks disable preemption for UP (when
|
||||||
|
CONFIG_PREEMPT is enabled) and on SMP prevents multiple CPUs from
|
||||||
|
entering critical sections simultaneously.
|
||||||
|
|
||||||
|
spin lock - Same as lock above.
|
||||||
|
|
||||||
|
waiter - A waiter is a struct that is stored on the stack of a blocked
|
||||||
|
process. Since the scope of the waiter is within the code for
|
||||||
|
a process being blocked on the mutex, it is fine to allocate
|
||||||
|
the waiter on the process's stack (local variable). This
|
||||||
|
structure holds a pointer to the task, as well as the mutex that
|
||||||
|
the task is blocked on. It also has the plist node structures to
|
||||||
|
place the task in the waiter_list of a mutex as well as the
|
||||||
|
pi_list of a mutex owner task (described below).
|
||||||
|
|
||||||
|
waiter is sometimes used in reference to the task that is waiting
|
||||||
|
on a mutex. This is the same as waiter->task.
|
||||||
|
|
||||||
|
waiters - A list of processes that are blocked on a mutex.
|
||||||
|
|
||||||
|
top waiter - The highest priority process waiting on a specific mutex.
|
||||||
|
|
||||||
|
top pi waiter - The highest priority process waiting on one of the mutexes
|
||||||
|
that a specific process owns.
|
||||||
|
|
||||||
|
Note: task and process are used interchangeably in this document, mostly to
|
||||||
|
differentiate between two processes that are being described together.
|
||||||
|
|
||||||
|
|
||||||
|
PI chain
|
||||||
|
--------
|
||||||
|
|
||||||
|
The PI chain is a list of processes and mutexes that may cause priority
|
||||||
|
inheritance to take place. Multiple chains may converge, but a chain
|
||||||
|
would never diverge, since a process can't be blocked on more than one
|
||||||
|
mutex at a time.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
Process: A, B, C, D, E
|
||||||
|
Mutexes: L1, L2, L3, L4
|
||||||
|
|
||||||
|
A owns: L1
|
||||||
|
B blocked on L1
|
||||||
|
B owns L2
|
||||||
|
C blocked on L2
|
||||||
|
C owns L3
|
||||||
|
D blocked on L3
|
||||||
|
D owns L4
|
||||||
|
E blocked on L4
|
||||||
|
|
||||||
|
The chain would be:
|
||||||
|
|
||||||
|
E->L4->D->L3->C->L2->B->L1->A
|
||||||
|
|
||||||
|
To show where two chains merge, we could add another process F and
|
||||||
|
another mutex L5 where B owns L5 and F is blocked on mutex L5.
|
||||||
|
|
||||||
|
The chain for F would be:
|
||||||
|
|
||||||
|
F->L5->B->L1->A
|
||||||
|
|
||||||
|
Since a process may own more than one mutex, but never be blocked on more than
|
||||||
|
one, the chains merge.
|
||||||
|
|
||||||
|
Here we show both chains:
|
||||||
|
|
||||||
|
E->L4->D->L3->C->L2-+
|
||||||
|
|
|
||||||
|
+->B->L1->A
|
||||||
|
|
|
||||||
|
F->L5-+
|
||||||
|
|
||||||
|
For PI to work, the processes at the right end of these chains (or we may
|
||||||
|
also call it the Top of the chain) must be equal to or higher in priority
|
||||||
|
than the processes to the left or below in the chain.
|
||||||
|
|
||||||
|
Also since a mutex may have more than one process blocked on it, we can
|
||||||
|
have multiple chains merge at mutexes. If we add another process G that is
|
||||||
|
blocked on mutex L2:
|
||||||
|
|
||||||
|
G->L2->B->L1->A
|
||||||
|
|
||||||
|
And once again, to show how this can grow I will show the merging chains
|
||||||
|
again.
|
||||||
|
|
||||||
|
E->L4->D->L3->C-+
|
||||||
|
+->L2-+
|
||||||
|
| |
|
||||||
|
G-+ +->B->L1->A
|
||||||
|
|
|
||||||
|
F->L5-+
|
||||||
|
|
||||||
|
|
||||||
|
Plist
|
||||||
|
-----
|
||||||
|
|
||||||
|
Before I go further and talk about how the PI chain is stored through lists
|
||||||
|
on both mutexes and processes, I'll explain the plist. This is similar to
|
||||||
|
the struct list_head functionality that is already in the kernel.
|
||||||
|
The implementation of plist is out of scope for this document, but it is
|
||||||
|
very important to understand what it does.
|
||||||
|
|
||||||
|
There are a few differences between plist and list, the most important one
|
||||||
|
being that plist is a priority sorted linked list. This means that the
|
||||||
|
priorities of the plist are sorted, such that it takes O(1) to retrieve the
|
||||||
|
highest priority item in the list. Obviously this is useful to store processes
|
||||||
|
based on their priorities.
|
||||||
|
|
||||||
|
Another difference, which is important for implementation, is that, unlike
|
||||||
|
list, the head of the list is a different element than the nodes of a list.
|
||||||
|
So the head of the list is declared as struct plist_head and nodes that will
|
||||||
|
be added to the list are declared as struct plist_node.
|
||||||
|
|
||||||
|
|
||||||
|
Mutex Waiter List
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Every mutex keeps track of all the waiters that are blocked on itself. The mutex
|
||||||
|
has a plist to store these waiters by priority. This list is protected by
|
||||||
|
a spin lock that is located in the struct of the mutex. This lock is called
|
||||||
|
wait_lock. Since the modification of the waiter list is never done in
|
||||||
|
interrupt context, the wait_lock can be taken without disabling interrupts.
|
||||||
|
|
||||||
|
|
||||||
|
Task PI List
|
||||||
|
------------
|
||||||
|
|
||||||
|
To keep track of the PI chains, each process has its own PI list. This is
|
||||||
|
a list of all top waiters of the mutexes that are owned by the process.
|
||||||
|
Note that this list only holds the top waiters and not all waiters that are
|
||||||
|
blocked on mutexes owned by the process.
|
||||||
|
|
||||||
|
The top of the task's PI list is always the highest priority task that
|
||||||
|
is waiting on a mutex that is owned by the task. So if the task has
|
||||||
|
inherited a priority, it will always be the priority of the task that is
|
||||||
|
at the top of this list.
|
||||||
|
|
||||||
|
This list is stored in the task structure of a process as a plist called
|
||||||
|
pi_list. This list is protected by a spin lock also in the task structure,
|
||||||
|
called pi_lock. This lock may also be taken in interrupt context, so when
|
||||||
|
locking the pi_lock, interrupts must be disabled.
|
||||||
|
|
||||||
|
|
||||||
|
Depth of the PI Chain
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The maximum depth of the PI chain is not dynamic, and could actually be
|
||||||
|
defined. But is very complex to figure it out, since it depends on all
|
||||||
|
the nesting of mutexes. Let's look at the example where we have 3 mutexes,
|
||||||
|
L1, L2, and L3, and four separate functions func1, func2, func3 and func4.
|
||||||
|
The following shows a locking order of L1->L2->L3, but may not actually
|
||||||
|
be directly nested that way.
|
||||||
|
|
||||||
|
void func1(void)
|
||||||
|
{
|
||||||
|
mutex_lock(L1);
|
||||||
|
|
||||||
|
/* do anything */
|
||||||
|
|
||||||
|
mutex_unlock(L1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void func2(void)
|
||||||
|
{
|
||||||
|
mutex_lock(L1);
|
||||||
|
mutex_lock(L2);
|
||||||
|
|
||||||
|
/* do something */
|
||||||
|
|
||||||
|
mutex_unlock(L2);
|
||||||
|
mutex_unlock(L1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void func3(void)
|
||||||
|
{
|
||||||
|
mutex_lock(L2);
|
||||||
|
mutex_lock(L3);
|
||||||
|
|
||||||
|
/* do something else */
|
||||||
|
|
||||||
|
mutex_unlock(L3);
|
||||||
|
mutex_unlock(L2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void func4(void)
|
||||||
|
{
|
||||||
|
mutex_lock(L3);
|
||||||
|
|
||||||
|
/* do something again */
|
||||||
|
|
||||||
|
mutex_unlock(L3);
|
||||||
|
}
|
||||||
|
|
||||||
|
Now we add 4 processes that run each of these functions separately.
|
||||||
|
Processes A, B, C, and D which run functions func1, func2, func3 and func4
|
||||||
|
respectively, and such that D runs first and A last. With D being preempted
|
||||||
|
in func4 in the "do something again" area, we have a locking that follows:
|
||||||
|
|
||||||
|
D owns L3
|
||||||
|
C blocked on L3
|
||||||
|
C owns L2
|
||||||
|
B blocked on L2
|
||||||
|
B owns L1
|
||||||
|
A blocked on L1
|
||||||
|
|
||||||
|
And thus we have the chain A->L1->B->L2->C->L3->D.
|
||||||
|
|
||||||
|
This gives us a PI depth of 4 (four processes), but looking at any of the
|
||||||
|
functions individually, it seems as though they only have at most a locking
|
||||||
|
depth of two. So, although the locking depth is defined at compile time,
|
||||||
|
it still is very difficult to find the possibilities of that depth.
|
||||||
|
|
||||||
|
Now since mutexes can be defined by user-land applications, we don't want a DOS
|
||||||
|
type of application that nests large amounts of mutexes to create a large
|
||||||
|
PI chain, and have the code holding spin locks while looking at a large
|
||||||
|
amount of data. So to prevent this, the implementation not only implements
|
||||||
|
a maximum lock depth, but also only holds at most two different locks at a
|
||||||
|
time, as it walks the PI chain. More about this below.
|
||||||
|
|
||||||
|
|
||||||
|
Mutex owner and flags
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The mutex structure contains a pointer to the owner of the mutex. If the
|
||||||
|
mutex is not owned, this owner is set to NULL. Since all architectures
|
||||||
|
have the task structure on at least a four byte alignment (and if this is
|
||||||
|
not true, the rtmutex.c code will be broken!), this allows for the two
|
||||||
|
least significant bits to be used as flags. This part is also described
|
||||||
|
in Documentation/rt-mutex.txt, but will also be briefly described here.
|
||||||
|
|
||||||
|
Bit 0 is used as the "Pending Owner" flag. This is described later.
|
||||||
|
Bit 1 is used as the "Has Waiters" flags. This is also described later
|
||||||
|
in more detail, but is set whenever there are waiters on a mutex.
|
||||||
|
|
||||||
|
|
||||||
|
cmpxchg Tricks
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Some architectures implement an atomic cmpxchg (Compare and Exchange). This
|
||||||
|
is used (when applicable) to keep the fast path of grabbing and releasing
|
||||||
|
mutexes short.
|
||||||
|
|
||||||
|
cmpxchg is basically the following function performed atomically:
|
||||||
|
|
||||||
|
unsigned long _cmpxchg(unsigned long *A, unsigned long *B, unsigned long *C)
|
||||||
|
{
|
||||||
|
unsigned long T = *A;
|
||||||
|
if (*A == *B) {
|
||||||
|
*A = *C;
|
||||||
|
}
|
||||||
|
return T;
|
||||||
|
}
|
||||||
|
#define cmpxchg(a,b,c) _cmpxchg(&a,&b,&c)
|
||||||
|
|
||||||
|
This is really nice to have, since it allows you to only update a variable
|
||||||
|
if the variable is what you expect it to be. You know if it succeeded if
|
||||||
|
the return value (the old value of A) is equal to B.
|
||||||
|
|
||||||
|
The macro rt_mutex_cmpxchg is used to try to lock and unlock mutexes. If
|
||||||
|
the architecture does not support CMPXCHG, then this macro is simply set
|
||||||
|
to fail every time. But if CMPXCHG is supported, then this will
|
||||||
|
help out extremely to keep the fast path short.
|
||||||
|
|
||||||
|
The use of rt_mutex_cmpxchg with the flags in the owner field help optimize
|
||||||
|
the system for architectures that support it. This will also be explained
|
||||||
|
later in this document.
|
||||||
|
|
||||||
|
|
||||||
|
Priority adjustments
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The implementation of the PI code in rtmutex.c has several places that a
|
||||||
|
process must adjust its priority. With the help of the pi_list of a
|
||||||
|
process this is rather easy to know what needs to be adjusted.
|
||||||
|
|
||||||
|
The functions implementing the task adjustments are rt_mutex_adjust_prio,
|
||||||
|
__rt_mutex_adjust_prio (same as the former, but expects the task pi_lock
|
||||||
|
to already be taken), rt_mutex_get_prio, and rt_mutex_setprio.
|
||||||
|
|
||||||
|
rt_mutex_getprio and rt_mutex_setprio are only used in __rt_mutex_adjust_prio.
|
||||||
|
|
||||||
|
rt_mutex_getprio returns the priority that the task should have. Either the
|
||||||
|
task's own normal priority, or if a process of a higher priority is waiting on
|
||||||
|
a mutex owned by the task, then that higher priority should be returned.
|
||||||
|
Since the pi_list of a task holds an order by priority list of all the top
|
||||||
|
waiters of all the mutexes that the task owns, rt_mutex_getprio simply needs
|
||||||
|
to compare the top pi waiter to its own normal priority, and return the higher
|
||||||
|
priority back.
|
||||||
|
|
||||||
|
(Note: if looking at the code, you will notice that the lower number of
|
||||||
|
prio is returned. This is because the prio field in the task structure
|
||||||
|
is an inverse order of the actual priority. So a "prio" of 5 is
|
||||||
|
of higher priority than a "prio" of 10.)
|
||||||
|
|
||||||
|
__rt_mutex_adjust_prio examines the result of rt_mutex_getprio, and if the
|
||||||
|
result does not equal the task's current priority, then rt_mutex_setprio
|
||||||
|
is called to adjust the priority of the task to the new priority.
|
||||||
|
Note that rt_mutex_setprio is defined in kernel/sched.c to implement the
|
||||||
|
actual change in priority.
|
||||||
|
|
||||||
|
It is interesting to note that __rt_mutex_adjust_prio can either increase
|
||||||
|
or decrease the priority of the task. In the case that a higher priority
|
||||||
|
process has just blocked on a mutex owned by the task, __rt_mutex_adjust_prio
|
||||||
|
would increase/boost the task's priority. But if a higher priority task
|
||||||
|
were for some reason to leave the mutex (timeout or signal), this same function
|
||||||
|
would decrease/unboost the priority of the task. That is because the pi_list
|
||||||
|
always contains the highest priority task that is waiting on a mutex owned
|
||||||
|
by the task, so we only need to compare the priority of that top pi waiter
|
||||||
|
to the normal priority of the given task.
|
||||||
|
|
||||||
|
|
||||||
|
High level overview of the PI chain walk
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
The PI chain walk is implemented by the function rt_mutex_adjust_prio_chain.
|
||||||
|
|
||||||
|
The implementation has gone through several iterations, and has ended up
|
||||||
|
with what we believe is the best. It walks the PI chain by only grabbing
|
||||||
|
at most two locks at a time, and is very efficient.
|
||||||
|
|
||||||
|
The rt_mutex_adjust_prio_chain can be used either to boost or lower process
|
||||||
|
priorities.
|
||||||
|
|
||||||
|
rt_mutex_adjust_prio_chain is called with a task to be checked for PI
|
||||||
|
(de)boosting (the owner of a mutex that a process is blocking on), a flag to
|
||||||
|
check for deadlocking, the mutex that the task owns, and a pointer to a waiter
|
||||||
|
that is the process's waiter struct that is blocked on the mutex (although this
|
||||||
|
parameter may be NULL for deboosting).
|
||||||
|
|
||||||
|
For this explanation, I will not mention deadlock detection. This explanation
|
||||||
|
will try to stay at a high level.
|
||||||
|
|
||||||
|
When this function is called, there are no locks held. That also means
|
||||||
|
that the state of the owner and lock can change when entered into this function.
|
||||||
|
|
||||||
|
Before this function is called, the task has already had rt_mutex_adjust_prio
|
||||||
|
performed on it. This means that the task is set to the priority that it
|
||||||
|
should be at, but the plist nodes of the task's waiter have not been updated
|
||||||
|
with the new priorities, and that this task may not be in the proper locations
|
||||||
|
in the pi_lists and wait_lists that the task is blocked on. This function
|
||||||
|
solves all that.
|
||||||
|
|
||||||
|
A loop is entered, where task is the owner to be checked for PI changes that
|
||||||
|
was passed by parameter (for the first iteration). The pi_lock of this task is
|
||||||
|
taken to prevent any more changes to the pi_list of the task. This also
|
||||||
|
prevents new tasks from completing the blocking on a mutex that is owned by this
|
||||||
|
task.
|
||||||
|
|
||||||
|
If the task is not blocked on a mutex then the loop is exited. We are at
|
||||||
|
the top of the PI chain.
|
||||||
|
|
||||||
|
A check is now done to see if the original waiter (the process that is blocked
|
||||||
|
on the current mutex) is the top pi waiter of the task. That is, is this
|
||||||
|
waiter on the top of the task's pi_list. If it is not, it either means that
|
||||||
|
there is another process higher in priority that is blocked on one of the
|
||||||
|
mutexes that the task owns, or that the waiter has just woken up via a signal
|
||||||
|
or timeout and has left the PI chain. In either case, the loop is exited, since
|
||||||
|
we don't need to do any more changes to the priority of the current task, or any
|
||||||
|
task that owns a mutex that this current task is waiting on. A priority chain
|
||||||
|
walk is only needed when a new top pi waiter is made to a task.
|
||||||
|
|
||||||
|
The next check sees if the task's waiter plist node has the priority equal to
|
||||||
|
the priority the task is set at. If they are equal, then we are done with
|
||||||
|
the loop. Remember that the function started with the priority of the
|
||||||
|
task adjusted, but the plist nodes that hold the task in other processes
|
||||||
|
pi_lists have not been adjusted.
|
||||||
|
|
||||||
|
Next, we look at the mutex that the task is blocked on. The mutex's wait_lock
|
||||||
|
is taken. This is done by a spin_trylock, because the locking order of the
|
||||||
|
pi_lock and wait_lock goes in the opposite direction. If we fail to grab the
|
||||||
|
lock, the pi_lock is released, and we restart the loop.
|
||||||
|
|
||||||
|
Now that we have both the pi_lock of the task as well as the wait_lock of
|
||||||
|
the mutex the task is blocked on, we update the task's waiter's plist node
|
||||||
|
that is located on the mutex's wait_list.
|
||||||
|
|
||||||
|
Now we release the pi_lock of the task.
|
||||||
|
|
||||||
|
Next the owner of the mutex has its pi_lock taken, so we can update the
|
||||||
|
task's entry in the owner's pi_list. If the task is the highest priority
|
||||||
|
process on the mutex's wait_list, then we remove the previous top waiter
|
||||||
|
from the owner's pi_list, and replace it with the task.
|
||||||
|
|
||||||
|
Note: It is possible that the task was the current top waiter on the mutex,
|
||||||
|
in which case the task is not yet on the pi_list of the waiter. This
|
||||||
|
is OK, since plist_del does nothing if the plist node is not on any
|
||||||
|
list.
|
||||||
|
|
||||||
|
If the task was not the top waiter of the mutex, but it was before we
|
||||||
|
did the priority updates, that means we are deboosting/lowering the
|
||||||
|
task. In this case, the task is removed from the pi_list of the owner,
|
||||||
|
and the new top waiter is added.
|
||||||
|
|
||||||
|
Lastly, we unlock both the pi_lock of the task, as well as the mutex's
|
||||||
|
wait_lock, and continue the loop again. On the next iteration of the
|
||||||
|
loop, the previous owner of the mutex will be the task that will be
|
||||||
|
processed.
|
||||||
|
|
||||||
|
Note: One might think that the owner of this mutex might have changed
|
||||||
|
since we just grab the mutex's wait_lock. And one could be right.
|
||||||
|
The important thing to remember is that the owner could not have
|
||||||
|
become the task that is being processed in the PI chain, since
|
||||||
|
we have taken that task's pi_lock at the beginning of the loop.
|
||||||
|
So as long as there is an owner of this mutex that is not the same
|
||||||
|
process as the tasked being worked on, we are OK.
|
||||||
|
|
||||||
|
Looking closely at the code, one might be confused. The check for the
|
||||||
|
end of the PI chain is when the task isn't blocked on anything or the
|
||||||
|
task's waiter structure "task" element is NULL. This check is
|
||||||
|
protected only by the task's pi_lock. But the code to unlock the mutex
|
||||||
|
sets the task's waiter structure "task" element to NULL with only
|
||||||
|
the protection of the mutex's wait_lock, which was not taken yet.
|
||||||
|
Isn't this a race condition if the task becomes the new owner?
|
||||||
|
|
||||||
|
The answer is No! The trick is the spin_trylock of the mutex's
|
||||||
|
wait_lock. If we fail that lock, we release the pi_lock of the
|
||||||
|
task and continue the loop, doing the end of PI chain check again.
|
||||||
|
|
||||||
|
In the code to release the lock, the wait_lock of the mutex is held
|
||||||
|
the entire time, and it is not let go when we grab the pi_lock of the
|
||||||
|
new owner of the mutex. So if the switch of a new owner were to happen
|
||||||
|
after the check for end of the PI chain and the grabbing of the
|
||||||
|
wait_lock, the unlocking code would spin on the new owner's pi_lock
|
||||||
|
but never give up the wait_lock. So the PI chain loop is guaranteed to
|
||||||
|
fail the spin_trylock on the wait_lock, release the pi_lock, and
|
||||||
|
try again.
|
||||||
|
|
||||||
|
If you don't quite understand the above, that's OK. You don't have to,
|
||||||
|
unless you really want to make a proof out of it ;)
|
||||||
|
|
||||||
|
|
||||||
|
Pending Owners and Lock stealing
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
One of the flags in the owner field of the mutex structure is "Pending Owner".
|
||||||
|
What this means is that an owner was chosen by the process releasing the
|
||||||
|
mutex, but that owner has yet to wake up and actually take the mutex.
|
||||||
|
|
||||||
|
Why is this important? Why can't we just give the mutex to another process
|
||||||
|
and be done with it?
|
||||||
|
|
||||||
|
The PI code is to help with real-time processes, and to let the highest
|
||||||
|
priority process run as long as possible with little latencies and delays.
|
||||||
|
If a high priority process owns a mutex that a lower priority process is
|
||||||
|
blocked on, when the mutex is released it would be given to the lower priority
|
||||||
|
process. What if the higher priority process wants to take that mutex again.
|
||||||
|
The high priority process would fail to take that mutex that it just gave up
|
||||||
|
and it would need to boost the lower priority process to run with full
|
||||||
|
latency of that critical section (since the low priority process just entered
|
||||||
|
it).
|
||||||
|
|
||||||
|
There's no reason a high priority process that gives up a mutex should be
|
||||||
|
penalized if it tries to take that mutex again. If the new owner of the
|
||||||
|
mutex has not woken up yet, there's no reason that the higher priority process
|
||||||
|
could not take that mutex away.
|
||||||
|
|
||||||
|
To solve this, we introduced Pending Ownership and Lock Stealing. When a
|
||||||
|
new process is given a mutex that it was blocked on, it is only given
|
||||||
|
pending ownership. This means that it's the new owner, unless a higher
|
||||||
|
priority process comes in and tries to grab that mutex. If a higher priority
|
||||||
|
process does come along and wants that mutex, we let the higher priority
|
||||||
|
process "steal" the mutex from the pending owner (only if it is still pending)
|
||||||
|
and continue with the mutex.
|
||||||
|
|
||||||
|
|
||||||
|
Taking of a mutex (The walk through)
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
OK, now let's take a look at the detailed walk through of what happens when
|
||||||
|
taking a mutex.
|
||||||
|
|
||||||
|
The first thing that is tried is the fast taking of the mutex. This is
|
||||||
|
done when we have CMPXCHG enabled (otherwise the fast taking automatically
|
||||||
|
fails). Only when the owner field of the mutex is NULL can the lock be
|
||||||
|
taken with the CMPXCHG and nothing else needs to be done.
|
||||||
|
|
||||||
|
If there is contention on the lock, whether it is owned or pending owner
|
||||||
|
we go about the slow path (rt_mutex_slowlock).
|
||||||
|
|
||||||
|
The slow path function is where the task's waiter structure is created on
|
||||||
|
the stack. This is because the waiter structure is only needed for the
|
||||||
|
scope of this function. The waiter structure holds the nodes to store
|
||||||
|
the task on the wait_list of the mutex, and if need be, the pi_list of
|
||||||
|
the owner.
|
||||||
|
|
||||||
|
The wait_lock of the mutex is taken since the slow path of unlocking the
|
||||||
|
mutex also takes this lock.
|
||||||
|
|
||||||
|
We then call try_to_take_rt_mutex. This is where the architecture that
|
||||||
|
does not implement CMPXCHG would always grab the lock (if there's no
|
||||||
|
contention).
|
||||||
|
|
||||||
|
try_to_take_rt_mutex is used every time the task tries to grab a mutex in the
|
||||||
|
slow path. The first thing that is done here is an atomic setting of
|
||||||
|
the "Has Waiters" flag of the mutex's owner field. Yes, this could really
|
||||||
|
be false, because if the the mutex has no owner, there are no waiters and
|
||||||
|
the current task also won't have any waiters. But we don't have the lock
|
||||||
|
yet, so we assume we are going to be a waiter. The reason for this is to
|
||||||
|
play nice for those architectures that do have CMPXCHG. By setting this flag
|
||||||
|
now, the owner of the mutex can't release the mutex without going into the
|
||||||
|
slow unlock path, and it would then need to grab the wait_lock, which this
|
||||||
|
code currently holds. So setting the "Has Waiters" flag forces the owner
|
||||||
|
to synchronize with this code.
|
||||||
|
|
||||||
|
Now that we know that we can't have any races with the owner releasing the
|
||||||
|
mutex, we check to see if we can take the ownership. This is done if the
|
||||||
|
mutex doesn't have a owner, or if we can steal the mutex from a pending
|
||||||
|
owner. Let's look at the situations we have here.
|
||||||
|
|
||||||
|
1) Has owner that is pending
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
The mutex has a owner, but it hasn't woken up and the mutex flag
|
||||||
|
"Pending Owner" is set. The first check is to see if the owner isn't the
|
||||||
|
current task. This is because this function is also used for the pending
|
||||||
|
owner to grab the mutex. When a pending owner wakes up, it checks to see
|
||||||
|
if it can take the mutex, and this is done if the owner is already set to
|
||||||
|
itself. If so, we succeed and leave the function, clearing the "Pending
|
||||||
|
Owner" bit.
|
||||||
|
|
||||||
|
If the pending owner is not current, we check to see if the current priority is
|
||||||
|
higher than the pending owner. If not, we fail the function and return.
|
||||||
|
|
||||||
|
There's also something special about a pending owner. That is a pending owner
|
||||||
|
is never blocked on a mutex. So there is no PI chain to worry about. It also
|
||||||
|
means that if the mutex doesn't have any waiters, there's no accounting needed
|
||||||
|
to update the pending owner's pi_list, since we only worry about processes
|
||||||
|
blocked on the current mutex.
|
||||||
|
|
||||||
|
If there are waiters on this mutex, and we just stole the ownership, we need
|
||||||
|
to take the top waiter, remove it from the pi_list of the pending owner, and
|
||||||
|
add it to the current pi_list. Note that at this moment, the pending owner
|
||||||
|
is no longer on the list of waiters. This is fine, since the pending owner
|
||||||
|
would add itself back when it realizes that it had the ownership stolen
|
||||||
|
from itself. When the pending owner tries to grab the mutex, it will fail
|
||||||
|
in try_to_take_rt_mutex if the owner field points to another process.
|
||||||
|
|
||||||
|
2) No owner
|
||||||
|
-----------
|
||||||
|
|
||||||
|
If there is no owner (or we successfully stole the lock), we set the owner
|
||||||
|
of the mutex to current, and set the flag of "Has Waiters" if the current
|
||||||
|
mutex actually has waiters, or we clear the flag if it doesn't. See, it was
|
||||||
|
OK that we set that flag early, since now it is cleared.
|
||||||
|
|
||||||
|
3) Failed to grab ownership
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The most interesting case is when we fail to take ownership. This means that
|
||||||
|
there exists an owner, or there's a pending owner with equal or higher
|
||||||
|
priority than the current task.
|
||||||
|
|
||||||
|
We'll continue on the failed case.
|
||||||
|
|
||||||
|
If the mutex has a timeout, we set up a timer to go off to break us out
|
||||||
|
of this mutex if we failed to get it after a specified amount of time.
|
||||||
|
|
||||||
|
Now we enter a loop that will continue to try to take ownership of the mutex, or
|
||||||
|
fail from a timeout or signal.
|
||||||
|
|
||||||
|
Once again we try to take the mutex. This will usually fail the first time
|
||||||
|
in the loop, since it had just failed to get the mutex. But the second time
|
||||||
|
in the loop, this would likely succeed, since the task would likely be
|
||||||
|
the pending owner.
|
||||||
|
|
||||||
|
If the mutex is TASK_INTERRUPTIBLE a check for signals and timeout is done
|
||||||
|
here.
|
||||||
|
|
||||||
|
The waiter structure has a "task" field that points to the task that is blocked
|
||||||
|
on the mutex. This field can be NULL the first time it goes through the loop
|
||||||
|
or if the task is a pending owner and had it's mutex stolen. If the "task"
|
||||||
|
field is NULL then we need to set up the accounting for it.
|
||||||
|
|
||||||
|
Task blocks on mutex
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The accounting of a mutex and process is done with the waiter structure of
|
||||||
|
the process. The "task" field is set to the process, and the "lock" field
|
||||||
|
to the mutex. The plist nodes are initialized to the processes current
|
||||||
|
priority.
|
||||||
|
|
||||||
|
Since the wait_lock was taken at the entry of the slow lock, we can safely
|
||||||
|
add the waiter to the wait_list. If the current process is the highest
|
||||||
|
priority process currently waiting on this mutex, then we remove the
|
||||||
|
previous top waiter process (if it exists) from the pi_list of the owner,
|
||||||
|
and add the current process to that list. Since the pi_list of the owner
|
||||||
|
has changed, we call rt_mutex_adjust_prio on the owner to see if the owner
|
||||||
|
should adjust its priority accordingly.
|
||||||
|
|
||||||
|
If the owner is also blocked on a lock, and had its pi_list changed
|
||||||
|
(or deadlock checking is on), we unlock the wait_lock of the mutex and go ahead
|
||||||
|
and run rt_mutex_adjust_prio_chain on the owner, as described earlier.
|
||||||
|
|
||||||
|
Now all locks are released, and if the current process is still blocked on a
|
||||||
|
mutex (waiter "task" field is not NULL), then we go to sleep (call schedule).
|
||||||
|
|
||||||
|
Waking up in the loop
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The schedule can then wake up for a few reasons.
|
||||||
|
1) we were given pending ownership of the mutex.
|
||||||
|
2) we received a signal and was TASK_INTERRUPTIBLE
|
||||||
|
3) we had a timeout and was TASK_INTERRUPTIBLE
|
||||||
|
|
||||||
|
In any of these cases, we continue the loop and once again try to grab the
|
||||||
|
ownership of the mutex. If we succeed, we exit the loop, otherwise we continue
|
||||||
|
and on signal and timeout, will exit the loop, or if we had the mutex stolen
|
||||||
|
we just simply add ourselves back on the lists and go back to sleep.
|
||||||
|
|
||||||
|
Note: For various reasons, because of timeout and signals, the steal mutex
|
||||||
|
algorithm needs to be careful. This is because the current process is
|
||||||
|
still on the wait_list. And because of dynamic changing of priorities,
|
||||||
|
especially on SCHED_OTHER tasks, the current process can be the
|
||||||
|
highest priority task on the wait_list.
|
||||||
|
|
||||||
|
Failed to get mutex on Timeout or Signal
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
If a timeout or signal occurred, the waiter's "task" field would not be
|
||||||
|
NULL and the task needs to be taken off the wait_list of the mutex and perhaps
|
||||||
|
pi_list of the owner. If this process was a high priority process, then
|
||||||
|
the rt_mutex_adjust_prio_chain needs to be executed again on the owner,
|
||||||
|
but this time it will be lowering the priorities.
|
||||||
|
|
||||||
|
|
||||||
|
Unlocking the Mutex
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The unlocking of a mutex also has a fast path for those architectures with
|
||||||
|
CMPXCHG. Since the taking of a mutex on contention always sets the
|
||||||
|
"Has Waiters" flag of the mutex's owner, we use this to know if we need to
|
||||||
|
take the slow path when unlocking the mutex. If the mutex doesn't have any
|
||||||
|
waiters, the owner field of the mutex would equal the current process and
|
||||||
|
the mutex can be unlocked by just replacing the owner field with NULL.
|
||||||
|
|
||||||
|
If the owner field has the "Has Waiters" bit set (or CMPXCHG is not available),
|
||||||
|
the slow unlock path is taken.
|
||||||
|
|
||||||
|
The first thing done in the slow unlock path is to take the wait_lock of the
|
||||||
|
mutex. This synchronizes the locking and unlocking of the mutex.
|
||||||
|
|
||||||
|
A check is made to see if the mutex has waiters or not. On architectures that
|
||||||
|
do not have CMPXCHG, this is the location that the owner of the mutex will
|
||||||
|
determine if a waiter needs to be awoken or not. On architectures that
|
||||||
|
do have CMPXCHG, that check is done in the fast path, but it is still needed
|
||||||
|
in the slow path too. If a waiter of a mutex woke up because of a signal
|
||||||
|
or timeout between the time the owner failed the fast path CMPXCHG check and
|
||||||
|
the grabbing of the wait_lock, the mutex may not have any waiters, thus the
|
||||||
|
owner still needs to make this check. If there are no waiters than the mutex
|
||||||
|
owner field is set to NULL, the wait_lock is released and nothing more is
|
||||||
|
needed.
|
||||||
|
|
||||||
|
If there are waiters, then we need to wake one up and give that waiter
|
||||||
|
pending ownership.
|
||||||
|
|
||||||
|
On the wake up code, the pi_lock of the current owner is taken. The top
|
||||||
|
waiter of the lock is found and removed from the wait_list of the mutex
|
||||||
|
as well as the pi_list of the current owner. The task field of the new
|
||||||
|
pending owner's waiter structure is set to NULL, and the owner field of the
|
||||||
|
mutex is set to the new owner with the "Pending Owner" bit set, as well
|
||||||
|
as the "Has Waiters" bit if there still are other processes blocked on the
|
||||||
|
mutex.
|
||||||
|
|
||||||
|
The pi_lock of the previous owner is released, and the new pending owner's
|
||||||
|
pi_lock is taken. Remember that this is the trick to prevent the race
|
||||||
|
condition in rt_mutex_adjust_prio_chain from adding itself as a waiter
|
||||||
|
on the mutex.
|
||||||
|
|
||||||
|
We now clear the "pi_blocked_on" field of the new pending owner, and if
|
||||||
|
the mutex still has waiters pending, we add the new top waiter to the pi_list
|
||||||
|
of the pending owner.
|
||||||
|
|
||||||
|
Finally we unlock the pi_lock of the pending owner and wake it up.
|
||||||
|
|
||||||
|
|
||||||
|
Contact
|
||||||
|
-------
|
||||||
|
|
||||||
|
For updates on this document, please email Steven Rostedt <rostedt@goodmis.org>
|
||||||
|
|
||||||
|
|
||||||
|
Credits
|
||||||
|
-------
|
||||||
|
|
||||||
|
Author: Steven Rostedt <rostedt@goodmis.org>
|
||||||
|
|
||||||
|
Reviewers: Ingo Molnar, Thomas Gleixner, Thomas Duetsch, and Randy Dunlap
|
||||||
|
|
||||||
|
Updates
|
||||||
|
-------
|
||||||
|
|
||||||
|
This document was originally written for 2.6.17-rc3-mm1
|
79
Documentation/rt-mutex.txt
Normal file
79
Documentation/rt-mutex.txt
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
RT-mutex subsystem with PI support
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
RT-mutexes with priority inheritance are used to support PI-futexes,
|
||||||
|
which enable pthread_mutex_t priority inheritance attributes
|
||||||
|
(PTHREAD_PRIO_INHERIT). [See Documentation/pi-futex.txt for more details
|
||||||
|
about PI-futexes.]
|
||||||
|
|
||||||
|
This technology was developed in the -rt tree and streamlined for
|
||||||
|
pthread_mutex support.
|
||||||
|
|
||||||
|
Basic principles:
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
RT-mutexes extend the semantics of simple mutexes by the priority
|
||||||
|
inheritance protocol.
|
||||||
|
|
||||||
|
A low priority owner of a rt-mutex inherits the priority of a higher
|
||||||
|
priority waiter until the rt-mutex is released. If the temporarily
|
||||||
|
boosted owner blocks on a rt-mutex itself it propagates the priority
|
||||||
|
boosting to the owner of the other rt_mutex it gets blocked on. The
|
||||||
|
priority boosting is immediately removed once the rt_mutex has been
|
||||||
|
unlocked.
|
||||||
|
|
||||||
|
This approach allows us to shorten the block of high-prio tasks on
|
||||||
|
mutexes which protect shared resources. Priority inheritance is not a
|
||||||
|
magic bullet for poorly designed applications, but it allows
|
||||||
|
well-designed applications to use userspace locks in critical parts of
|
||||||
|
an high priority thread, without losing determinism.
|
||||||
|
|
||||||
|
The enqueueing of the waiters into the rtmutex waiter list is done in
|
||||||
|
priority order. For same priorities FIFO order is chosen. For each
|
||||||
|
rtmutex, only the top priority waiter is enqueued into the owner's
|
||||||
|
priority waiters list. This list too queues in priority order. Whenever
|
||||||
|
the top priority waiter of a task changes (for example it timed out or
|
||||||
|
got a signal), the priority of the owner task is readjusted. [The
|
||||||
|
priority enqueueing is handled by "plists", see include/linux/plist.h
|
||||||
|
for more details.]
|
||||||
|
|
||||||
|
RT-mutexes are optimized for fastpath operations and have no internal
|
||||||
|
locking overhead when locking an uncontended mutex or unlocking a mutex
|
||||||
|
without waiters. The optimized fastpath operations require cmpxchg
|
||||||
|
support. [If that is not available then the rt-mutex internal spinlock
|
||||||
|
is used]
|
||||||
|
|
||||||
|
The state of the rt-mutex is tracked via the owner field of the rt-mutex
|
||||||
|
structure:
|
||||||
|
|
||||||
|
rt_mutex->owner holds the task_struct pointer of the owner. Bit 0 and 1
|
||||||
|
are used to keep track of the "owner is pending" and "rtmutex has
|
||||||
|
waiters" state.
|
||||||
|
|
||||||
|
owner bit1 bit0
|
||||||
|
NULL 0 0 mutex is free (fast acquire possible)
|
||||||
|
NULL 0 1 invalid state
|
||||||
|
NULL 1 0 Transitional state*
|
||||||
|
NULL 1 1 invalid state
|
||||||
|
taskpointer 0 0 mutex is held (fast release possible)
|
||||||
|
taskpointer 0 1 task is pending owner
|
||||||
|
taskpointer 1 0 mutex is held and has waiters
|
||||||
|
taskpointer 1 1 task is pending owner and mutex has waiters
|
||||||
|
|
||||||
|
Pending-ownership handling is a performance optimization:
|
||||||
|
pending-ownership is assigned to the first (highest priority) waiter of
|
||||||
|
the mutex, when the mutex is released. The thread is woken up and once
|
||||||
|
it starts executing it can acquire the mutex. Until the mutex is taken
|
||||||
|
by it (bit 0 is cleared) a competing higher priority thread can "steal"
|
||||||
|
the mutex which puts the woken up thread back on the waiters list.
|
||||||
|
|
||||||
|
The pending-ownership optimization is especially important for the
|
||||||
|
uninterrupted workflow of high-prio tasks which repeatedly
|
||||||
|
takes/releases locks that have lower-prio waiters. Without this
|
||||||
|
optimization the higher-prio thread would ping-pong to the lower-prio
|
||||||
|
task [because at unlock time we always assign a new owner].
|
||||||
|
|
||||||
|
(*) The "mutex has waiters" bit gets set to take the lock. If the lock
|
||||||
|
doesn't already have an owner, this bit is quickly cleared if there are
|
||||||
|
no waiters. So this is a transitional state to synchronize with looking
|
||||||
|
at the owner field of the mutex and the mutex owner releasing the lock.
|
@@ -12,5 +12,3 @@ http://www.torque.net/parport/
|
|||||||
Email list for Linux Parport
|
Email list for Linux Parport
|
||||||
linux-parport@torque.net
|
linux-parport@torque.net
|
||||||
|
|
||||||
Email for problems with ZIP or ZIP Plus drivers
|
|
||||||
campbell@torque.net
|
|
||||||
|
@@ -80,13 +80,6 @@ receive_buf() - Hand buffers of bytes from the driver to the ldisc
|
|||||||
for processing. Semantics currently rather
|
for processing. Semantics currently rather
|
||||||
mysterious 8(
|
mysterious 8(
|
||||||
|
|
||||||
receive_room() - Can be called by the driver layer at any time when
|
|
||||||
the ldisc is opened. The ldisc must be able to
|
|
||||||
handle the reported amount of data at that instant.
|
|
||||||
Synchronization between active receive_buf and
|
|
||||||
receive_room calls is down to the driver not the
|
|
||||||
ldisc. Must not sleep.
|
|
||||||
|
|
||||||
write_wakeup() - May be called at any point between open and close.
|
write_wakeup() - May be called at any point between open and close.
|
||||||
The TTY_DO_WRITE_WAKEUP flag indicates if a call
|
The TTY_DO_WRITE_WAKEUP flag indicates if a call
|
||||||
is needed but always races versus calls. Thus the
|
is needed but always races versus calls. Thus the
|
||||||
|
212
Documentation/video4linux/README.pvrusb2
Normal file
212
Documentation/video4linux/README.pvrusb2
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
|
||||||
|
$Id$
|
||||||
|
Mike Isely <isely@pobox.com>
|
||||||
|
|
||||||
|
pvrusb2 driver
|
||||||
|
|
||||||
|
Background:
|
||||||
|
|
||||||
|
This driver is intended for the "Hauppauge WinTV PVR USB 2.0", which
|
||||||
|
is a USB 2.0 hosted TV Tuner. This driver is a work in progress.
|
||||||
|
Its history started with the reverse-engineering effort by Bj<42>rn
|
||||||
|
Danielsson <pvrusb2@dax.nu> whose web page can be found here:
|
||||||
|
|
||||||
|
http://pvrusb2.dax.nu/
|
||||||
|
|
||||||
|
From there Aurelien Alleaume <slts@free.fr> began an effort to
|
||||||
|
create a video4linux compatible driver. I began with Aurelien's
|
||||||
|
last known snapshot and evolved the driver to the state it is in
|
||||||
|
here.
|
||||||
|
|
||||||
|
More information on this driver can be found at:
|
||||||
|
|
||||||
|
http://www.isely.net/pvrusb2.html
|
||||||
|
|
||||||
|
|
||||||
|
This driver has a strong separation of layers. They are very
|
||||||
|
roughly:
|
||||||
|
|
||||||
|
1a. Low level wire-protocol implementation with the device.
|
||||||
|
|
||||||
|
1b. I2C adaptor implementation and corresponding I2C client drivers
|
||||||
|
implemented elsewhere in V4L.
|
||||||
|
|
||||||
|
1c. High level hardware driver implementation which coordinates all
|
||||||
|
activities that ensure correct operation of the device.
|
||||||
|
|
||||||
|
2. A "context" layer which manages instancing of driver, setup,
|
||||||
|
tear-down, arbitration, and interaction with high level
|
||||||
|
interfaces appropriately as devices are hotplugged in the
|
||||||
|
system.
|
||||||
|
|
||||||
|
3. High level interfaces which glue the driver to various published
|
||||||
|
Linux APIs (V4L, sysfs, maybe DVB in the future).
|
||||||
|
|
||||||
|
The most important shearing layer is between the top 2 layers. A
|
||||||
|
lot of work went into the driver to ensure that any kind of
|
||||||
|
conceivable API can be laid on top of the core driver. (Yes, the
|
||||||
|
driver internally leverages V4L to do its work but that really has
|
||||||
|
nothing to do with the API published by the driver to the outside
|
||||||
|
world.) The architecture allows for different APIs to
|
||||||
|
simultaneously access the driver. I have a strong sense of fairness
|
||||||
|
about APIs and also feel that it is a good design principle to keep
|
||||||
|
implementation and interface isolated from each other. Thus while
|
||||||
|
right now the V4L high level interface is the most complete, the
|
||||||
|
sysfs high level interface will work equally well for similar
|
||||||
|
functions, and there's no reason I see right now why it shouldn't be
|
||||||
|
possible to produce a DVB high level interface that can sit right
|
||||||
|
alongside V4L.
|
||||||
|
|
||||||
|
NOTE: Complete documentation on the pvrusb2 driver is contained in
|
||||||
|
the html files within the doc directory; these are exactly the same
|
||||||
|
as what is on the web site at the time. Browse those files
|
||||||
|
(especially the FAQ) before asking questions.
|
||||||
|
|
||||||
|
|
||||||
|
Building
|
||||||
|
|
||||||
|
To build these modules essentially amounts to just running "Make",
|
||||||
|
but you need the kernel source tree nearby and you will likely also
|
||||||
|
want to set a few controlling environment variables first in order
|
||||||
|
to link things up with that source tree. Please see the Makefile
|
||||||
|
here for comments that explain how to do that.
|
||||||
|
|
||||||
|
|
||||||
|
Source file list / functional overview:
|
||||||
|
|
||||||
|
(Note: The term "module" used below generally refers to loosely
|
||||||
|
defined functional units within the pvrusb2 driver and bears no
|
||||||
|
relation to the Linux kernel's concept of a loadable module.)
|
||||||
|
|
||||||
|
pvrusb2-audio.[ch] - This is glue logic that resides between this
|
||||||
|
driver and the msp3400.ko I2C client driver (which is found
|
||||||
|
elsewhere in V4L).
|
||||||
|
|
||||||
|
pvrusb2-context.[ch] - This module implements the context for an
|
||||||
|
instance of the driver. Everything else eventually ties back to
|
||||||
|
or is otherwise instanced within the data structures implemented
|
||||||
|
here. Hotplugging is ultimately coordinated here. All high level
|
||||||
|
interfaces tie into the driver through this module. This module
|
||||||
|
helps arbitrate each interface's access to the actual driver core,
|
||||||
|
and is designed to allow concurrent access through multiple
|
||||||
|
instances of multiple interfaces (thus you can for example change
|
||||||
|
the tuner's frequency through sysfs while simultaneously streaming
|
||||||
|
video through V4L out to an instance of mplayer).
|
||||||
|
|
||||||
|
pvrusb2-debug.h - This header defines a printk() wrapper and a mask
|
||||||
|
of debugging bit definitions for the various kinds of debug
|
||||||
|
messages that can be enabled within the driver.
|
||||||
|
|
||||||
|
pvrusb2-debugifc.[ch] - This module implements a crude command line
|
||||||
|
oriented debug interface into the driver. Aside from being part
|
||||||
|
of the process for implementing manual firmware extraction (see
|
||||||
|
the pvrusb2 web site mentioned earlier), probably I'm the only one
|
||||||
|
who has ever used this. It is mainly a debugging aid.
|
||||||
|
|
||||||
|
pvrusb2-eeprom.[ch] - This is glue logic that resides between this
|
||||||
|
driver the tveeprom.ko module, which is itself implemented
|
||||||
|
elsewhere in V4L.
|
||||||
|
|
||||||
|
pvrusb2-encoder.[ch] - This module implements all protocol needed to
|
||||||
|
interact with the Conexant mpeg2 encoder chip within the pvrusb2
|
||||||
|
device. It is a crude echo of corresponding logic in ivtv,
|
||||||
|
however the design goals (strict isolation) and physical layer
|
||||||
|
(proxy through USB instead of PCI) are enough different that this
|
||||||
|
implementation had to be completely different.
|
||||||
|
|
||||||
|
pvrusb2-hdw-internal.h - This header defines the core data structure
|
||||||
|
in the driver used to track ALL internal state related to control
|
||||||
|
of the hardware. Nobody outside of the core hardware-handling
|
||||||
|
modules should have any business using this header. All external
|
||||||
|
access to the driver should be through one of the high level
|
||||||
|
interfaces (e.g. V4L, sysfs, etc), and in fact even those high
|
||||||
|
level interfaces are restricted to the API defined in
|
||||||
|
pvrusb2-hdw.h and NOT this header.
|
||||||
|
|
||||||
|
pvrusb2-hdw.h - This header defines the full internal API for
|
||||||
|
controlling the hardware. High level interfaces (e.g. V4L, sysfs)
|
||||||
|
will work through here.
|
||||||
|
|
||||||
|
pvrusb2-hdw.c - This module implements all the various bits of logic
|
||||||
|
that handle overall control of a specific pvrusb2 device.
|
||||||
|
(Policy, instantiation, and arbitration of pvrusb2 devices fall
|
||||||
|
within the jurisdiction of pvrusb-context not here).
|
||||||
|
|
||||||
|
pvrusb2-i2c-chips-*.c - These modules implement the glue logic to
|
||||||
|
tie together and configure various I2C modules as they attach to
|
||||||
|
the I2C bus. There are two versions of this file. The "v4l2"
|
||||||
|
version is intended to be used in-tree alongside V4L, where we
|
||||||
|
implement just the logic that makes sense for a pure V4L
|
||||||
|
environment. The "all" version is intended for use outside of
|
||||||
|
V4L, where we might encounter other possibly "challenging" modules
|
||||||
|
from ivtv or older kernel snapshots (or even the support modules
|
||||||
|
in the standalone snapshot).
|
||||||
|
|
||||||
|
pvrusb2-i2c-cmd-v4l1.[ch] - This module implements generic V4L1
|
||||||
|
compatible commands to the I2C modules. It is here where state
|
||||||
|
changes inside the pvrusb2 driver are translated into V4L1
|
||||||
|
commands that are in turn send to the various I2C modules.
|
||||||
|
|
||||||
|
pvrusb2-i2c-cmd-v4l2.[ch] - This module implements generic V4L2
|
||||||
|
compatible commands to the I2C modules. It is here where state
|
||||||
|
changes inside the pvrusb2 driver are translated into V4L2
|
||||||
|
commands that are in turn send to the various I2C modules.
|
||||||
|
|
||||||
|
pvrusb2-i2c-core.[ch] - This module provides an implementation of a
|
||||||
|
kernel-friendly I2C adaptor driver, through which other external
|
||||||
|
I2C client drivers (e.g. msp3400, tuner, lirc) may connect and
|
||||||
|
operate corresponding chips within the the pvrusb2 device. It is
|
||||||
|
through here that other V4L modules can reach into this driver to
|
||||||
|
operate specific pieces (and those modules are in turn driven by
|
||||||
|
glue logic which is coordinated by pvrusb2-hdw, doled out by
|
||||||
|
pvrusb2-context, and then ultimately made available to users
|
||||||
|
through one of the high level interfaces).
|
||||||
|
|
||||||
|
pvrusb2-io.[ch] - This module implements a very low level ring of
|
||||||
|
transfer buffers, required in order to stream data from the
|
||||||
|
device. This module is *very* low level. It only operates the
|
||||||
|
buffers and makes no attempt to define any policy or mechanism for
|
||||||
|
how such buffers might be used.
|
||||||
|
|
||||||
|
pvrusb2-ioread.[ch] - This module layers on top of pvrusb2-io.[ch]
|
||||||
|
to provide a streaming API usable by a read() system call style of
|
||||||
|
I/O. Right now this is the only layer on top of pvrusb2-io.[ch],
|
||||||
|
however the underlying architecture here was intended to allow for
|
||||||
|
other styles of I/O to be implemented with additonal modules, like
|
||||||
|
mmap()'ed buffers or something even more exotic.
|
||||||
|
|
||||||
|
pvrusb2-main.c - This is the top level of the driver. Module level
|
||||||
|
and USB core entry points are here. This is our "main".
|
||||||
|
|
||||||
|
pvrusb2-sysfs.[ch] - This is the high level interface which ties the
|
||||||
|
pvrusb2 driver into sysfs. Through this interface you can do
|
||||||
|
everything with the driver except actually stream data.
|
||||||
|
|
||||||
|
pvrusb2-tuner.[ch] - This is glue logic that resides between this
|
||||||
|
driver and the tuner.ko I2C client driver (which is found
|
||||||
|
elsewhere in V4L).
|
||||||
|
|
||||||
|
pvrusb2-util.h - This header defines some common macros used
|
||||||
|
throughout the driver. These macros are not really specific to
|
||||||
|
the driver, but they had to go somewhere.
|
||||||
|
|
||||||
|
pvrusb2-v4l2.[ch] - This is the high level interface which ties the
|
||||||
|
pvrusb2 driver into video4linux. It is through here that V4L
|
||||||
|
applications can open and operate the driver in the usual V4L
|
||||||
|
ways. Note that **ALL** V4L functionality is published only
|
||||||
|
through here and nowhere else.
|
||||||
|
|
||||||
|
pvrusb2-video-*.[ch] - This is glue logic that resides between this
|
||||||
|
driver and the saa711x.ko I2C client driver (which is found
|
||||||
|
elsewhere in V4L). Note that saa711x.ko used to be known as
|
||||||
|
saa7115.ko in ivtv. There are two versions of this; one is
|
||||||
|
selected depending on the particular saa711[5x].ko that is found.
|
||||||
|
|
||||||
|
pvrusb2.h - This header contains compile time tunable parameters
|
||||||
|
(and at the moment the driver has very little that needs to be
|
||||||
|
tuned).
|
||||||
|
|
||||||
|
|
||||||
|
-Mike Isely
|
||||||
|
isely@pobox.com
|
||||||
|
|
@@ -205,6 +205,27 @@ IOMMU
|
|||||||
pages Prereserve that many 128K pages for the software IO bounce buffering.
|
pages Prereserve that many 128K pages for the software IO bounce buffering.
|
||||||
force Force all IO through the software TLB.
|
force Force all IO through the software TLB.
|
||||||
|
|
||||||
|
calgary=[64k,128k,256k,512k,1M,2M,4M,8M]
|
||||||
|
calgary=[translate_empty_slots]
|
||||||
|
calgary=[disable=<PCI bus number>]
|
||||||
|
|
||||||
|
64k,...,8M - Set the size of each PCI slot's translation table
|
||||||
|
when using the Calgary IOMMU. This is the size of the translation
|
||||||
|
table itself in main memory. The smallest table, 64k, covers an IO
|
||||||
|
space of 32MB; the largest, 8MB table, can cover an IO space of
|
||||||
|
4GB. Normally the kernel will make the right choice by itself.
|
||||||
|
|
||||||
|
translate_empty_slots - Enable translation even on slots that have
|
||||||
|
no devices attached to them, in case a device will be hotplugged
|
||||||
|
in the future.
|
||||||
|
|
||||||
|
disable=<PCI bus number> - Disable translation on a given PHB. For
|
||||||
|
example, the built-in graphics adapter resides on the first bridge
|
||||||
|
(PCI bus number 0); if translation (isolation) is enabled on this
|
||||||
|
bridge, X servers that access the hardware directly from user
|
||||||
|
space might stop working. Use this option if you have devices that
|
||||||
|
are accessed from userspace directly on some PCI host bridge.
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
|
|
||||||
oops=panic Always panic on oopses. Default is to just kill the process,
|
oops=panic Always panic on oopses. Default is to just kill the process,
|
||||||
|
18
MAINTAINERS
18
MAINTAINERS
@@ -1118,6 +1118,11 @@ L: lm-sensors@lm-sensors.org
|
|||||||
W: http://www.lm-sensors.nu/
|
W: http://www.lm-sensors.nu/
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
HARDWARE RANDOM NUMBER GENERATOR CORE
|
||||||
|
P: Michael Buesch
|
||||||
|
M: mb@bu3sch.de
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
|
HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
|
||||||
P: Robert Love
|
P: Robert Love
|
||||||
M: rlove@rlove.org
|
M: rlove@rlove.org
|
||||||
@@ -1396,7 +1401,8 @@ S: Supported
|
|||||||
|
|
||||||
INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
|
INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
|
||||||
P: Dmitry Torokhov
|
P: Dmitry Torokhov
|
||||||
M: dtor_core@ameritech.net
|
M: dmitry.torokhov@gmail.com
|
||||||
|
M: dtor@mail.ru
|
||||||
L: linux-input@atrey.karlin.mff.cuni.cz
|
L: linux-input@atrey.karlin.mff.cuni.cz
|
||||||
L: linux-joystick@atrey.karlin.mff.cuni.cz
|
L: linux-joystick@atrey.karlin.mff.cuni.cz
|
||||||
T: git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git
|
T: git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git
|
||||||
@@ -1436,6 +1442,11 @@ P: Tigran Aivazian
|
|||||||
M: tigran@veritas.com
|
M: tigran@veritas.com
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
|
||||||
|
P: Deepak Saxena
|
||||||
|
M: dsaxena@plexity.net
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
INTEL PRO/100 ETHERNET SUPPORT
|
INTEL PRO/100 ETHERNET SUPPORT
|
||||||
P: John Ronciak
|
P: John Ronciak
|
||||||
M: john.ronciak@intel.com
|
M: john.ronciak@intel.com
|
||||||
@@ -2725,6 +2736,11 @@ P: Christoph Hellwig
|
|||||||
M: hch@infradead.org
|
M: hch@infradead.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
TI OMAP RANDOM NUMBER GENERATOR SUPPORT
|
||||||
|
P: Deepak Saxena
|
||||||
|
M: dsaxena@plexity.net
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
TI PARALLEL LINK CABLE DRIVER
|
TI PARALLEL LINK CABLE DRIVER
|
||||||
P: Romain Lievin
|
P: Romain Lievin
|
||||||
M: roms@lpg.ticalc.org
|
M: roms@lpg.ticalc.org
|
||||||
|
213
Makefile
213
Makefile
@@ -71,7 +71,7 @@ endif
|
|||||||
# In both cases the working directory must be the root of the kernel src.
|
# In both cases the working directory must be the root of the kernel src.
|
||||||
# 1) O=
|
# 1) O=
|
||||||
# Use "make O=dir/to/store/output/files/"
|
# Use "make O=dir/to/store/output/files/"
|
||||||
#
|
#
|
||||||
# 2) Set KBUILD_OUTPUT
|
# 2) Set KBUILD_OUTPUT
|
||||||
# Set the environment variable KBUILD_OUTPUT to point to the directory
|
# Set the environment variable KBUILD_OUTPUT to point to the directory
|
||||||
# where the output files shall be placed.
|
# where the output files shall be placed.
|
||||||
@@ -178,18 +178,20 @@ CROSS_COMPILE ?=
|
|||||||
# Architecture as present in compile.h
|
# Architecture as present in compile.h
|
||||||
UTS_MACHINE := $(ARCH)
|
UTS_MACHINE := $(ARCH)
|
||||||
|
|
||||||
|
KCONFIG_CONFIG ?= .config
|
||||||
|
|
||||||
# SHELL used by kbuild
|
# SHELL used by kbuild
|
||||||
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
|
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
|
||||||
else if [ -x /bin/bash ]; then echo /bin/bash; \
|
else if [ -x /bin/bash ]; then echo /bin/bash; \
|
||||||
else echo sh; fi ; fi)
|
else echo sh; fi ; fi)
|
||||||
|
|
||||||
HOSTCC = gcc
|
HOSTCC = gcc
|
||||||
HOSTCXX = g++
|
HOSTCXX = g++
|
||||||
HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
|
HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
|
||||||
HOSTCXXFLAGS = -O2
|
HOSTCXXFLAGS = -O2
|
||||||
|
|
||||||
# Decide whether to build built-in, modular, or both.
|
# Decide whether to build built-in, modular, or both.
|
||||||
# Normally, just do built-in.
|
# Normally, just do built-in.
|
||||||
|
|
||||||
KBUILD_MODULES :=
|
KBUILD_MODULES :=
|
||||||
KBUILD_BUILTIN := 1
|
KBUILD_BUILTIN := 1
|
||||||
@@ -197,7 +199,7 @@ KBUILD_BUILTIN := 1
|
|||||||
# If we have only "make modules", don't compile built-in objects.
|
# If we have only "make modules", don't compile built-in objects.
|
||||||
# When we're building modules with modversions, we need to consider
|
# When we're building modules with modversions, we need to consider
|
||||||
# the built-in objects during the descend as well, in order to
|
# the built-in objects during the descend as well, in order to
|
||||||
# make sure the checksums are uptodate before we record them.
|
# make sure the checksums are up to date before we record them.
|
||||||
|
|
||||||
ifeq ($(MAKECMDGOALS),modules)
|
ifeq ($(MAKECMDGOALS),modules)
|
||||||
KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
|
KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
|
||||||
@@ -230,7 +232,7 @@ export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
|
|||||||
#
|
#
|
||||||
# If $(quiet) is empty, the whole command will be printed.
|
# If $(quiet) is empty, the whole command will be printed.
|
||||||
# If it is set to "quiet_", only the short version will be printed.
|
# If it is set to "quiet_", only the short version will be printed.
|
||||||
# If it is set to "silent_", nothing wil be printed at all, since
|
# If it is set to "silent_", nothing will be printed at all, since
|
||||||
# the variable $(silent_cmd_cc_o_c) doesn't exist.
|
# the variable $(silent_cmd_cc_o_c) doesn't exist.
|
||||||
#
|
#
|
||||||
# A simple variant is to prefix commands with $(Q) - that's useful
|
# A simple variant is to prefix commands with $(Q) - that's useful
|
||||||
@@ -265,10 +267,9 @@ MAKEFLAGS += --include-dir=$(srctree)
|
|||||||
# We need some generic definitions
|
# We need some generic definitions
|
||||||
include $(srctree)/scripts/Kbuild.include
|
include $(srctree)/scripts/Kbuild.include
|
||||||
|
|
||||||
# For maximum performance (+ possibly random breakage, uncomment
|
# Do not use make's built-in rules and variables
|
||||||
# the following)
|
# This increases performance and avoid hard-to-debug behavour
|
||||||
|
MAKEFLAGS += -rR
|
||||||
#MAKEFLAGS += -rR
|
|
||||||
|
|
||||||
# Make variables (CC, etc...)
|
# Make variables (CC, etc...)
|
||||||
|
|
||||||
@@ -305,21 +306,21 @@ LINUXINCLUDE := -Iinclude \
|
|||||||
|
|
||||||
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
||||||
|
|
||||||
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
|
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
|
||||||
-fno-strict-aliasing -fno-common
|
-fno-strict-aliasing -fno-common
|
||||||
AFLAGS := -D__ASSEMBLY__
|
AFLAGS := -D__ASSEMBLY__
|
||||||
|
|
||||||
# Read KERNELRELEASE from .kernelrelease (if it exists)
|
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
|
||||||
KERNELRELEASE = $(shell cat .kernelrelease 2> /dev/null)
|
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
|
||||||
KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
|
KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
|
||||||
|
|
||||||
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION \
|
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
|
||||||
ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
|
export ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
|
||||||
CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
|
export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
|
||||||
HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
|
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
|
||||||
|
|
||||||
export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
|
export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
|
||||||
export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
|
export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
|
||||||
export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
|
export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
|
||||||
|
|
||||||
# When compiling out-of-tree modules, put MODVERDIR in the module
|
# When compiling out-of-tree modules, put MODVERDIR in the module
|
||||||
@@ -357,12 +358,13 @@ endif
|
|||||||
# catch them early, and hand them over to scripts/kconfig/Makefile
|
# catch them early, and hand them over to scripts/kconfig/Makefile
|
||||||
# It is allowed to specify more targets when calling make, including
|
# It is allowed to specify more targets when calling make, including
|
||||||
# mixing *config targets and build targets.
|
# mixing *config targets and build targets.
|
||||||
# For example 'make oldconfig all'.
|
# For example 'make oldconfig all'.
|
||||||
# Detect when mixed targets is specified, and make a second invocation
|
# Detect when mixed targets is specified, and make a second invocation
|
||||||
# of make so .config is not included in this case either (for *config).
|
# of make so .config is not included in this case either (for *config).
|
||||||
|
|
||||||
no-dot-config-targets := clean mrproper distclean \
|
no-dot-config-targets := clean mrproper distclean \
|
||||||
cscope TAGS tags help %docs check%
|
cscope TAGS tags help %docs check% \
|
||||||
|
kernelrelease kernelversion
|
||||||
|
|
||||||
config-targets := 0
|
config-targets := 0
|
||||||
mixed-targets := 0
|
mixed-targets := 0
|
||||||
@@ -404,9 +406,8 @@ include $(srctree)/arch/$(ARCH)/Makefile
|
|||||||
export KBUILD_DEFCONFIG
|
export KBUILD_DEFCONFIG
|
||||||
|
|
||||||
config %config: scripts_basic outputmakefile FORCE
|
config %config: scripts_basic outputmakefile FORCE
|
||||||
$(Q)mkdir -p include/linux
|
$(Q)mkdir -p include/linux include/config
|
||||||
$(Q)$(MAKE) $(build)=scripts/kconfig $@
|
$(Q)$(MAKE) $(build)=scripts/kconfig $@
|
||||||
$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease
|
|
||||||
|
|
||||||
else
|
else
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
@@ -416,13 +417,11 @@ else
|
|||||||
ifeq ($(KBUILD_EXTMOD),)
|
ifeq ($(KBUILD_EXTMOD),)
|
||||||
# Additional helpers built in scripts/
|
# Additional helpers built in scripts/
|
||||||
# Carefully list dependencies so we do not try to build scripts twice
|
# Carefully list dependencies so we do not try to build scripts twice
|
||||||
# in parrallel
|
# in parallel
|
||||||
PHONY += scripts
|
PHONY += scripts
|
||||||
scripts: scripts_basic include/config/MARKER
|
scripts: scripts_basic include/config/auto.conf
|
||||||
$(Q)$(MAKE) $(build)=$(@)
|
$(Q)$(MAKE) $(build)=$(@)
|
||||||
|
|
||||||
scripts_basic: include/linux/autoconf.h
|
|
||||||
|
|
||||||
# Objects we will link into vmlinux / subdirs we need to visit
|
# Objects we will link into vmlinux / subdirs we need to visit
|
||||||
init-y := init/
|
init-y := init/
|
||||||
drivers-y := drivers/ sound/
|
drivers-y := drivers/ sound/
|
||||||
@@ -436,31 +435,32 @@ ifeq ($(dot-config),1)
|
|||||||
|
|
||||||
# Read in dependencies to all Kconfig* files, make sure to run
|
# Read in dependencies to all Kconfig* files, make sure to run
|
||||||
# oldconfig if changes are detected.
|
# oldconfig if changes are detected.
|
||||||
-include .kconfig.d
|
-include include/config/auto.conf.cmd
|
||||||
|
-include include/config/auto.conf
|
||||||
|
|
||||||
include .config
|
|
||||||
|
|
||||||
# If .config needs to be updated, it will be done via the dependency
|
|
||||||
# that autoconf has on .config.
|
|
||||||
# To avoid any implicit rule to kick in, define an empty command
|
# To avoid any implicit rule to kick in, define an empty command
|
||||||
.config .kconfig.d: ;
|
$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
|
||||||
|
|
||||||
# If .config is newer than include/linux/autoconf.h, someone tinkered
|
# If .config is newer than include/config/auto.conf, someone tinkered
|
||||||
# with it and forgot to run make oldconfig.
|
# with it and forgot to run make oldconfig.
|
||||||
# If kconfig.d is missing then we are probarly in a cleaned tree so
|
# if auto.conf.cmd is missing then we are probably in a cleaned tree so
|
||||||
# we execute the config step to be sure to catch updated Kconfig files
|
# we execute the config step to be sure to catch updated Kconfig files
|
||||||
include/linux/autoconf.h: .kconfig.d .config
|
include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
|
||||||
$(Q)mkdir -p include/linux
|
ifeq ($(KBUILD_EXTMOD),)
|
||||||
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
|
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
|
||||||
|
else
|
||||||
|
$(error kernel configuration not valid - run 'make prepare' in $(srctree) to update it)
|
||||||
|
endif
|
||||||
|
|
||||||
else
|
else
|
||||||
# Dummy target needed, because used as prerequisite
|
# Dummy target needed, because used as prerequisite
|
||||||
include/linux/autoconf.h: ;
|
include/config/auto.conf: ;
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# The all: target is the default when no target is given on the
|
# The all: target is the default when no target is given on the
|
||||||
# command line.
|
# command line.
|
||||||
# This allow a user to issue only 'make' to build a kernel including modules
|
# This allow a user to issue only 'make' to build a kernel including modules
|
||||||
# Defaults vmlinux but it is usually overriden in the arch makefile
|
# Defaults vmlinux but it is usually overridden in the arch makefile
|
||||||
all: vmlinux
|
all: vmlinux
|
||||||
|
|
||||||
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||||
@@ -492,11 +492,11 @@ CHECKFLAGS += $(NOSTDINC_FLAGS)
|
|||||||
# warn about C99 declaration after statement
|
# warn about C99 declaration after statement
|
||||||
CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
|
CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
|
||||||
|
|
||||||
# disable pointer signedness warnings in gcc 4.0
|
# disable pointer signed / unsigned warnings in gcc 4.0
|
||||||
CFLAGS += $(call cc-option,-Wno-pointer-sign,)
|
CFLAGS += $(call cc-option,-Wno-pointer-sign,)
|
||||||
|
|
||||||
# Default kernel image to build when no specific target is given.
|
# Default kernel image to build when no specific target is given.
|
||||||
# KBUILD_IMAGE may be overruled on the commandline or
|
# KBUILD_IMAGE may be overruled on the command line or
|
||||||
# set in the environment
|
# set in the environment
|
||||||
# Also any assignments in arch/$(ARCH)/Makefile take precedence over
|
# Also any assignments in arch/$(ARCH)/Makefile take precedence over
|
||||||
# this default value
|
# this default value
|
||||||
@@ -510,12 +510,29 @@ export INSTALL_PATH ?= /boot
|
|||||||
#
|
#
|
||||||
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
|
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
|
||||||
# relocations required by build roots. This is not defined in the
|
# relocations required by build roots. This is not defined in the
|
||||||
# makefile but the arguement can be passed to make if needed.
|
# makefile but the argument can be passed to make if needed.
|
||||||
#
|
#
|
||||||
|
|
||||||
MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
|
MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
|
||||||
export MODLIB
|
export MODLIB
|
||||||
|
|
||||||
|
#
|
||||||
|
# INSTALL_MOD_STRIP, if defined, will cause modules to be
|
||||||
|
# stripped after they are installed. If INSTALL_MOD_STRIP is '1', then
|
||||||
|
# the default option --strip-debug will be used. Otherwise,
|
||||||
|
# INSTALL_MOD_STRIP will used as the options to the strip command.
|
||||||
|
|
||||||
|
ifdef INSTALL_MOD_STRIP
|
||||||
|
ifeq ($(INSTALL_MOD_STRIP),1)
|
||||||
|
mod_strip_cmd = $STRIP) --strip-debug
|
||||||
|
else
|
||||||
|
mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
|
||||||
|
endif # INSTALL_MOD_STRIP=1
|
||||||
|
else
|
||||||
|
mod_strip_cmd = true
|
||||||
|
endif # INSTALL_MOD_STRIP
|
||||||
|
export mod_strip_cmd
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(KBUILD_EXTMOD),)
|
ifeq ($(KBUILD_EXTMOD),)
|
||||||
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
|
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
|
||||||
@@ -539,7 +556,7 @@ libs-y := $(libs-y1) $(libs-y2)
|
|||||||
|
|
||||||
# Build vmlinux
|
# Build vmlinux
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# vmlinux is build from the objects selected by $(vmlinux-init) and
|
# vmlinux is built from the objects selected by $(vmlinux-init) and
|
||||||
# $(vmlinux-main). Most are built-in.o files from top-level directories
|
# $(vmlinux-main). Most are built-in.o files from top-level directories
|
||||||
# in the kernel tree, others are specified in arch/$(ARCH)Makefile.
|
# in the kernel tree, others are specified in arch/$(ARCH)Makefile.
|
||||||
# Ordering when linking is important, and $(vmlinux-init) must be first.
|
# Ordering when linking is important, and $(vmlinux-init) must be first.
|
||||||
@@ -590,7 +607,7 @@ quiet_cmd_vmlinux_version = GEN .version
|
|||||||
$(MAKE) $(build)=init
|
$(MAKE) $(build)=init
|
||||||
|
|
||||||
# Generate System.map
|
# Generate System.map
|
||||||
quiet_cmd_sysmap = SYSMAP
|
quiet_cmd_sysmap = SYSMAP
|
||||||
cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
|
cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
|
||||||
|
|
||||||
# Link of vmlinux
|
# Link of vmlinux
|
||||||
@@ -719,7 +736,7 @@ $(vmlinux-dirs): prepare scripts
|
|||||||
$(Q)$(MAKE) $(build)=$@
|
$(Q)$(MAKE) $(build)=$@
|
||||||
|
|
||||||
# Build the kernel release string
|
# Build the kernel release string
|
||||||
# The KERNELRELEASE is stored in a file named .kernelrelease
|
# The KERNELRELEASE is stored in a file named include/config/kernel.release
|
||||||
# to be used when executing for example make install or make modules_install
|
# to be used when executing for example make install or make modules_install
|
||||||
#
|
#
|
||||||
# Take the contents of any files called localversion* and the config
|
# Take the contents of any files called localversion* and the config
|
||||||
@@ -737,10 +754,10 @@ _localver = $(foreach f, $(__localver), $(if $(findstring ~, $(f)),,$(f)))
|
|||||||
localver = $(subst $(space),, \
|
localver = $(subst $(space),, \
|
||||||
$(shell cat /dev/null $(_localver)) \
|
$(shell cat /dev/null $(_localver)) \
|
||||||
$(patsubst "%",%,$(CONFIG_LOCALVERSION)))
|
$(patsubst "%",%,$(CONFIG_LOCALVERSION)))
|
||||||
|
|
||||||
# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
|
# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
|
||||||
# and if the SCM is know a tag from the SCM is appended.
|
# and if the SCM is know a tag from the SCM is appended.
|
||||||
# The appended tag is determinded by the SCM used.
|
# The appended tag is determined by the SCM used.
|
||||||
#
|
#
|
||||||
# Currently, only git is supported.
|
# Currently, only git is supported.
|
||||||
# Other SCMs can edit scripts/setlocalversion and add the appropriate
|
# Other SCMs can edit scripts/setlocalversion and add the appropriate
|
||||||
@@ -753,9 +770,9 @@ endif
|
|||||||
|
|
||||||
localver-full = $(localver)$(localver-auto)
|
localver-full = $(localver)$(localver-auto)
|
||||||
|
|
||||||
# Store (new) KERNELRELASE string in .kernelrelease
|
# Store (new) KERNELRELASE string in include/config/kernel.release
|
||||||
kernelrelease = $(KERNELVERSION)$(localver-full)
|
kernelrelease = $(KERNELVERSION)$(localver-full)
|
||||||
.kernelrelease: FORCE
|
include/config/kernel.release: include/config/auto.conf FORCE
|
||||||
$(Q)rm -f $@
|
$(Q)rm -f $@
|
||||||
$(Q)echo $(kernelrelease) > $@
|
$(Q)echo $(kernelrelease) > $@
|
||||||
|
|
||||||
@@ -776,10 +793,10 @@ PHONY += prepare-all
|
|||||||
# and if so do:
|
# and if so do:
|
||||||
# 1) Check that make has not been executed in the kernel src $(srctree)
|
# 1) Check that make has not been executed in the kernel src $(srctree)
|
||||||
# 2) Create the include2 directory, used for the second asm symlink
|
# 2) Create the include2 directory, used for the second asm symlink
|
||||||
prepare3: .kernelrelease
|
prepare3: include/config/kernel.release
|
||||||
ifneq ($(KBUILD_SRC),)
|
ifneq ($(KBUILD_SRC),)
|
||||||
@echo ' Using $(srctree) as source for kernel'
|
@echo ' Using $(srctree) as source for kernel'
|
||||||
$(Q)if [ -f $(srctree)/.config ]; then \
|
$(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
|
||||||
echo " $(srctree) is not clean, please run 'make mrproper'";\
|
echo " $(srctree) is not clean, please run 'make mrproper'";\
|
||||||
echo " in the '$(srctree)' directory.";\
|
echo " in the '$(srctree)' directory.";\
|
||||||
/bin/false; \
|
/bin/false; \
|
||||||
@@ -792,7 +809,7 @@ endif
|
|||||||
prepare2: prepare3 outputmakefile
|
prepare2: prepare3 outputmakefile
|
||||||
|
|
||||||
prepare1: prepare2 include/linux/version.h include/asm \
|
prepare1: prepare2 include/linux/version.h include/asm \
|
||||||
include/config/MARKER
|
include/config/auto.conf
|
||||||
ifneq ($(KBUILD_MODULES),)
|
ifneq ($(KBUILD_MODULES),)
|
||||||
$(Q)mkdir -p $(MODVERDIR)
|
$(Q)mkdir -p $(MODVERDIR)
|
||||||
$(Q)rm -f $(MODVERDIR)/*
|
$(Q)rm -f $(MODVERDIR)/*
|
||||||
@@ -806,27 +823,20 @@ prepare0: archprepare FORCE
|
|||||||
# All the preparing..
|
# All the preparing..
|
||||||
prepare prepare-all: prepare0
|
prepare prepare-all: prepare0
|
||||||
|
|
||||||
# Leave this as default for preprocessing vmlinux.lds.S, which is now
|
# Leave this as default for preprocessing vmlinux.lds.S, which is now
|
||||||
# done in arch/$(ARCH)/kernel/Makefile
|
# done in arch/$(ARCH)/kernel/Makefile
|
||||||
|
|
||||||
export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
|
export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
|
||||||
|
|
||||||
# FIXME: The asm symlink changes when $(ARCH) changes. That's
|
# FIXME: The asm symlink changes when $(ARCH) changes. That's
|
||||||
# hard to detect, but I suppose "make mrproper" is a good idea
|
# hard to detect, but I suppose "make mrproper" is a good idea
|
||||||
# before switching between archs anyway.
|
# before switching between archs anyway.
|
||||||
|
|
||||||
include/asm:
|
include/asm:
|
||||||
@echo ' SYMLINK $@ -> include/asm-$(ARCH)'
|
@echo ' SYMLINK $@ -> include/asm-$(ARCH)'
|
||||||
$(Q)if [ ! -d include ]; then mkdir -p include; fi;
|
$(Q)if [ ! -d include ]; then mkdir -p include; fi;
|
||||||
@ln -fsn asm-$(ARCH) $@
|
@ln -fsn asm-$(ARCH) $@
|
||||||
|
|
||||||
# Split autoconf.h into include/linux/config/*
|
|
||||||
|
|
||||||
include/config/MARKER: scripts/basic/split-include include/linux/autoconf.h
|
|
||||||
@echo ' SPLIT include/linux/autoconf.h -> include/config/*'
|
|
||||||
@scripts/basic/split-include include/linux/autoconf.h include/config
|
|
||||||
@touch $@
|
|
||||||
|
|
||||||
# Generate some files
|
# Generate some files
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -846,7 +856,7 @@ define filechk_version.h
|
|||||||
)
|
)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
include/linux/version.h: $(srctree)/Makefile .config .kernelrelease FORCE
|
include/linux/version.h: $(srctree)/Makefile include/config/kernel.release FORCE
|
||||||
$(call filechk,version.h)
|
$(call filechk,version.h)
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -860,7 +870,7 @@ depend dep:
|
|||||||
|
|
||||||
ifdef CONFIG_MODULES
|
ifdef CONFIG_MODULES
|
||||||
|
|
||||||
# By default, build modules as well
|
# By default, build modules as well
|
||||||
|
|
||||||
all: modules
|
all: modules
|
||||||
|
|
||||||
@@ -942,7 +952,7 @@ CLEAN_FILES += vmlinux System.map \
|
|||||||
MRPROPER_DIRS += include/config include2
|
MRPROPER_DIRS += include/config include2
|
||||||
MRPROPER_FILES += .config .config.old include/asm .version .old_version \
|
MRPROPER_FILES += .config .config.old include/asm .version .old_version \
|
||||||
include/linux/autoconf.h include/linux/version.h \
|
include/linux/autoconf.h include/linux/version.h \
|
||||||
.kernelrelease Module.symvers tags TAGS cscope*
|
Module.symvers tags TAGS cscope*
|
||||||
|
|
||||||
# clean - Delete most, but leave enough to build external modules
|
# clean - Delete most, but leave enough to build external modules
|
||||||
#
|
#
|
||||||
@@ -958,8 +968,9 @@ clean: archclean $(clean-dirs)
|
|||||||
$(call cmd,rmdirs)
|
$(call cmd,rmdirs)
|
||||||
$(call cmd,rmfiles)
|
$(call cmd,rmfiles)
|
||||||
@find . $(RCS_FIND_IGNORE) \
|
@find . $(RCS_FIND_IGNORE) \
|
||||||
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
|
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
|
||||||
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
|
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
|
||||||
|
-o -name '*.symtypes' \) \
|
||||||
-type f -print | xargs rm -f
|
-type f -print | xargs rm -f
|
||||||
|
|
||||||
# mrproper - Delete all generated files, including .config
|
# mrproper - Delete all generated files, including .config
|
||||||
@@ -982,9 +993,9 @@ PHONY += distclean
|
|||||||
|
|
||||||
distclean: mrproper
|
distclean: mrproper
|
||||||
@find $(srctree) $(RCS_FIND_IGNORE) \
|
@find $(srctree) $(RCS_FIND_IGNORE) \
|
||||||
\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
|
\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
|
||||||
-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
|
-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
|
||||||
-o -name '.*.rej' -o -size 0 \
|
-o -name '.*.rej' -o -size 0 \
|
||||||
-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
|
-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
|
||||||
-type f -print | xargs rm -f
|
-type f -print | xargs rm -f
|
||||||
|
|
||||||
@@ -994,9 +1005,9 @@ distclean: mrproper
|
|||||||
# rpm target kept for backward compatibility
|
# rpm target kept for backward compatibility
|
||||||
package-dir := $(srctree)/scripts/package
|
package-dir := $(srctree)/scripts/package
|
||||||
|
|
||||||
%pkg: FORCE
|
%pkg: include/config/kernel.release FORCE
|
||||||
$(Q)$(MAKE) $(build)=$(package-dir) $@
|
$(Q)$(MAKE) $(build)=$(package-dir) $@
|
||||||
rpm: FORCE
|
rpm: include/config/kernel.release FORCE
|
||||||
$(Q)$(MAKE) $(build)=$(package-dir) $@
|
$(Q)$(MAKE) $(build)=$(package-dir) $@
|
||||||
|
|
||||||
|
|
||||||
@@ -1077,7 +1088,7 @@ else # KBUILD_EXTMOD
|
|||||||
# make M=dir modules Make all modules in specified dir
|
# make M=dir modules Make all modules in specified dir
|
||||||
# make M=dir Same as 'make M=dir modules'
|
# make M=dir Same as 'make M=dir modules'
|
||||||
# make M=dir modules_install
|
# make M=dir modules_install
|
||||||
# Install the modules build in the module directory
|
# Install the modules built in the module directory
|
||||||
# Assumes install directory is already created
|
# Assumes install directory is already created
|
||||||
|
|
||||||
# We are always building modules
|
# We are always building modules
|
||||||
@@ -1136,7 +1147,7 @@ clean: rm-dirs := $(MODVERDIR)
|
|||||||
clean: $(clean-dirs)
|
clean: $(clean-dirs)
|
||||||
$(call cmd,rmdirs)
|
$(call cmd,rmdirs)
|
||||||
@find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \
|
@find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \
|
||||||
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
|
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
|
||||||
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
|
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
|
||||||
-type f -print | xargs rm -f
|
-type f -print | xargs rm -f
|
||||||
|
|
||||||
@@ -1175,31 +1186,41 @@ else
|
|||||||
ALLINCLUDE_ARCHS := $(ARCH)
|
ALLINCLUDE_ARCHS := $(ARCH)
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behaviour.
|
#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behavour.
|
||||||
ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS)
|
ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ALLSOURCE_ARCHS := $(ARCH)
|
ALLSOURCE_ARCHS := $(ARCH)
|
||||||
|
|
||||||
define all-sources
|
define find-sources
|
||||||
( find $(__srctree) $(RCS_FIND_IGNORE) \
|
( find $(__srctree) $(RCS_FIND_IGNORE) \
|
||||||
\( -name include -o -name arch \) -prune -o \
|
\( -name include -o -name arch \) -prune -o \
|
||||||
-name '*.[chS]' -print; \
|
-name $1 -print; \
|
||||||
for ARCH in $(ALLSOURCE_ARCHS) ; do \
|
for ARCH in $(ALLSOURCE_ARCHS) ; do \
|
||||||
find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
|
find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
|
||||||
-name '*.[chS]' -print; \
|
-name $1 -print; \
|
||||||
done ; \
|
done ; \
|
||||||
find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
|
find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
|
||||||
-name '*.[chS]' -print; \
|
-name $1 -print; \
|
||||||
find $(__srctree)include $(RCS_FIND_IGNORE) \
|
find $(__srctree)include $(RCS_FIND_IGNORE) \
|
||||||
\( -name config -o -name 'asm-*' \) -prune \
|
\( -name config -o -name 'asm-*' \) -prune \
|
||||||
-o -name '*.[chS]' -print; \
|
-o -name $1 -print; \
|
||||||
for ARCH in $(ALLINCLUDE_ARCHS) ; do \
|
for ARCH in $(ALLINCLUDE_ARCHS) ; do \
|
||||||
find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
|
find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
|
||||||
-name '*.[chS]' -print; \
|
-name $1 -print; \
|
||||||
done ; \
|
done ; \
|
||||||
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
|
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
|
||||||
-name '*.[chS]' -print )
|
-name $1 -print )
|
||||||
|
endef
|
||||||
|
|
||||||
|
define all-sources
|
||||||
|
$(call find-sources,'*.[chS]')
|
||||||
|
endef
|
||||||
|
define all-kconfigs
|
||||||
|
$(call find-sources,'Kconfig*')
|
||||||
|
endef
|
||||||
|
define all-defconfigs
|
||||||
|
$(call find-sources,'defconfig')
|
||||||
endef
|
endef
|
||||||
|
|
||||||
quiet_cmd_cscope-file = FILELST cscope.files
|
quiet_cmd_cscope-file = FILELST cscope.files
|
||||||
@@ -1219,7 +1240,13 @@ define cmd_TAGS
|
|||||||
echo "-I __initdata,__exitdata,__acquires,__releases \
|
echo "-I __initdata,__exitdata,__acquires,__releases \
|
||||||
-I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
|
-I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
|
||||||
--extra=+f --c-kinds=+px"`; \
|
--extra=+f --c-kinds=+px"`; \
|
||||||
$(all-sources) | xargs etags $$ETAGSF -a
|
$(all-sources) | xargs etags $$ETAGSF -a; \
|
||||||
|
if test "x$$ETAGSF" = x; then \
|
||||||
|
$(all-kconfigs) | xargs etags -a \
|
||||||
|
--regex='/^config[ \t]+\([a-zA-Z0-9_]+\)/\1/'; \
|
||||||
|
$(all-defconfigs) | xargs etags -a \
|
||||||
|
--regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \
|
||||||
|
fi
|
||||||
endef
|
endef
|
||||||
|
|
||||||
TAGS: FORCE
|
TAGS: FORCE
|
||||||
@@ -1259,14 +1286,14 @@ namespacecheck:
|
|||||||
endif #ifeq ($(config-targets),1)
|
endif #ifeq ($(config-targets),1)
|
||||||
endif #ifeq ($(mixed-targets),1)
|
endif #ifeq ($(mixed-targets),1)
|
||||||
|
|
||||||
PHONY += checkstack
|
PHONY += checkstack kernelrelease kernelversion
|
||||||
checkstack:
|
checkstack:
|
||||||
$(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
|
$(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
|
||||||
$(PERL) $(src)/scripts/checkstack.pl $(ARCH)
|
$(PERL) $(src)/scripts/checkstack.pl $(ARCH)
|
||||||
|
|
||||||
kernelrelease:
|
kernelrelease:
|
||||||
$(if $(wildcard .kernelrelease), $(Q)echo $(KERNELRELEASE), \
|
$(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
|
||||||
$(error kernelrelease not valid - run 'make *config' to update it))
|
$(error kernelrelease not valid - run 'make prepare' to update it))
|
||||||
kernelversion:
|
kernelversion:
|
||||||
@echo $(KERNELVERSION)
|
@echo $(KERNELVERSION)
|
||||||
|
|
||||||
@@ -1301,6 +1328,8 @@ endif
|
|||||||
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
|
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
|
||||||
%.o: %.S prepare scripts FORCE
|
%.o: %.S prepare scripts FORCE
|
||||||
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
|
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
|
||||||
|
%.symtypes: %.c prepare scripts FORCE
|
||||||
|
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
|
||||||
|
|
||||||
# Modules
|
# Modules
|
||||||
/ %/: prepare scripts FORCE
|
/ %/: prepare scripts FORCE
|
||||||
|
@@ -481,7 +481,7 @@ register_cpus(void)
|
|||||||
struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
|
struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
|
||||||
if (!p)
|
if (!p)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
register_cpu(p, i, NULL);
|
register_cpu(p, i);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -112,7 +112,7 @@ op_axp_create_files(struct super_block * sb, struct dentry * root)
|
|||||||
|
|
||||||
for (i = 0; i < model->num_counters; ++i) {
|
for (i = 0; i < model->num_counters; ++i) {
|
||||||
struct dentry *dir;
|
struct dentry *dir;
|
||||||
char buf[3];
|
char buf[4];
|
||||||
|
|
||||||
snprintf(buf, sizeof buf, "%d", i);
|
snprintf(buf, sizeof buf, "%d", i);
|
||||||
dir = oprofilefs_mkdir(sb, root, buf);
|
dir = oprofilefs_mkdir(sb, root, buf);
|
||||||
|
@@ -253,7 +253,7 @@ config ARCH_SA1100
|
|||||||
Support for StrongARM 11x0 based boards.
|
Support for StrongARM 11x0 based boards.
|
||||||
|
|
||||||
config ARCH_S3C2410
|
config ARCH_S3C2410
|
||||||
bool "Samsung S3C2410"
|
bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442"
|
||||||
help
|
help
|
||||||
Samsung S3C2410X CPU based systems, such as the Simtec Electronics
|
Samsung S3C2410X CPU based systems, such as the Simtec Electronics
|
||||||
BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
|
BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
|
||||||
@@ -372,7 +372,7 @@ config ISA_DMA_API
|
|||||||
bool
|
bool
|
||||||
|
|
||||||
config PCI
|
config PCI
|
||||||
bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB
|
bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX
|
||||||
help
|
help
|
||||||
Find out whether you have a PCI motherboard. PCI is the name of a
|
Find out whether you have a PCI motherboard. PCI is the name of a
|
||||||
bus system, i.e. the way the CPU talks to the other stuff inside
|
bus system, i.e. the way the CPU talks to the other stuff inside
|
||||||
|
@@ -177,7 +177,7 @@ boot := arch/arm/boot
|
|||||||
# them changed. We use .arch to indicate when they were updated
|
# them changed. We use .arch to indicate when they were updated
|
||||||
# last, otherwise make uses the target directory mtime.
|
# last, otherwise make uses the target directory mtime.
|
||||||
|
|
||||||
include/asm-arm/.arch: $(wildcard include/config/arch/*.h) include/config/MARKER
|
include/asm-arm/.arch: $(wildcard include/config/arch/*.h) include/config/auto.conf
|
||||||
@echo ' SYMLINK include/asm-arm/arch -> include/asm-arm/$(INCDIR)'
|
@echo ' SYMLINK include/asm-arm/arch -> include/asm-arm/$(INCDIR)'
|
||||||
ifneq ($(KBUILD_SRC),)
|
ifneq ($(KBUILD_SRC),)
|
||||||
$(Q)mkdir -p include/asm-arm
|
$(Q)mkdir -p include/asm-arm
|
||||||
|
@@ -61,6 +61,12 @@
|
|||||||
cmp r7, r3
|
cmp r7, r3
|
||||||
beq 99f
|
beq 99f
|
||||||
|
|
||||||
|
@ Ajeco 1ARM : 1075
|
||||||
|
mov r3, #(MACH_TYPE_ONEARM & 0xff)
|
||||||
|
orr r3, r3, #(MACH_TYPE_ONEARM & 0xff00)
|
||||||
|
cmp r7, r3
|
||||||
|
beq 99f
|
||||||
|
|
||||||
@ Unknown board, use the AT91RM9200DK board
|
@ Unknown board, use the AT91RM9200DK board
|
||||||
@ mov r7, #MACH_TYPE_AT91RM9200
|
@ mov r7, #MACH_TYPE_AT91RM9200
|
||||||
mov r7, #(MACH_TYPE_AT91RM9200DK & 0xff)
|
mov r7, #(MACH_TYPE_AT91RM9200DK & 0xff)
|
||||||
|
@@ -77,7 +77,7 @@ Lrow4bpplp:
|
|||||||
subne r1, r1, #1
|
subne r1, r1, #1
|
||||||
ldrneb r7, [r6, r1]
|
ldrneb r7, [r6, r1]
|
||||||
bne Lrow4bpplp
|
bne Lrow4bpplp
|
||||||
LOADREGS(fd, sp!, {r4 - r7, pc})
|
ldmfd sp!, {r4 - r7, pc}
|
||||||
|
|
||||||
@
|
@
|
||||||
@ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc)
|
@ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc)
|
||||||
@@ -105,7 +105,7 @@ Lrow8bpplp:
|
|||||||
subne r1, r1, #1
|
subne r1, r1, #1
|
||||||
ldrneb r7, [r6, r1]
|
ldrneb r7, [r6, r1]
|
||||||
bne Lrow8bpplp
|
bne Lrow8bpplp
|
||||||
LOADREGS(fd, sp!, {r4 - r7, pc})
|
ldmfd sp!, {r4 - r7, pc}
|
||||||
|
|
||||||
@
|
@
|
||||||
@ Smashable regs: {r0 - r3}, [r4], {r5, r6}, [r7], (r8 - fp), [ip], (sp), [lr], (pc)
|
@ Smashable regs: {r0 - r3}, [r4], {r5, r6}, [r7], (r8 - fp), [ip], (sp), [lr], (pc)
|
||||||
@@ -127,7 +127,7 @@ Lrow1bpp:
|
|||||||
strb r7, [r0], r5
|
strb r7, [r0], r5
|
||||||
mov r7, r7, lsr #8
|
mov r7, r7, lsr #8
|
||||||
strb r7, [r0], r5
|
strb r7, [r0], r5
|
||||||
LOADREGS(fd, sp!, {r4 - r7, pc})
|
ldmfd sp!, {r4 - r7, pc}
|
||||||
|
|
||||||
.bss
|
.bss
|
||||||
ENTRY(con_charconvtable)
|
ENTRY(con_charconvtable)
|
||||||
|
@@ -629,21 +629,6 @@ static int locomo_resume(struct platform_device *dev)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define LCM_ALC_EN 0x8000
|
|
||||||
|
|
||||||
void frontlight_set(struct locomo *lchip, int duty, int vr, int bpwf)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&lchip->lock, flags);
|
|
||||||
locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
|
|
||||||
udelay(100);
|
|
||||||
locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
|
|
||||||
locomo_writel(bpwf | LCM_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
|
|
||||||
spin_unlock_irqrestore(&lchip->lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* locomo_probe - probe for a single LoCoMo chip.
|
* locomo_probe - probe for a single LoCoMo chip.
|
||||||
* @phys_addr: physical address of device.
|
* @phys_addr: physical address of device.
|
||||||
@@ -698,14 +683,10 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
|
|||||||
, lchip->base + LOCOMO_GPD);
|
, lchip->base + LOCOMO_GPD);
|
||||||
locomo_writel(0, lchip->base + LOCOMO_GIE);
|
locomo_writel(0, lchip->base + LOCOMO_GIE);
|
||||||
|
|
||||||
/* FrontLight */
|
/* Frontlight */
|
||||||
locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
|
locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
|
||||||
locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
|
locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
|
||||||
|
|
||||||
/* Same constants can be used for collie and poodle
|
|
||||||
(depending on CONFIG options in original sharp code)? */
|
|
||||||
frontlight_set(lchip, 163, 0, 148);
|
|
||||||
|
|
||||||
/* Longtime timer */
|
/* Longtime timer */
|
||||||
locomo_writel(0, lchip->base + LOCOMO_LTINT);
|
locomo_writel(0, lchip->base + LOCOMO_LTINT);
|
||||||
/* SPI */
|
/* SPI */
|
||||||
@@ -1062,6 +1043,30 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int
|
|||||||
spin_unlock_irqrestore(&lchip->lock, flags);
|
spin_unlock_irqrestore(&lchip->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Frontlight control
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct locomo *locomo_chip_driver(struct locomo_dev *ldev);
|
||||||
|
|
||||||
|
void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
struct locomo *lchip = locomo_chip_driver(dev);
|
||||||
|
|
||||||
|
if (vr)
|
||||||
|
locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 1);
|
||||||
|
else
|
||||||
|
locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 0);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&lchip->lock, flags);
|
||||||
|
locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
|
||||||
|
udelay(100);
|
||||||
|
locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
|
||||||
|
locomo_writel(bpwf | LOCOMO_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
|
||||||
|
spin_unlock_irqrestore(&lchip->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LoCoMo "Register Access Bus."
|
* LoCoMo "Register Access Bus."
|
||||||
*
|
*
|
||||||
|
1053
arch/arm/configs/onearm_defconfig
Normal file
1053
arch/arm/configs/onearm_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated make config: don't edit
|
# Automatically generated make config: don't edit
|
||||||
# Linux kernel version: 2.6.17
|
# Linux kernel version: 2.6.17-git9
|
||||||
# Tue Jun 20 18:57:01 2006
|
# Sun Jun 25 23:56:32 2006
|
||||||
#
|
#
|
||||||
CONFIG_ARM=y
|
CONFIG_ARM=y
|
||||||
CONFIG_MMU=y
|
CONFIG_MMU=y
|
||||||
@@ -49,7 +49,6 @@ CONFIG_SLAB=y
|
|||||||
# CONFIG_TINY_SHMEM is not set
|
# CONFIG_TINY_SHMEM is not set
|
||||||
CONFIG_BASE_SMALL=0
|
CONFIG_BASE_SMALL=0
|
||||||
# CONFIG_SLOB is not set
|
# CONFIG_SLOB is not set
|
||||||
CONFIG_OBSOLETE_INTERMODULE=y
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Loadable module support
|
# Loadable module support
|
||||||
@@ -81,18 +80,26 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
|
|||||||
#
|
#
|
||||||
# System Type
|
# System Type
|
||||||
#
|
#
|
||||||
|
# CONFIG_ARCH_AAEC2000 is not set
|
||||||
|
# CONFIG_ARCH_INTEGRATOR is not set
|
||||||
|
# CONFIG_ARCH_REALVIEW is not set
|
||||||
|
# CONFIG_ARCH_VERSATILE is not set
|
||||||
|
# CONFIG_ARCH_AT91RM9200 is not set
|
||||||
# CONFIG_ARCH_CLPS7500 is not set
|
# CONFIG_ARCH_CLPS7500 is not set
|
||||||
# CONFIG_ARCH_CLPS711X is not set
|
# CONFIG_ARCH_CLPS711X is not set
|
||||||
# CONFIG_ARCH_CO285 is not set
|
# CONFIG_ARCH_CO285 is not set
|
||||||
# CONFIG_ARCH_EBSA110 is not set
|
# CONFIG_ARCH_EBSA110 is not set
|
||||||
# CONFIG_ARCH_EP93XX is not set
|
# CONFIG_ARCH_EP93XX is not set
|
||||||
# CONFIG_ARCH_FOOTBRIDGE is not set
|
# CONFIG_ARCH_FOOTBRIDGE is not set
|
||||||
# CONFIG_ARCH_INTEGRATOR is not set
|
# CONFIG_ARCH_NETX is not set
|
||||||
|
# CONFIG_ARCH_H720X is not set
|
||||||
|
# CONFIG_ARCH_IMX is not set
|
||||||
# CONFIG_ARCH_IOP3XX is not set
|
# CONFIG_ARCH_IOP3XX is not set
|
||||||
# CONFIG_ARCH_IXP4XX is not set
|
# CONFIG_ARCH_IXP4XX is not set
|
||||||
# CONFIG_ARCH_IXP2000 is not set
|
# CONFIG_ARCH_IXP2000 is not set
|
||||||
# CONFIG_ARCH_IXP23XX is not set
|
# CONFIG_ARCH_IXP23XX is not set
|
||||||
# CONFIG_ARCH_L7200 is not set
|
# CONFIG_ARCH_L7200 is not set
|
||||||
|
# CONFIG_ARCH_PNX4008 is not set
|
||||||
# CONFIG_ARCH_PXA is not set
|
# CONFIG_ARCH_PXA is not set
|
||||||
# CONFIG_ARCH_RPC is not set
|
# CONFIG_ARCH_RPC is not set
|
||||||
# CONFIG_ARCH_SA1100 is not set
|
# CONFIG_ARCH_SA1100 is not set
|
||||||
@@ -100,14 +107,6 @@ CONFIG_ARCH_S3C2410=y
|
|||||||
# CONFIG_ARCH_SHARK is not set
|
# CONFIG_ARCH_SHARK is not set
|
||||||
# CONFIG_ARCH_LH7A40X is not set
|
# CONFIG_ARCH_LH7A40X is not set
|
||||||
# CONFIG_ARCH_OMAP is not set
|
# CONFIG_ARCH_OMAP is not set
|
||||||
# CONFIG_ARCH_VERSATILE is not set
|
|
||||||
# CONFIG_ARCH_REALVIEW is not set
|
|
||||||
# CONFIG_ARCH_IMX is not set
|
|
||||||
# CONFIG_ARCH_H720X is not set
|
|
||||||
# CONFIG_ARCH_AAEC2000 is not set
|
|
||||||
# CONFIG_ARCH_AT91RM9200 is not set
|
|
||||||
# CONFIG_ARCH_PNX4008 is not set
|
|
||||||
# CONFIG_ARCH_NETX is not set
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# S3C24XX Implementations
|
# S3C24XX Implementations
|
||||||
@@ -123,11 +122,14 @@ CONFIG_ARCH_SMDK2410=y
|
|||||||
CONFIG_ARCH_S3C2440=y
|
CONFIG_ARCH_S3C2440=y
|
||||||
CONFIG_SMDK2440_CPU2440=y
|
CONFIG_SMDK2440_CPU2440=y
|
||||||
CONFIG_SMDK2440_CPU2442=y
|
CONFIG_SMDK2440_CPU2442=y
|
||||||
|
CONFIG_MACH_SMDK2413=y
|
||||||
CONFIG_MACH_VR1000=y
|
CONFIG_MACH_VR1000=y
|
||||||
CONFIG_MACH_RX3715=y
|
CONFIG_MACH_RX3715=y
|
||||||
CONFIG_MACH_OTOM=y
|
CONFIG_MACH_OTOM=y
|
||||||
CONFIG_MACH_NEXCODER_2440=y
|
CONFIG_MACH_NEXCODER_2440=y
|
||||||
|
CONFIG_S3C2410_CLOCK=y
|
||||||
CONFIG_CPU_S3C2410=y
|
CONFIG_CPU_S3C2410=y
|
||||||
|
CONFIG_CPU_S3C2412=y
|
||||||
CONFIG_CPU_S3C244X=y
|
CONFIG_CPU_S3C244X=y
|
||||||
CONFIG_CPU_S3C2440=y
|
CONFIG_CPU_S3C2440=y
|
||||||
CONFIG_CPU_S3C2442=y
|
CONFIG_CPU_S3C2442=y
|
||||||
@@ -153,8 +155,11 @@ CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
|
|||||||
#
|
#
|
||||||
CONFIG_CPU_32=y
|
CONFIG_CPU_32=y
|
||||||
CONFIG_CPU_ARM920T=y
|
CONFIG_CPU_ARM920T=y
|
||||||
|
CONFIG_CPU_ARM926T=y
|
||||||
CONFIG_CPU_32v4=y
|
CONFIG_CPU_32v4=y
|
||||||
|
CONFIG_CPU_32v5=y
|
||||||
CONFIG_CPU_ABRT_EV4T=y
|
CONFIG_CPU_ABRT_EV4T=y
|
||||||
|
CONFIG_CPU_ABRT_EV5TJ=y
|
||||||
CONFIG_CPU_CACHE_V4WT=y
|
CONFIG_CPU_CACHE_V4WT=y
|
||||||
CONFIG_CPU_CACHE_VIVT=y
|
CONFIG_CPU_CACHE_VIVT=y
|
||||||
CONFIG_CPU_COPY_V4WB=y
|
CONFIG_CPU_COPY_V4WB=y
|
||||||
@@ -167,6 +172,7 @@ CONFIG_CPU_TLB_V4WBI=y
|
|||||||
# CONFIG_CPU_ICACHE_DISABLE is not set
|
# CONFIG_CPU_ICACHE_DISABLE is not set
|
||||||
# CONFIG_CPU_DCACHE_DISABLE is not set
|
# CONFIG_CPU_DCACHE_DISABLE is not set
|
||||||
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
|
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
|
||||||
|
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bus support
|
# Bus support
|
||||||
@@ -214,6 +220,7 @@ CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
|
|||||||
CONFIG_FPE_NWFPE=y
|
CONFIG_FPE_NWFPE=y
|
||||||
# CONFIG_FPE_NWFPE_XP is not set
|
# CONFIG_FPE_NWFPE_XP is not set
|
||||||
# CONFIG_FPE_FASTFPE is not set
|
# CONFIG_FPE_FASTFPE is not set
|
||||||
|
# CONFIG_VFP is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# Userspace binary formats
|
# Userspace binary formats
|
||||||
@@ -242,6 +249,8 @@ CONFIG_NET=y
|
|||||||
# CONFIG_NETDEBUG is not set
|
# CONFIG_NETDEBUG is not set
|
||||||
# CONFIG_PACKET is not set
|
# CONFIG_PACKET is not set
|
||||||
CONFIG_UNIX=y
|
CONFIG_UNIX=y
|
||||||
|
CONFIG_XFRM=y
|
||||||
|
# CONFIG_XFRM_USER is not set
|
||||||
# CONFIG_NET_KEY is not set
|
# CONFIG_NET_KEY is not set
|
||||||
CONFIG_INET=y
|
CONFIG_INET=y
|
||||||
# CONFIG_IP_MULTICAST is not set
|
# CONFIG_IP_MULTICAST is not set
|
||||||
@@ -260,6 +269,8 @@ CONFIG_IP_PNP_BOOTP=y
|
|||||||
# CONFIG_INET_IPCOMP is not set
|
# CONFIG_INET_IPCOMP is not set
|
||||||
# CONFIG_INET_XFRM_TUNNEL is not set
|
# CONFIG_INET_XFRM_TUNNEL is not set
|
||||||
# CONFIG_INET_TUNNEL is not set
|
# CONFIG_INET_TUNNEL is not set
|
||||||
|
CONFIG_INET_XFRM_MODE_TRANSPORT=y
|
||||||
|
CONFIG_INET_XFRM_MODE_TUNNEL=y
|
||||||
CONFIG_INET_DIAG=y
|
CONFIG_INET_DIAG=y
|
||||||
CONFIG_INET_TCP_DIAG=y
|
CONFIG_INET_TCP_DIAG=y
|
||||||
# CONFIG_TCP_CONG_ADVANCED is not set
|
# CONFIG_TCP_CONG_ADVANCED is not set
|
||||||
@@ -267,6 +278,7 @@ CONFIG_TCP_CONG_BIC=y
|
|||||||
# CONFIG_IPV6 is not set
|
# CONFIG_IPV6 is not set
|
||||||
# CONFIG_INET6_XFRM_TUNNEL is not set
|
# CONFIG_INET6_XFRM_TUNNEL is not set
|
||||||
# CONFIG_INET6_TUNNEL is not set
|
# CONFIG_INET6_TUNNEL is not set
|
||||||
|
# CONFIG_NETWORK_SECMARK is not set
|
||||||
# CONFIG_NETFILTER is not set
|
# CONFIG_NETFILTER is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -321,6 +333,7 @@ CONFIG_STANDALONE=y
|
|||||||
CONFIG_PREVENT_FIRMWARE_BUILD=y
|
CONFIG_PREVENT_FIRMWARE_BUILD=y
|
||||||
# CONFIG_FW_LOADER is not set
|
# CONFIG_FW_LOADER is not set
|
||||||
# CONFIG_DEBUG_DRIVER is not set
|
# CONFIG_DEBUG_DRIVER is not set
|
||||||
|
# CONFIG_SYS_HYPERVISOR is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# Connector - unified userspace <-> kernelspace linker
|
# Connector - unified userspace <-> kernelspace linker
|
||||||
@@ -408,10 +421,12 @@ CONFIG_MTD_BAST_MAXSIZE=4
|
|||||||
#
|
#
|
||||||
CONFIG_MTD_NAND=y
|
CONFIG_MTD_NAND=y
|
||||||
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
|
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
|
||||||
|
# CONFIG_MTD_NAND_ECC_SMC is not set
|
||||||
CONFIG_MTD_NAND_IDS=y
|
CONFIG_MTD_NAND_IDS=y
|
||||||
CONFIG_MTD_NAND_S3C2410=y
|
CONFIG_MTD_NAND_S3C2410=y
|
||||||
# CONFIG_MTD_NAND_S3C2410_DEBUG is not set
|
# CONFIG_MTD_NAND_S3C2410_DEBUG is not set
|
||||||
# CONFIG_MTD_NAND_S3C2410_HWECC is not set
|
# CONFIG_MTD_NAND_S3C2410_HWECC is not set
|
||||||
|
# CONFIG_MTD_NAND_S3C2410_CLKSTOP is not set
|
||||||
# CONFIG_MTD_NAND_DISKONCHIP is not set
|
# CONFIG_MTD_NAND_DISKONCHIP is not set
|
||||||
# CONFIG_MTD_NAND_NANDSIM is not set
|
# CONFIG_MTD_NAND_NANDSIM is not set
|
||||||
|
|
||||||
@@ -425,8 +440,8 @@ CONFIG_MTD_NAND_S3C2410=y
|
|||||||
#
|
#
|
||||||
CONFIG_PARPORT=y
|
CONFIG_PARPORT=y
|
||||||
# CONFIG_PARPORT_PC is not set
|
# CONFIG_PARPORT_PC is not set
|
||||||
# CONFIG_PARPORT_ARC is not set
|
|
||||||
# CONFIG_PARPORT_GSC is not set
|
# CONFIG_PARPORT_GSC is not set
|
||||||
|
# CONFIG_PARPORT_AX88796 is not set
|
||||||
CONFIG_PARPORT_1284=y
|
CONFIG_PARPORT_1284=y
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -735,6 +750,7 @@ CONFIG_I2C_ALGOBIT=m
|
|||||||
#
|
#
|
||||||
# CONFIG_I2C_ELEKTOR is not set
|
# CONFIG_I2C_ELEKTOR is not set
|
||||||
CONFIG_I2C_ISA=m
|
CONFIG_I2C_ISA=m
|
||||||
|
# CONFIG_I2C_OCORES is not set
|
||||||
# CONFIG_I2C_PARPORT is not set
|
# CONFIG_I2C_PARPORT is not set
|
||||||
# CONFIG_I2C_PARPORT_LIGHT is not set
|
# CONFIG_I2C_PARPORT_LIGHT is not set
|
||||||
CONFIG_I2C_S3C2410=y
|
CONFIG_I2C_S3C2410=y
|
||||||
@@ -765,13 +781,13 @@ CONFIG_SENSORS_EEPROM=m
|
|||||||
#
|
#
|
||||||
# Dallas's 1-wire bus
|
# Dallas's 1-wire bus
|
||||||
#
|
#
|
||||||
# CONFIG_W1 is not set
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Hardware Monitoring support
|
# Hardware Monitoring support
|
||||||
#
|
#
|
||||||
CONFIG_HWMON=y
|
CONFIG_HWMON=y
|
||||||
CONFIG_HWMON_VID=m
|
CONFIG_HWMON_VID=m
|
||||||
|
# CONFIG_SENSORS_ABITUGURU is not set
|
||||||
# CONFIG_SENSORS_ADM1021 is not set
|
# CONFIG_SENSORS_ADM1021 is not set
|
||||||
# CONFIG_SENSORS_ADM1025 is not set
|
# CONFIG_SENSORS_ADM1025 is not set
|
||||||
# CONFIG_SENSORS_ADM1026 is not set
|
# CONFIG_SENSORS_ADM1026 is not set
|
||||||
@@ -799,8 +815,10 @@ CONFIG_SENSORS_LM85=m
|
|||||||
# CONFIG_SENSORS_MAX1619 is not set
|
# CONFIG_SENSORS_MAX1619 is not set
|
||||||
# CONFIG_SENSORS_PC87360 is not set
|
# CONFIG_SENSORS_PC87360 is not set
|
||||||
# CONFIG_SENSORS_SMSC47M1 is not set
|
# CONFIG_SENSORS_SMSC47M1 is not set
|
||||||
|
# CONFIG_SENSORS_SMSC47M192 is not set
|
||||||
# CONFIG_SENSORS_SMSC47B397 is not set
|
# CONFIG_SENSORS_SMSC47B397 is not set
|
||||||
# CONFIG_SENSORS_W83781D is not set
|
# CONFIG_SENSORS_W83781D is not set
|
||||||
|
# CONFIG_SENSORS_W83791D is not set
|
||||||
# CONFIG_SENSORS_W83792D is not set
|
# CONFIG_SENSORS_W83792D is not set
|
||||||
# CONFIG_SENSORS_W83L785TS is not set
|
# CONFIG_SENSORS_W83L785TS is not set
|
||||||
# CONFIG_SENSORS_W83627HF is not set
|
# CONFIG_SENSORS_W83627HF is not set
|
||||||
@@ -845,6 +863,7 @@ CONFIG_FB_CFB_COPYAREA=y
|
|||||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||||
# CONFIG_FB_MACMODES is not set
|
# CONFIG_FB_MACMODES is not set
|
||||||
CONFIG_FB_FIRMWARE_EDID=y
|
CONFIG_FB_FIRMWARE_EDID=y
|
||||||
|
# CONFIG_FB_BACKLIGHT is not set
|
||||||
CONFIG_FB_MODE_HELPERS=y
|
CONFIG_FB_MODE_HELPERS=y
|
||||||
# CONFIG_FB_TILEBLITTING is not set
|
# CONFIG_FB_TILEBLITTING is not set
|
||||||
# CONFIG_FB_S1D13XXX is not set
|
# CONFIG_FB_S1D13XXX is not set
|
||||||
@@ -976,10 +995,12 @@ CONFIG_USB_MON=y
|
|||||||
# CONFIG_USB_LEGOTOWER is not set
|
# CONFIG_USB_LEGOTOWER is not set
|
||||||
# CONFIG_USB_LCD is not set
|
# CONFIG_USB_LCD is not set
|
||||||
# CONFIG_USB_LED is not set
|
# CONFIG_USB_LED is not set
|
||||||
|
# CONFIG_USB_CY7C63 is not set
|
||||||
# CONFIG_USB_CYTHERM is not set
|
# CONFIG_USB_CYTHERM is not set
|
||||||
# CONFIG_USB_PHIDGETKIT is not set
|
# CONFIG_USB_PHIDGETKIT is not set
|
||||||
# CONFIG_USB_PHIDGETSERVO is not set
|
# CONFIG_USB_PHIDGETSERVO is not set
|
||||||
# CONFIG_USB_IDMOUSE is not set
|
# CONFIG_USB_IDMOUSE is not set
|
||||||
|
# CONFIG_USB_APPLEDISPLAY is not set
|
||||||
# CONFIG_USB_LD is not set
|
# CONFIG_USB_LD is not set
|
||||||
# CONFIG_USB_TEST is not set
|
# CONFIG_USB_TEST is not set
|
||||||
|
|
||||||
@@ -1024,6 +1045,7 @@ CONFIG_FS_MBCACHE=y
|
|||||||
# CONFIG_MINIX_FS is not set
|
# CONFIG_MINIX_FS is not set
|
||||||
CONFIG_ROMFS_FS=y
|
CONFIG_ROMFS_FS=y
|
||||||
CONFIG_INOTIFY=y
|
CONFIG_INOTIFY=y
|
||||||
|
CONFIG_INOTIFY_USER=y
|
||||||
# CONFIG_QUOTA is not set
|
# CONFIG_QUOTA is not set
|
||||||
CONFIG_DNOTIFY=y
|
CONFIG_DNOTIFY=y
|
||||||
# CONFIG_AUTOFS_FS is not set
|
# CONFIG_AUTOFS_FS is not set
|
||||||
|
@@ -340,7 +340,7 @@ sys_mmap2:
|
|||||||
streq r5, [sp, #4]
|
streq r5, [sp, #4]
|
||||||
beq do_mmap2
|
beq do_mmap2
|
||||||
mov r0, #-EINVAL
|
mov r0, #-EINVAL
|
||||||
RETINSTR(mov,pc, lr)
|
mov pc, lr
|
||||||
#else
|
#else
|
||||||
str r5, [sp, #4]
|
str r5, [sp, #4]
|
||||||
b do_mmap2
|
b do_mmap2
|
||||||
|
@@ -39,7 +39,7 @@
|
|||||||
__INIT
|
__INIT
|
||||||
.type stext, %function
|
.type stext, %function
|
||||||
ENTRY(stext)
|
ENTRY(stext)
|
||||||
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode
|
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
|
||||||
@ and irqs disabled
|
@ and irqs disabled
|
||||||
mrc p15, 0, r9, c0, c0 @ get processor id
|
mrc p15, 0, r9, c0, c0 @ get processor id
|
||||||
bl __lookup_processor_type @ r5=procinfo r9=cpuid
|
bl __lookup_processor_type @ r5=procinfo r9=cpuid
|
||||||
|
@@ -71,7 +71,7 @@
|
|||||||
__INIT
|
__INIT
|
||||||
.type stext, %function
|
.type stext, %function
|
||||||
ENTRY(stext)
|
ENTRY(stext)
|
||||||
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode
|
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
|
||||||
@ and irqs disabled
|
@ and irqs disabled
|
||||||
mrc p15, 0, r9, c0, c0 @ get processor id
|
mrc p15, 0, r9, c0, c0 @ get processor id
|
||||||
bl __lookup_processor_type @ r5=procinfo r9=cpuid
|
bl __lookup_processor_type @ r5=procinfo r9=cpuid
|
||||||
@@ -104,7 +104,7 @@ ENTRY(secondary_startup)
|
|||||||
* the processor type - there is no need to check the machine type
|
* the processor type - there is no need to check the machine type
|
||||||
* as it has already been validated by the primary processor.
|
* as it has already been validated by the primary processor.
|
||||||
*/
|
*/
|
||||||
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
|
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
|
||||||
mrc p15, 0, r9, c0, c0 @ get processor id
|
mrc p15, 0, r9, c0, c0 @ get processor id
|
||||||
bl __lookup_processor_type
|
bl __lookup_processor_type
|
||||||
movs r10, r5 @ invalid processor?
|
movs r10, r5 @ invalid processor?
|
||||||
|
@@ -808,7 +808,7 @@ static int __init topology_init(void)
|
|||||||
int cpu;
|
int cpu;
|
||||||
|
|
||||||
for_each_possible_cpu(cpu)
|
for_each_possible_cpu(cpu)
|
||||||
register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu, NULL);
|
register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -41,7 +41,7 @@ ENTRY(c_backtrace)
|
|||||||
movne r0, #0
|
movne r0, #0
|
||||||
movs frame, r0
|
movs frame, r0
|
||||||
1: moveq r0, #-2
|
1: moveq r0, #-2
|
||||||
LOADREGS(eqfd, sp!, {r4 - r8, pc})
|
ldmeqfd sp!, {r4 - r8, pc}
|
||||||
|
|
||||||
2: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction
|
2: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction
|
||||||
ldr r0, [sp], #4
|
ldr r0, [sp], #4
|
||||||
@@ -85,7 +85,7 @@ ENTRY(c_backtrace)
|
|||||||
* A zero next framepointer means we're done.
|
* A zero next framepointer means we're done.
|
||||||
*/
|
*/
|
||||||
teq next, #0
|
teq next, #0
|
||||||
LOADREGS(eqfd, sp!, {r4 - r8, pc})
|
ldmeqfd sp!, {r4 - r8, pc}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The next framepointer must be above the
|
* The next framepointer must be above the
|
||||||
@@ -104,7 +104,7 @@ ENTRY(c_backtrace)
|
|||||||
1007: ldr r0, =.Lbad
|
1007: ldr r0, =.Lbad
|
||||||
mov r1, frame
|
mov r1, frame
|
||||||
bl printk
|
bl printk
|
||||||
LOADREGS(fd, sp!, {r4 - r8, pc})
|
ldmfd sp!, {r4 - r8, pc}
|
||||||
.ltorg
|
.ltorg
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ ENTRY(c_backtrace)
|
|||||||
adrne r0, .Lcr
|
adrne r0, .Lcr
|
||||||
blne printk
|
blne printk
|
||||||
mov r0, stack
|
mov r0, stack
|
||||||
LOADREGS(fd, sp!, {instr, reg, stack, r7, r8, pc})
|
ldmfd sp!, {instr, reg, stack, r7, r8, pc}
|
||||||
|
|
||||||
.Lfp: .asciz " r%d = %08X%c"
|
.Lfp: .asciz " r%d = %08X%c"
|
||||||
.Lcr: .asciz "\n"
|
.Lcr: .asciz "\n"
|
||||||
|
@@ -43,10 +43,10 @@ USER( strnebt r2, [r0], #1)
|
|||||||
tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
|
tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
|
||||||
USER( strnebt r2, [r0], #1)
|
USER( strnebt r2, [r0], #1)
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
LOADREGS(fd,sp!, {r1, pc})
|
ldmfd sp!, {r1, pc}
|
||||||
|
|
||||||
.section .fixup,"ax"
|
.section .fixup,"ax"
|
||||||
.align 0
|
.align 0
|
||||||
9001: LOADREGS(fd,sp!, {r0, pc})
|
9001: ldmfd sp!, {r0, pc}
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
|
@@ -43,4 +43,4 @@ ENTRY(copy_page)
|
|||||||
bgt 1b @ 1
|
bgt 1b @ 1
|
||||||
PLD( ldmeqia r1!, {r3, r4, ip, lr} )
|
PLD( ldmeqia r1!, {r3, r4, ip, lr} )
|
||||||
PLD( beq 2b )
|
PLD( beq 2b )
|
||||||
LOADREGS(fd, sp!, {r4, pc}) @ 3
|
ldmfd sp!, {r4, pc} @ 3
|
||||||
|
@@ -28,5 +28,5 @@ ENTRY(__csum_ipv6_magic)
|
|||||||
adcs r0, r0, r3
|
adcs r0, r0, r3
|
||||||
adcs r0, r0, r2
|
adcs r0, r0, r2
|
||||||
adcs r0, r0, #0
|
adcs r0, r0, #0
|
||||||
LOADREGS(fd, sp!, {pc})
|
ldmfd sp!, {pc}
|
||||||
|
|
||||||
|
@@ -31,7 +31,7 @@ ENTRY(__const_udelay) @ 0 <= r0 <= 0x7fffff06
|
|||||||
mov r2, r2, lsr #10 @ max = 0x00007fff
|
mov r2, r2, lsr #10 @ max = 0x00007fff
|
||||||
mul r0, r2, r0 @ max = 2^32-1
|
mul r0, r2, r0 @ max = 2^32-1
|
||||||
movs r0, r0, lsr #6
|
movs r0, r0, lsr #6
|
||||||
RETINSTR(moveq,pc,lr)
|
moveq pc, lr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* loops = r0 * HZ * loops_per_jiffy / 1000000
|
* loops = r0 * HZ * loops_per_jiffy / 1000000
|
||||||
@@ -43,20 +43,20 @@ ENTRY(__const_udelay) @ 0 <= r0 <= 0x7fffff06
|
|||||||
ENTRY(__delay)
|
ENTRY(__delay)
|
||||||
subs r0, r0, #1
|
subs r0, r0, #1
|
||||||
#if 0
|
#if 0
|
||||||
RETINSTR(movls,pc,lr)
|
movls pc, lr
|
||||||
subs r0, r0, #1
|
subs r0, r0, #1
|
||||||
RETINSTR(movls,pc,lr)
|
movls pc, lr
|
||||||
subs r0, r0, #1
|
subs r0, r0, #1
|
||||||
RETINSTR(movls,pc,lr)
|
movls pc, lr
|
||||||
subs r0, r0, #1
|
subs r0, r0, #1
|
||||||
RETINSTR(movls,pc,lr)
|
movls pc, lr
|
||||||
subs r0, r0, #1
|
subs r0, r0, #1
|
||||||
RETINSTR(movls,pc,lr)
|
movls pc, lr
|
||||||
subs r0, r0, #1
|
subs r0, r0, #1
|
||||||
RETINSTR(movls,pc,lr)
|
movls pc, lr
|
||||||
subs r0, r0, #1
|
subs r0, r0, #1
|
||||||
RETINSTR(movls,pc,lr)
|
movls pc, lr
|
||||||
subs r0, r0, #1
|
subs r0, r0, #1
|
||||||
#endif
|
#endif
|
||||||
bhi __delay
|
bhi __delay
|
||||||
RETINSTR(mov,pc,lr)
|
mov pc, lr
|
||||||
|
@@ -29,7 +29,7 @@ ENTRY(ecard_loader_read)
|
|||||||
CPSR2SPSR(r0)
|
CPSR2SPSR(r0)
|
||||||
mov lr, pc
|
mov lr, pc
|
||||||
mov pc, r2
|
mov pc, r2
|
||||||
LOADREGS(fd, sp!, {r4 - r12, pc})
|
ldmfd sp!, {r4 - r12, pc}
|
||||||
|
|
||||||
@ Purpose: call an expansion card loader to reset the card
|
@ Purpose: call an expansion card loader to reset the card
|
||||||
@ Proto : void read_loader(int card_base, char *loader);
|
@ Proto : void read_loader(int card_base, char *loader);
|
||||||
@@ -41,5 +41,5 @@ ENTRY(ecard_loader_reset)
|
|||||||
CPSR2SPSR(r0)
|
CPSR2SPSR(r0)
|
||||||
mov lr, pc
|
mov lr, pc
|
||||||
add pc, r1, #8
|
add pc, r1, #8
|
||||||
LOADREGS(fd, sp!, {r4 - r12, pc})
|
ldmfd sp!, {r4 - r12, pc}
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ ENTRY(_find_first_zero_bit_le)
|
|||||||
2: cmp r2, r1 @ any more?
|
2: cmp r2, r1 @ any more?
|
||||||
blo 1b
|
blo 1b
|
||||||
3: mov r0, r1 @ no free bits
|
3: mov r0, r1 @ no free bits
|
||||||
RETINSTR(mov,pc,lr)
|
mov pc, lr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Purpose : Find next 'zero' bit
|
* Purpose : Find next 'zero' bit
|
||||||
@@ -66,7 +66,7 @@ ENTRY(_find_first_bit_le)
|
|||||||
2: cmp r2, r1 @ any more?
|
2: cmp r2, r1 @ any more?
|
||||||
blo 1b
|
blo 1b
|
||||||
3: mov r0, r1 @ no free bits
|
3: mov r0, r1 @ no free bits
|
||||||
RETINSTR(mov,pc,lr)
|
mov pc, lr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Purpose : Find next 'one' bit
|
* Purpose : Find next 'one' bit
|
||||||
@@ -98,7 +98,7 @@ ENTRY(_find_first_zero_bit_be)
|
|||||||
2: cmp r2, r1 @ any more?
|
2: cmp r2, r1 @ any more?
|
||||||
blo 1b
|
blo 1b
|
||||||
3: mov r0, r1 @ no free bits
|
3: mov r0, r1 @ no free bits
|
||||||
RETINSTR(mov,pc,lr)
|
mov pc, lr
|
||||||
|
|
||||||
ENTRY(_find_next_zero_bit_be)
|
ENTRY(_find_next_zero_bit_be)
|
||||||
teq r1, #0
|
teq r1, #0
|
||||||
@@ -126,7 +126,7 @@ ENTRY(_find_first_bit_be)
|
|||||||
2: cmp r2, r1 @ any more?
|
2: cmp r2, r1 @ any more?
|
||||||
blo 1b
|
blo 1b
|
||||||
3: mov r0, r1 @ no free bits
|
3: mov r0, r1 @ no free bits
|
||||||
RETINSTR(mov,pc,lr)
|
mov pc, lr
|
||||||
|
|
||||||
ENTRY(_find_next_bit_be)
|
ENTRY(_find_next_bit_be)
|
||||||
teq r1, #0
|
teq r1, #0
|
||||||
@@ -164,5 +164,5 @@ ENTRY(_find_next_bit_be)
|
|||||||
addeq r2, r2, #1
|
addeq r2, r2, #1
|
||||||
mov r0, r2
|
mov r0, r2
|
||||||
#endif
|
#endif
|
||||||
RETINSTR(mov,pc,lr)
|
mov pc, lr
|
||||||
|
|
||||||
|
@@ -72,7 +72,7 @@ ENTRY(__raw_readsb)
|
|||||||
bpl .Linsb_16_lp
|
bpl .Linsb_16_lp
|
||||||
|
|
||||||
tst r2, #15
|
tst r2, #15
|
||||||
LOADREGS(eqfd, sp!, {r4 - r6, pc})
|
ldmeqfd sp!, {r4 - r6, pc}
|
||||||
|
|
||||||
.Linsb_no_16: tst r2, #8
|
.Linsb_no_16: tst r2, #8
|
||||||
beq .Linsb_no_8
|
beq .Linsb_no_8
|
||||||
@@ -109,7 +109,7 @@ ENTRY(__raw_readsb)
|
|||||||
str r3, [r1], #4
|
str r3, [r1], #4
|
||||||
|
|
||||||
.Linsb_no_4: ands r2, r2, #3
|
.Linsb_no_4: ands r2, r2, #3
|
||||||
LOADREGS(eqfd, sp!, {r4 - r6, pc})
|
ldmeqfd sp!, {r4 - r6, pc}
|
||||||
|
|
||||||
cmp r2, #2
|
cmp r2, #2
|
||||||
ldrb r3, [r0]
|
ldrb r3, [r0]
|
||||||
@@ -119,4 +119,4 @@ ENTRY(__raw_readsb)
|
|||||||
ldrgtb r3, [r0]
|
ldrgtb r3, [r0]
|
||||||
strgtb r3, [r1]
|
strgtb r3, [r1]
|
||||||
|
|
||||||
LOADREGS(fd, sp!, {r4 - r6, pc})
|
ldmfd sp!, {r4 - r6, pc}
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
strb r3, [r1], #1
|
strb r3, [r1], #1
|
||||||
|
|
||||||
subs r2, r2, #1
|
subs r2, r2, #1
|
||||||
RETINSTR(moveq, pc, lr)
|
moveq pc, lr
|
||||||
|
|
||||||
ENTRY(__raw_readsw)
|
ENTRY(__raw_readsw)
|
||||||
teq r2, #0 @ do we have to check for the zero len?
|
teq r2, #0 @ do we have to check for the zero len?
|
||||||
@@ -69,7 +69,7 @@ ENTRY(__raw_readsw)
|
|||||||
bpl .Linsw_8_lp
|
bpl .Linsw_8_lp
|
||||||
|
|
||||||
tst r2, #7
|
tst r2, #7
|
||||||
LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
|
ldmeqfd sp!, {r4, r5, r6, pc}
|
||||||
|
|
||||||
.Lno_insw_8: tst r2, #4
|
.Lno_insw_8: tst r2, #4
|
||||||
beq .Lno_insw_4
|
beq .Lno_insw_4
|
||||||
@@ -102,6 +102,6 @@ ENTRY(__raw_readsw)
|
|||||||
movne r3, r3, lsr #8
|
movne r3, r3, lsr #8
|
||||||
strneb r3, [r1]
|
strneb r3, [r1]
|
||||||
|
|
||||||
LOADREGS(fd, sp!, {r4, r5, r6, pc})
|
ldmfd sp!, {r4, r5, r6, pc}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -64,7 +64,7 @@ ENTRY(__raw_writesb)
|
|||||||
bpl .Loutsb_16_lp
|
bpl .Loutsb_16_lp
|
||||||
|
|
||||||
tst r2, #15
|
tst r2, #15
|
||||||
LOADREGS(eqfd, sp!, {r4, r5, pc})
|
ldmeqfd sp!, {r4, r5, pc}
|
||||||
|
|
||||||
.Loutsb_no_16: tst r2, #8
|
.Loutsb_no_16: tst r2, #8
|
||||||
beq .Loutsb_no_8
|
beq .Loutsb_no_8
|
||||||
@@ -80,7 +80,7 @@ ENTRY(__raw_writesb)
|
|||||||
outword r3
|
outword r3
|
||||||
|
|
||||||
.Loutsb_no_4: ands r2, r2, #3
|
.Loutsb_no_4: ands r2, r2, #3
|
||||||
LOADREGS(eqfd, sp!, {r4, r5, pc})
|
ldmeqfd sp!, {r4, r5, pc}
|
||||||
|
|
||||||
cmp r2, #2
|
cmp r2, #2
|
||||||
ldrb r3, [r1], #1
|
ldrb r3, [r1], #1
|
||||||
@@ -90,4 +90,4 @@ ENTRY(__raw_writesb)
|
|||||||
ldrgtb r3, [r1]
|
ldrgtb r3, [r1]
|
||||||
strgtb r3, [r0]
|
strgtb r3, [r0]
|
||||||
|
|
||||||
LOADREGS(fd, sp!, {r4, r5, pc})
|
ldmfd sp!, {r4, r5, pc}
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
orr r3, r3, r3, lsl #16
|
orr r3, r3, r3, lsl #16
|
||||||
str r3, [r0]
|
str r3, [r0]
|
||||||
subs r2, r2, #1
|
subs r2, r2, #1
|
||||||
RETINSTR(moveq, pc, lr)
|
moveq pc, lr
|
||||||
|
|
||||||
ENTRY(__raw_writesw)
|
ENTRY(__raw_writesw)
|
||||||
teq r2, #0 @ do we have to check for the zero len?
|
teq r2, #0 @ do we have to check for the zero len?
|
||||||
@@ -80,7 +80,7 @@ ENTRY(__raw_writesw)
|
|||||||
bpl .Loutsw_8_lp
|
bpl .Loutsw_8_lp
|
||||||
|
|
||||||
tst r2, #7
|
tst r2, #7
|
||||||
LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
|
ldmeqfd sp!, {r4, r5, r6, pc}
|
||||||
|
|
||||||
.Lno_outsw_8: tst r2, #4
|
.Lno_outsw_8: tst r2, #4
|
||||||
beq .Lno_outsw_4
|
beq .Lno_outsw_4
|
||||||
@@ -124,4 +124,4 @@ ENTRY(__raw_writesw)
|
|||||||
orrne ip, ip, ip, lsr #16
|
orrne ip, ip, ip, lsr #16
|
||||||
strne ip, [r0]
|
strne ip, [r0]
|
||||||
|
|
||||||
LOADREGS(fd, sp!, {r4, r5, r6, pc})
|
ldmfd sp!, {r4, r5, r6, pc}
|
||||||
|
@@ -22,4 +22,4 @@ ENTRY(memchr)
|
|||||||
bne 1b
|
bne 1b
|
||||||
sub r0, r0, #1
|
sub r0, r0, #1
|
||||||
2: movne r0, #0
|
2: movne r0, #0
|
||||||
RETINSTR(mov,pc,lr)
|
mov pc, lr
|
||||||
|
@@ -53,7 +53,7 @@ ENTRY(memset)
|
|||||||
stmgeia r0!, {r1, r3, ip, lr}
|
stmgeia r0!, {r1, r3, ip, lr}
|
||||||
stmgeia r0!, {r1, r3, ip, lr}
|
stmgeia r0!, {r1, r3, ip, lr}
|
||||||
bgt 2b
|
bgt 2b
|
||||||
LOADREGS(eqfd, sp!, {pc}) @ Now <64 bytes to go.
|
ldmeqfd sp!, {pc} @ Now <64 bytes to go.
|
||||||
/*
|
/*
|
||||||
* No need to correct the count; we're only testing bits from now on
|
* No need to correct the count; we're only testing bits from now on
|
||||||
*/
|
*/
|
||||||
@@ -77,4 +77,4 @@ ENTRY(memset)
|
|||||||
strneb r1, [r0], #1
|
strneb r1, [r0], #1
|
||||||
tst r2, #1
|
tst r2, #1
|
||||||
strneb r1, [r0], #1
|
strneb r1, [r0], #1
|
||||||
RETINSTR(mov,pc,lr)
|
mov pc, lr
|
||||||
|
@@ -53,7 +53,7 @@ ENTRY(__memzero)
|
|||||||
stmgeia r0!, {r2, r3, ip, lr} @ 4
|
stmgeia r0!, {r2, r3, ip, lr} @ 4
|
||||||
stmgeia r0!, {r2, r3, ip, lr} @ 4
|
stmgeia r0!, {r2, r3, ip, lr} @ 4
|
||||||
bgt 3b @ 1
|
bgt 3b @ 1
|
||||||
LOADREGS(eqfd, sp!, {pc}) @ 1/2 quick exit
|
ldmeqfd sp!, {pc} @ 1/2 quick exit
|
||||||
/*
|
/*
|
||||||
* No need to correct the count; we're only testing bits from now on
|
* No need to correct the count; we're only testing bits from now on
|
||||||
*/
|
*/
|
||||||
@@ -77,4 +77,4 @@ ENTRY(__memzero)
|
|||||||
strneb r2, [r0], #1 @ 1
|
strneb r2, [r0], #1 @ 1
|
||||||
tst r1, #1 @ 1 a byte left over
|
tst r1, #1 @ 1 a byte left over
|
||||||
strneb r2, [r0], #1 @ 1
|
strneb r2, [r0], #1 @ 1
|
||||||
RETINSTR(mov,pc,lr) @ 1
|
mov pc, lr @ 1
|
||||||
|
@@ -23,4 +23,4 @@ ENTRY(strchr)
|
|||||||
teq r2, r1
|
teq r2, r1
|
||||||
movne r0, #0
|
movne r0, #0
|
||||||
subeq r0, r0, #1
|
subeq r0, r0, #1
|
||||||
RETINSTR(mov,pc,lr)
|
mov pc, lr
|
||||||
|
@@ -21,7 +21,6 @@
|
|||||||
* -EFAULT on exception, or "len" if we fill the whole buffer
|
* -EFAULT on exception, or "len" if we fill the whole buffer
|
||||||
*/
|
*/
|
||||||
ENTRY(__arch_strncpy_from_user)
|
ENTRY(__arch_strncpy_from_user)
|
||||||
save_lr
|
|
||||||
mov ip, r1
|
mov ip, r1
|
||||||
1: subs r2, r2, #1
|
1: subs r2, r2, #1
|
||||||
USER( ldrplbt r3, [r1], #1)
|
USER( ldrplbt r3, [r1], #1)
|
||||||
@@ -31,13 +30,13 @@ USER( ldrplbt r3, [r1], #1)
|
|||||||
bne 1b
|
bne 1b
|
||||||
sub r1, r1, #1 @ take NUL character out of count
|
sub r1, r1, #1 @ take NUL character out of count
|
||||||
2: sub r0, r1, ip
|
2: sub r0, r1, ip
|
||||||
restore_pc
|
mov pc, lr
|
||||||
|
|
||||||
.section .fixup,"ax"
|
.section .fixup,"ax"
|
||||||
.align 0
|
.align 0
|
||||||
9001: mov r3, #0
|
9001: mov r3, #0
|
||||||
strb r3, [r0, #0] @ null terminate
|
strb r3, [r0, #0] @ null terminate
|
||||||
mov r0, #-EFAULT
|
mov r0, #-EFAULT
|
||||||
restore_pc
|
mov pc, lr
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
|
@@ -21,7 +21,6 @@
|
|||||||
* or zero on exception, or n + 1 if too long
|
* or zero on exception, or n + 1 if too long
|
||||||
*/
|
*/
|
||||||
ENTRY(__arch_strnlen_user)
|
ENTRY(__arch_strnlen_user)
|
||||||
save_lr
|
|
||||||
mov r2, r0
|
mov r2, r0
|
||||||
1:
|
1:
|
||||||
USER( ldrbt r3, [r0], #1)
|
USER( ldrbt r3, [r0], #1)
|
||||||
@@ -31,10 +30,10 @@ USER( ldrbt r3, [r0], #1)
|
|||||||
bne 1b
|
bne 1b
|
||||||
add r0, r0, #1
|
add r0, r0, #1
|
||||||
2: sub r0, r0, r2
|
2: sub r0, r0, r2
|
||||||
restore_pc
|
mov pc, lr
|
||||||
|
|
||||||
.section .fixup,"ax"
|
.section .fixup,"ax"
|
||||||
.align 0
|
.align 0
|
||||||
9001: mov r0, #0
|
9001: mov r0, #0
|
||||||
restore_pc
|
mov pc, lr
|
||||||
.previous
|
.previous
|
||||||
|
@@ -22,4 +22,4 @@ ENTRY(strrchr)
|
|||||||
teq r2, #0
|
teq r2, #0
|
||||||
bne 1b
|
bne 1b
|
||||||
mov r0, r3
|
mov r0, r3
|
||||||
RETINSTR(mov,pc,lr)
|
mov pc, lr
|
||||||
|
@@ -105,7 +105,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
|
|||||||
movs ip, r2
|
movs ip, r2
|
||||||
bne .Lc2u_nowords
|
bne .Lc2u_nowords
|
||||||
.Lc2u_finished: mov r0, #0
|
.Lc2u_finished: mov r0, #0
|
||||||
LOADREGS(fd,sp!,{r2, r4 - r7, pc})
|
ldmfd sp!, {r2, r4 - r7, pc}
|
||||||
|
|
||||||
.Lc2u_src_not_aligned:
|
.Lc2u_src_not_aligned:
|
||||||
bic r1, r1, #3
|
bic r1, r1, #3
|
||||||
@@ -280,7 +280,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
|
|||||||
|
|
||||||
.section .fixup,"ax"
|
.section .fixup,"ax"
|
||||||
.align 0
|
.align 0
|
||||||
9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc})
|
9001: ldmfd sp!, {r0, r4 - r7, pc}
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
/* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
|
/* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
|
||||||
@@ -369,7 +369,7 @@ USER( ldrgtbt r3, [r1], #1) @ May fault
|
|||||||
bne .Lcfu_nowords
|
bne .Lcfu_nowords
|
||||||
.Lcfu_finished: mov r0, #0
|
.Lcfu_finished: mov r0, #0
|
||||||
add sp, sp, #8
|
add sp, sp, #8
|
||||||
LOADREGS(fd,sp!,{r4 - r7, pc})
|
ldmfd sp!, {r4 - r7, pc}
|
||||||
|
|
||||||
.Lcfu_src_not_aligned:
|
.Lcfu_src_not_aligned:
|
||||||
bic r1, r1, #3
|
bic r1, r1, #3
|
||||||
@@ -556,6 +556,6 @@ USER( ldrgtbt r3, [r1], #1) @ May fault
|
|||||||
movne r1, r4
|
movne r1, r4
|
||||||
blne __memzero
|
blne __memzero
|
||||||
mov r0, r4
|
mov r0, r4
|
||||||
LOADREGS(fd,sp!, {r4 - r7, pc})
|
ldmfd sp!, {r4 - r7, pc}
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
|
@@ -4,6 +4,12 @@ menu "AT91RM9200 Implementations"
|
|||||||
|
|
||||||
comment "AT91RM9200 Board Type"
|
comment "AT91RM9200 Board Type"
|
||||||
|
|
||||||
|
config MACH_ONEARM
|
||||||
|
bool "Ajeco 1ARM Single Board Computer"
|
||||||
|
depends on ARCH_AT91RM9200
|
||||||
|
help
|
||||||
|
Select this if you are using Ajeco's 1ARM Single Board Computer
|
||||||
|
|
||||||
config ARCH_AT91RM9200DK
|
config ARCH_AT91RM9200DK
|
||||||
bool "Atmel AT91RM9200-DK Development board"
|
bool "Atmel AT91RM9200-DK Development board"
|
||||||
depends on ARCH_AT91RM9200
|
depends on ARCH_AT91RM9200
|
||||||
|
@@ -10,6 +10,7 @@ obj- :=
|
|||||||
obj-$(CONFIG_PM) += pm.o
|
obj-$(CONFIG_PM) += pm.o
|
||||||
|
|
||||||
# Board-specific support
|
# Board-specific support
|
||||||
|
obj-$(CONFIG_MACH_ONEARM) += board-1arm.o
|
||||||
obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o
|
obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o
|
||||||
obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o
|
obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o
|
||||||
obj-$(CONFIG_MACH_CSB337) += board-csb337.o
|
obj-$(CONFIG_MACH_CSB337) += board-csb337.o
|
||||||
|
109
arch/arm/mach-at91rm9200/board-1arm.c
Normal file
109
arch/arm/mach-at91rm9200/board-1arm.c
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* linux/arch/arm/mach-at91rm9200/board-1arm.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 SAN People
|
||||||
|
*
|
||||||
|
* 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 Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
#include <asm/hardware.h>
|
||||||
|
#include <asm/setup.h>
|
||||||
|
#include <asm/mach-types.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
|
||||||
|
#include <asm/mach/arch.h>
|
||||||
|
#include <asm/mach/map.h>
|
||||||
|
#include <asm/mach/irq.h>
|
||||||
|
|
||||||
|
#include <asm/hardware.h>
|
||||||
|
#include <asm/arch/board.h>
|
||||||
|
#include <asm/arch/gpio.h>
|
||||||
|
|
||||||
|
#include "generic.h"
|
||||||
|
|
||||||
|
static void __init onearm_init_irq(void)
|
||||||
|
{
|
||||||
|
/* Initialize AIC controller */
|
||||||
|
at91rm9200_init_irq(NULL);
|
||||||
|
|
||||||
|
/* Set up the GPIO interrupts */
|
||||||
|
at91_gpio_irq_setup(PQFP_GPIO_BANKS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Serial port configuration.
|
||||||
|
* 0 .. 3 = USART0 .. USART3
|
||||||
|
* 4 = DBGU
|
||||||
|
*/
|
||||||
|
static struct at91_uart_config __initdata onearm_uart_config = {
|
||||||
|
.console_tty = 0, /* ttyS0 */
|
||||||
|
.nr_tty = 3,
|
||||||
|
.tty_map = { 4, 0, 1, -1, -1 }, /* ttyS0, ..., ttyS4 */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init onearm_map_io(void)
|
||||||
|
{
|
||||||
|
at91rm9200_map_io();
|
||||||
|
|
||||||
|
/* Initialize clocks: 18.432 MHz crystal */
|
||||||
|
at91_clock_init(18432000);
|
||||||
|
|
||||||
|
/* Setup the serial ports and console */
|
||||||
|
at91_init_serial(&onearm_uart_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct at91_eth_data __initdata onearm_eth_data = {
|
||||||
|
.phy_irq_pin = AT91_PIN_PC4,
|
||||||
|
.is_rmii = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct at91_usbh_data __initdata onearm_usbh_data = {
|
||||||
|
.ports = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct at91_udc_data __initdata onearm_udc_data = {
|
||||||
|
.vbus_pin = AT91_PIN_PC2,
|
||||||
|
.pullup_pin = AT91_PIN_PC3,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init onearm_board_init(void)
|
||||||
|
{
|
||||||
|
/* Serial */
|
||||||
|
at91_add_device_serial();
|
||||||
|
/* Ethernet */
|
||||||
|
at91_add_device_eth(&onearm_eth_data);
|
||||||
|
/* USB Host */
|
||||||
|
at91_add_device_usbh(&onearm_usbh_data);
|
||||||
|
/* USB Device */
|
||||||
|
at91_add_device_udc(&onearm_udc_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
|
||||||
|
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
|
||||||
|
.phys_io = AT91_BASE_SYS,
|
||||||
|
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
||||||
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
|
.timer = &at91rm9200_timer,
|
||||||
|
.map_io = onearm_map_io,
|
||||||
|
.init_irq = onearm_init_irq,
|
||||||
|
.init_machine = onearm_board_init,
|
||||||
|
MACHINE_END
|
@@ -35,7 +35,6 @@ config ARCH_ADI_COYOTE
|
|||||||
|
|
||||||
config ARCH_IXDP425
|
config ARCH_IXDP425
|
||||||
bool "IXDP425"
|
bool "IXDP425"
|
||||||
select PCI
|
|
||||||
help
|
help
|
||||||
Say 'Y' here if you want your kernel to support Intel's
|
Say 'Y' here if you want your kernel to support Intel's
|
||||||
IXDP425 Development Platform (Also known as Richfield).
|
IXDP425 Development Platform (Also known as Richfield).
|
||||||
@@ -43,7 +42,6 @@ config ARCH_IXDP425
|
|||||||
|
|
||||||
config MACH_IXDPG425
|
config MACH_IXDPG425
|
||||||
bool "IXDPG425"
|
bool "IXDPG425"
|
||||||
select PCI
|
|
||||||
help
|
help
|
||||||
Say 'Y' here if you want your kernel to support Intel's
|
Say 'Y' here if you want your kernel to support Intel's
|
||||||
IXDPG425 Development Platform (Also known as Montajade).
|
IXDPG425 Development Platform (Also known as Montajade).
|
||||||
@@ -51,7 +49,6 @@ config MACH_IXDPG425
|
|||||||
|
|
||||||
config MACH_IXDP465
|
config MACH_IXDP465
|
||||||
bool "IXDP465"
|
bool "IXDP465"
|
||||||
select PCI
|
|
||||||
help
|
help
|
||||||
Say 'Y' here if you want your kernel to support Intel's
|
Say 'Y' here if you want your kernel to support Intel's
|
||||||
IXDP465 Development Platform (Also known as BMP).
|
IXDP465 Development Platform (Also known as BMP).
|
||||||
|
@@ -2,13 +2,23 @@
|
|||||||
# Makefile for the linux kernel.
|
# Makefile for the linux kernel.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
obj-pci-y :=
|
||||||
|
obj-pci-n :=
|
||||||
|
|
||||||
|
obj-pci-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o
|
||||||
|
obj-pci-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o
|
||||||
|
obj-pci-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o
|
||||||
|
obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o
|
||||||
|
obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-pci.o
|
||||||
|
obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o
|
||||||
|
|
||||||
obj-y += common.o
|
obj-y += common.o
|
||||||
|
|
||||||
obj-$(CONFIG_PCI) += common-pci.o
|
obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-setup.o
|
||||||
obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o ixdp425-setup.o
|
obj-$(CONFIG_MACH_IXDPG425) += coyote-setup.o
|
||||||
obj-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o coyote-setup.o
|
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o
|
||||||
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o coyote-setup.o
|
obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o
|
||||||
obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o gtwx5715-setup.o
|
obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o
|
||||||
obj-$(CONFIG_MACH_NSLU2) += nslu2-pci.o nslu2-setup.o nslu2-power.o
|
obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o nas100d-power.o
|
||||||
obj-$(CONFIG_MACH_NAS100D) += nas100d-pci.o nas100d-setup.o nas100d-power.o
|
|
||||||
|
|
||||||
|
obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o
|
||||||
|
@@ -189,7 +189,7 @@ ENTRY(pxa_cpu_suspend)
|
|||||||
.data
|
.data
|
||||||
.align 5
|
.align 5
|
||||||
ENTRY(pxa_cpu_resume)
|
ENTRY(pxa_cpu_resume)
|
||||||
mov r0, #PSR_I_BIT | PSR_F_BIT | MODE_SVC @ set SVC, irqs off
|
mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off
|
||||||
msr cpsr_c, r0
|
msr cpsr_c, r0
|
||||||
|
|
||||||
ldr r0, sleep_save_sp @ stack phys addr
|
ldr r0, sleep_save_sp @ stack phys addr
|
||||||
|
@@ -71,13 +71,13 @@ config ARCH_S3C2440
|
|||||||
Say Y here if you are using the SMDK2440.
|
Say Y here if you are using the SMDK2440.
|
||||||
|
|
||||||
config SMDK2440_CPU2440
|
config SMDK2440_CPU2440
|
||||||
bool "SMDK2440 with S3C2440 cpu module"
|
bool "SMDK2440 with S3C2440 CPU module"
|
||||||
depends on ARCH_S3C2440
|
depends on ARCH_S3C2440
|
||||||
default y if ARCH_S3C2440
|
default y if ARCH_S3C2440
|
||||||
select CPU_S3C2440
|
select CPU_S3C2440
|
||||||
|
|
||||||
config SMDK2440_CPU2442
|
config SMDK2440_CPU2442
|
||||||
bool "SMDM2440 with S3C2442 cpu module"
|
bool "SMDM2440 with S3C2442 CPU module"
|
||||||
depends on ARCH_S3C2440
|
depends on ARCH_S3C2440
|
||||||
select CPU_S3C2442
|
select CPU_S3C2442
|
||||||
|
|
||||||
|
@@ -128,7 +128,7 @@ s3c2410_sleep_save_phys:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ENTRY(s3c2410_cpu_resume)
|
ENTRY(s3c2410_cpu_resume)
|
||||||
mov r0, #PSR_I_BIT | PSR_F_BIT | MODE_SVC
|
mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
|
||||||
msr cpsr_c, r0
|
msr cpsr_c, r0
|
||||||
|
|
||||||
@@ load UART to allow us to print the two characters for
|
@@ load UART to allow us to print the two characters for
|
||||||
|
@@ -177,7 +177,7 @@ sa1110_sdram_controller_fix:
|
|||||||
.data
|
.data
|
||||||
.align 5
|
.align 5
|
||||||
ENTRY(sa1100_cpu_resume)
|
ENTRY(sa1100_cpu_resume)
|
||||||
mov r0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
|
mov r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
|
||||||
msr cpsr_c, r0 @ set SVC, irqs off
|
msr cpsr_c, r0 @ set SVC, irqs off
|
||||||
|
|
||||||
ldr r0, sleep_save_sp @ stack phys addr
|
ldr r0, sleep_save_sp @ stack phys addr
|
||||||
|
@@ -35,7 +35,7 @@ ENTRY(v3_copy_user_page)
|
|||||||
stmia r0!, {r3, r4, ip, lr} @ 4
|
stmia r0!, {r3, r4, ip, lr} @ 4
|
||||||
ldmneia r1!, {r3, r4, ip, lr} @ 4
|
ldmneia r1!, {r3, r4, ip, lr} @ 4
|
||||||
bne 1b @ 1
|
bne 1b @ 1
|
||||||
LOADREGS(fd, sp!, {r4, pc}) @ 3
|
ldmfd sp!, {r4, pc} @ 3
|
||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
/*
|
/*
|
||||||
|
@@ -29,38 +29,6 @@
|
|||||||
#define TTB_RGN_WT (2 << 3)
|
#define TTB_RGN_WT (2 << 3)
|
||||||
#define TTB_RGN_WB (3 << 3)
|
#define TTB_RGN_WB (3 << 3)
|
||||||
|
|
||||||
.macro cpsie, flags
|
|
||||||
.ifc \flags, f
|
|
||||||
.long 0xf1080040
|
|
||||||
.exitm
|
|
||||||
.endif
|
|
||||||
.ifc \flags, i
|
|
||||||
.long 0xf1080080
|
|
||||||
.exitm
|
|
||||||
.endif
|
|
||||||
.ifc \flags, if
|
|
||||||
.long 0xf10800c0
|
|
||||||
.exitm
|
|
||||||
.endif
|
|
||||||
.err
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro cpsid, flags
|
|
||||||
.ifc \flags, f
|
|
||||||
.long 0xf10c0040
|
|
||||||
.exitm
|
|
||||||
.endif
|
|
||||||
.ifc \flags, i
|
|
||||||
.long 0xf10c0080
|
|
||||||
.exitm
|
|
||||||
.endif
|
|
||||||
.ifc \flags, if
|
|
||||||
.long 0xf10c00c0
|
|
||||||
.exitm
|
|
||||||
.endif
|
|
||||||
.err
|
|
||||||
.endm
|
|
||||||
|
|
||||||
ENTRY(cpu_v6_proc_init)
|
ENTRY(cpu_v6_proc_init)
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
It is called from the kernel with code similar to this:
|
It is called from the kernel with code similar to this:
|
||||||
|
|
||||||
mov fp, #0
|
mov fp, #0
|
||||||
teqp pc, #PSR_I_BIT | MODE_SVC
|
teqp pc, #PSR_I_BIT | SVC_MODE
|
||||||
ldr r4, .LC2
|
ldr r4, .LC2
|
||||||
ldr pc, [r4] @ Call FP module USR entry point
|
ldr pc, [r4] @ Call FP module USR entry point
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
#
|
#
|
||||||
# http://www.arm.linux.org.uk/developer/machines/?action=new
|
# http://www.arm.linux.org.uk/developer/machines/?action=new
|
||||||
#
|
#
|
||||||
# Last update: Mon May 8 20:11:05 2006
|
# Last update: Mon Jun 26 22:26:08 2006
|
||||||
#
|
#
|
||||||
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
|
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
|
||||||
#
|
#
|
||||||
@@ -566,8 +566,8 @@ switchgrass MACH_SWITCHGRASS SWITCHGRASS 549
|
|||||||
ens_cmu MACH_ENS_CMU ENS_CMU 550
|
ens_cmu MACH_ENS_CMU ENS_CMU 550
|
||||||
mm6_sdb MACH_MM6_SDB MM6_SDB 551
|
mm6_sdb MACH_MM6_SDB MM6_SDB 551
|
||||||
saturn MACH_SATURN SATURN 552
|
saturn MACH_SATURN SATURN 552
|
||||||
i30030evb MACH_ARGONPLUSEVB ARGONPLUSEVB 553
|
i30030evb MACH_I30030EVB I30030EVB 553
|
||||||
mxc27530evb MACH_SCMA11EVB SCMA11EVB 554
|
mxc27530evb MACH_MXC27530EVB MXC27530EVB 554
|
||||||
smdk2800 MACH_SMDK2800 SMDK2800 555
|
smdk2800 MACH_SMDK2800 SMDK2800 555
|
||||||
mtwilson MACH_MTWILSON MTWILSON 556
|
mtwilson MACH_MTWILSON MTWILSON 556
|
||||||
ziti MACH_ZITI ZITI 557
|
ziti MACH_ZITI ZITI 557
|
||||||
@@ -647,7 +647,7 @@ sendt MACH_SENDT SENDT 630
|
|||||||
mx2jazz MACH_MX2JAZZ MX2JAZZ 631
|
mx2jazz MACH_MX2JAZZ MX2JAZZ 631
|
||||||
multiio MACH_MULTIIO MULTIIO 632
|
multiio MACH_MULTIIO MULTIIO 632
|
||||||
hrdisplay MACH_HRDISPLAY HRDISPLAY 633
|
hrdisplay MACH_HRDISPLAY HRDISPLAY 633
|
||||||
mxc27530ads MACH_SCMA11BB SCMA11BB 634
|
mxc27530ads MACH_MXC27530ADS MXC27530ADS 634
|
||||||
trizeps3 MACH_TRIZEPS3 TRIZEPS3 635
|
trizeps3 MACH_TRIZEPS3 TRIZEPS3 635
|
||||||
zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636
|
zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636
|
||||||
zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637
|
zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637
|
||||||
@@ -721,7 +721,7 @@ gp32 MACH_GP32 GP32 706
|
|||||||
gem MACH_GEM GEM 707
|
gem MACH_GEM GEM 707
|
||||||
i858 MACH_I858 I858 708
|
i858 MACH_I858 I858 708
|
||||||
hx2750 MACH_HX2750 HX2750 709
|
hx2750 MACH_HX2750 HX2750 709
|
||||||
mxc91131evb MACH_ZEUSEVB ZEUSEVB 710
|
mxc91131evb MACH_MXC91131EVB MXC91131EVB 710
|
||||||
p700 MACH_P700 P700 711
|
p700 MACH_P700 P700 711
|
||||||
cpe MACH_CPE CPE 712
|
cpe MACH_CPE CPE 712
|
||||||
spitz MACH_SPITZ SPITZ 713
|
spitz MACH_SPITZ SPITZ 713
|
||||||
@@ -802,7 +802,7 @@ cpuat91 MACH_CPUAT91 CPUAT91 787
|
|||||||
rea9200 MACH_REA9200 REA9200 788
|
rea9200 MACH_REA9200 REA9200 788
|
||||||
acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789
|
acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789
|
||||||
ixp425 MACH_IXP425 IXP425 790
|
ixp425 MACH_IXP425 IXP425 790
|
||||||
i30030ads MACH_ARGONPLUSODYSSEY ARGONPLUSODYSSEY 791
|
i30030ads MACH_I30030ADS I30030ADS 791
|
||||||
perch MACH_PERCH PERCH 792
|
perch MACH_PERCH PERCH 792
|
||||||
eis05r1 MACH_EIS05R1 EIS05R1 793
|
eis05r1 MACH_EIS05R1 EIS05R1 793
|
||||||
pepperpad MACH_PEPPERPAD PEPPERPAD 794
|
pepperpad MACH_PEPPERPAD PEPPERPAD 794
|
||||||
@@ -930,7 +930,7 @@ netclient MACH_NETCLIENT NETCLIENT 916
|
|||||||
xscale_palmtt5 MACH_XSCALE_PALMTT5 XSCALE_PALMTT5 917
|
xscale_palmtt5 MACH_XSCALE_PALMTT5 XSCALE_PALMTT5 917
|
||||||
xscale_palmtc MACH_OMAP_PALMTC OMAP_PALMTC 918
|
xscale_palmtc MACH_OMAP_PALMTC OMAP_PALMTC 918
|
||||||
omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919
|
omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919
|
||||||
mxc30030evb MACH_ARGONLVEVB ARGONLVEVB 920
|
mxc30030evb MACH_MXC30030EVB MXC30030EVB 920
|
||||||
rea_2d MACH_REA_2D REA_2D 921
|
rea_2d MACH_REA_2D REA_2D 921
|
||||||
eti3e524 MACH_TI3E524 TI3E524 922
|
eti3e524 MACH_TI3E524 TI3E524 922
|
||||||
ateb9200 MACH_ATEB9200 ATEB9200 923
|
ateb9200 MACH_ATEB9200 ATEB9200 923
|
||||||
@@ -986,7 +986,7 @@ redfox MACH_REDFOX REDFOX 972
|
|||||||
mysh_ep9315_1 MACH_MYSH_EP9315_1 MYSH_EP9315_1 973
|
mysh_ep9315_1 MACH_MYSH_EP9315_1 MYSH_EP9315_1 973
|
||||||
tpf106 MACH_TPF106 TPF106 974
|
tpf106 MACH_TPF106 TPF106 974
|
||||||
at91rm9200kg MACH_AT91RM9200KG AT91RM9200KG 975
|
at91rm9200kg MACH_AT91RM9200KG AT91RM9200KG 975
|
||||||
racemt2 MACH_SLEDB SLEDB 976
|
rcmt2 MACH_SLEDB SLEDB 976
|
||||||
ontrack MACH_ONTRACK ONTRACK 977
|
ontrack MACH_ONTRACK ONTRACK 977
|
||||||
pm1200 MACH_PM1200 PM1200 978
|
pm1200 MACH_PM1200 PM1200 978
|
||||||
ess24562 MACH_ESS24XXX ESS24XXX 979
|
ess24562 MACH_ESS24XXX ESS24XXX 979
|
||||||
@@ -1022,7 +1022,7 @@ smdk2440 MACH_SMDK2440 SMDK2440 1008
|
|||||||
smdk2412 MACH_SMDK2412 SMDK2412 1009
|
smdk2412 MACH_SMDK2412 SMDK2412 1009
|
||||||
webbox MACH_WEBBOX WEBBOX 1010
|
webbox MACH_WEBBOX WEBBOX 1010
|
||||||
cwwndp MACH_CWWNDP CWWNDP 1011
|
cwwndp MACH_CWWNDP CWWNDP 1011
|
||||||
dragon MACH_DRAGON DRAGON 1012
|
i839 MACH_DRAGON DRAGON 1012
|
||||||
opendo_cpu_board MACH_OPENDO_CPU_BOARD OPENDO_CPU_BOARD 1013
|
opendo_cpu_board MACH_OPENDO_CPU_BOARD OPENDO_CPU_BOARD 1013
|
||||||
ccm2200 MACH_CCM2200 CCM2200 1014
|
ccm2200 MACH_CCM2200 CCM2200 1014
|
||||||
etwarm MACH_ETWARM ETWARM 1015
|
etwarm MACH_ETWARM ETWARM 1015
|
||||||
@@ -1040,3 +1040,56 @@ edg79524 MACH_EDG79524 EDG79524 1026
|
|||||||
ai2410 MACH_AI2410 AI2410 1027
|
ai2410 MACH_AI2410 AI2410 1027
|
||||||
ixp465 MACH_IXP465 IXP465 1028
|
ixp465 MACH_IXP465 IXP465 1028
|
||||||
balloon3 MACH_BALLOON3 BALLOON3 1029
|
balloon3 MACH_BALLOON3 BALLOON3 1029
|
||||||
|
heins MACH_HEINS HEINS 1030
|
||||||
|
mpluseva MACH_MPLUSEVA MPLUSEVA 1031
|
||||||
|
rt042 MACH_RT042 RT042 1032
|
||||||
|
cwiem MACH_CWIEM CWIEM 1033
|
||||||
|
cm_x270 MACH_CM_X270 CM_X270 1034
|
||||||
|
cm_x255 MACH_CM_X255 CM_X255 1035
|
||||||
|
esh_at91 MACH_ESH_AT91 ESH_AT91 1036
|
||||||
|
sandgate3 MACH_SANDGATE3 SANDGATE3 1037
|
||||||
|
primo MACH_PRIMO PRIMO 1038
|
||||||
|
gemstone MACH_GEMSTONE GEMSTONE 1039
|
||||||
|
pronghorn_metro MACH_PRONGHORNMETRO PRONGHORNMETRO 1040
|
||||||
|
sidewinder MACH_SIDEWINDER SIDEWINDER 1041
|
||||||
|
picomod1 MACH_PICOMOD1 PICOMOD1 1042
|
||||||
|
sg590 MACH_SG590 SG590 1043
|
||||||
|
akai9307 MACH_AKAI9307 AKAI9307 1044
|
||||||
|
fontaine MACH_FONTAINE FONTAINE 1045
|
||||||
|
wombat MACH_WOMBAT WOMBAT 1046
|
||||||
|
acq300 MACH_ACQ300 ACQ300 1047
|
||||||
|
mod_270 MACH_MOD_270 MOD_270 1048
|
||||||
|
vmc_vc0820 MACH_VC0820 VC0820 1049
|
||||||
|
ani_aim MACH_ANI_AIM ANI_AIM 1050
|
||||||
|
jellyfish MACH_JELLYFISH JELLYFISH 1051
|
||||||
|
amanita MACH_AMANITA AMANITA 1052
|
||||||
|
vlink MACH_VLINK VLINK 1053
|
||||||
|
dexflex MACH_DEXFLEX DEXFLEX 1054
|
||||||
|
eigen_ttq MACH_EIGEN_TTQ EIGEN_TTQ 1055
|
||||||
|
arcom_titan MACH_ARCOM_TITAN ARCOM_TITAN 1056
|
||||||
|
tabla MACH_TABLA TABLA 1057
|
||||||
|
mdirac3 MACH_MDIRAC3 MDIRAC3 1058
|
||||||
|
mrhfbp2 MACH_MRHFBP2 MRHFBP2 1059
|
||||||
|
at91rm9200rb MACH_AT91RM9200RB AT91RM9200RB 1060
|
||||||
|
ani_apm MACH_ANI_APM ANI_APM 1061
|
||||||
|
ella1 MACH_ELLA1 ELLA1 1062
|
||||||
|
inhand_pxa27x MACH_INHAND_PXA27X INHAND_PXA27X 1063
|
||||||
|
inhand_pxa25x MACH_INHAND_PXA25X INHAND_PXA25X 1064
|
||||||
|
empos_xm MACH_EMPOS_XM EMPOS_XM 1065
|
||||||
|
empos MACH_EMPOS EMPOS 1066
|
||||||
|
empos_tiny MACH_EMPOS_TINY EMPOS_TINY 1067
|
||||||
|
empos_sm MACH_EMPOS_SM EMPOS_SM 1068
|
||||||
|
egret MACH_EGRET EGRET 1069
|
||||||
|
ostrich MACH_OSTRICH OSTRICH 1070
|
||||||
|
n50 MACH_N50 N50 1071
|
||||||
|
ecbat91 MACH_ECBAT91 ECBAT91 1072
|
||||||
|
stareast MACH_STAREAST STAREAST 1073
|
||||||
|
dspg_dw MACH_DSPG_DW DSPG_DW 1074
|
||||||
|
onearm MACH_ONEARM ONEARM 1075
|
||||||
|
mrg110_6 MACH_MRG110_6 MRG110_6 1076
|
||||||
|
wrt300nv2 MACH_WRT300NV2 WRT300NV2 1077
|
||||||
|
xm_bulverde MACH_XM_BULVERDE XM_BULVERDE 1078
|
||||||
|
msm6100 MACH_MSM6100 MSM6100 1079
|
||||||
|
eti_b1 MACH_ETI_B1 ETI_B1 1080
|
||||||
|
za9l_series MACH_ZILOG_ZA9L ZILOG_ZA9L 1081
|
||||||
|
bit2440 MACH_BIT2440 BIT2440 1082
|
||||||
|
@@ -14,6 +14,10 @@ config X86_32
|
|||||||
486, 586, Pentiums, and various instruction-set-compatible chips by
|
486, 586, Pentiums, and various instruction-set-compatible chips by
|
||||||
AMD, Cyrix, and others.
|
AMD, Cyrix, and others.
|
||||||
|
|
||||||
|
config GENERIC_TIME
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config SEMAPHORE_SLEEPERS
|
config SEMAPHORE_SLEEPERS
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
@@ -229,7 +233,7 @@ config NR_CPUS
|
|||||||
|
|
||||||
config SCHED_SMT
|
config SCHED_SMT
|
||||||
bool "SMT (Hyperthreading) scheduler support"
|
bool "SMT (Hyperthreading) scheduler support"
|
||||||
depends on SMP
|
depends on X86_HT
|
||||||
help
|
help
|
||||||
SMT scheduler support improves the CPU scheduler's decision making
|
SMT scheduler support improves the CPU scheduler's decision making
|
||||||
when dealing with Intel Pentium 4 chips with HyperThreading at a
|
when dealing with Intel Pentium 4 chips with HyperThreading at a
|
||||||
@@ -238,7 +242,7 @@ config SCHED_SMT
|
|||||||
|
|
||||||
config SCHED_MC
|
config SCHED_MC
|
||||||
bool "Multi-core scheduler support"
|
bool "Multi-core scheduler support"
|
||||||
depends on SMP
|
depends on X86_HT
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Multi-core scheduler support improves the CPU scheduler's decision
|
Multi-core scheduler support improves the CPU scheduler's decision
|
||||||
@@ -324,6 +328,15 @@ config X86_MCE_P4THERMAL
|
|||||||
Enabling this feature will cause a message to be printed when the P4
|
Enabling this feature will cause a message to be printed when the P4
|
||||||
enters thermal throttling.
|
enters thermal throttling.
|
||||||
|
|
||||||
|
config VM86
|
||||||
|
default y
|
||||||
|
bool "Enable VM86 support" if EMBEDDED
|
||||||
|
help
|
||||||
|
This option is required by programs like DOSEMU to run 16-bit legacy
|
||||||
|
code on X86 processors. It also may be needed by software like
|
||||||
|
XFree86 to initialize some video cards via BIOS. Disabling this
|
||||||
|
option saves about 6k.
|
||||||
|
|
||||||
config TOSHIBA
|
config TOSHIBA
|
||||||
tristate "Toshiba Laptop support"
|
tristate "Toshiba Laptop support"
|
||||||
---help---
|
---help---
|
||||||
@@ -721,7 +734,7 @@ config KEXEC
|
|||||||
help
|
help
|
||||||
kexec is a system call that implements the ability to shutdown your
|
kexec is a system call that implements the ability to shutdown your
|
||||||
current kernel, and to start another kernel. It is like a reboot
|
current kernel, and to start another kernel. It is like a reboot
|
||||||
but it is indepedent of the system firmware. And like a reboot
|
but it is independent of the system firmware. And like a reboot
|
||||||
you can start any kernel with it, not just Linux.
|
you can start any kernel with it, not just Linux.
|
||||||
|
|
||||||
The name comes from the similiarity to the exec system call.
|
The name comes from the similiarity to the exec system call.
|
||||||
@@ -767,6 +780,17 @@ config HOTPLUG_CPU
|
|||||||
enable suspend on SMP systems. CPUs can be controlled through
|
enable suspend on SMP systems. CPUs can be controlled through
|
||||||
/sys/devices/system/cpu.
|
/sys/devices/system/cpu.
|
||||||
|
|
||||||
|
config COMPAT_VDSO
|
||||||
|
bool "Compat VDSO support"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Map the VDSO to the predictable old-style address too.
|
||||||
|
---help---
|
||||||
|
Say N here if you are running a sufficiently recent glibc
|
||||||
|
version (2.3.3 or later), to remove the high-mapped
|
||||||
|
VDSO mapping and to exclusively use the randomized VDSO.
|
||||||
|
|
||||||
|
If unsure, say Y.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
@@ -1046,13 +1070,27 @@ config SCx200
|
|||||||
tristate "NatSemi SCx200 support"
|
tristate "NatSemi SCx200 support"
|
||||||
depends on !X86_VOYAGER
|
depends on !X86_VOYAGER
|
||||||
help
|
help
|
||||||
This provides basic support for the National Semiconductor SCx200
|
This provides basic support for National Semiconductor's
|
||||||
processor. Right now this is just a driver for the GPIO pins.
|
(now AMD's) Geode processors. The driver probes for the
|
||||||
|
PCI-IDs of several on-chip devices, so its a good dependency
|
||||||
|
for other scx200_* drivers.
|
||||||
|
|
||||||
If you don't know what to do here, say N.
|
If compiled as a module, the driver is named scx200.
|
||||||
|
|
||||||
This support is also available as a module. If compiled as a
|
config SCx200HR_TIMER
|
||||||
module, it will be called scx200.
|
tristate "NatSemi SCx200 27MHz High-Resolution Timer Support"
|
||||||
|
depends on SCx200 && GENERIC_TIME
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
This driver provides a clocksource built upon the on-chip
|
||||||
|
27MHz high-resolution timer. Its also a workaround for
|
||||||
|
NSC Geode SC-1100's buggy TSC, which loses time when the
|
||||||
|
processor goes idle (as is done by the scheduler). The
|
||||||
|
other workaround is idle=poll boot option.
|
||||||
|
|
||||||
|
config K8_NB
|
||||||
|
def_bool y
|
||||||
|
depends on AGP_AMD64
|
||||||
|
|
||||||
source "drivers/pcmcia/Kconfig"
|
source "drivers/pcmcia/Kconfig"
|
||||||
|
|
||||||
|
@@ -41,7 +41,7 @@ config M386
|
|||||||
- "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
|
- "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
|
||||||
- "Geode GX/LX" For AMD Geode GX and LX processors.
|
- "Geode GX/LX" For AMD Geode GX and LX processors.
|
||||||
- "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
|
- "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
|
||||||
- "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
|
- "VIA C3-2" for VIA C3-2 "Nehemiah" (model 9 and above).
|
||||||
|
|
||||||
If you don't know what to do, choose "386".
|
If you don't know what to do, choose "386".
|
||||||
|
|
||||||
|
@@ -109,8 +109,13 @@ fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
|
|||||||
isoimage: $(BOOTIMAGE)
|
isoimage: $(BOOTIMAGE)
|
||||||
-rm -rf $(obj)/isoimage
|
-rm -rf $(obj)/isoimage
|
||||||
mkdir $(obj)/isoimage
|
mkdir $(obj)/isoimage
|
||||||
cp `echo /usr/lib*/syslinux/isolinux.bin | awk '{ print $1; }'` \
|
for i in lib lib64 share end ; do \
|
||||||
$(obj)/isoimage
|
if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \
|
||||||
|
cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \
|
||||||
|
break ; \
|
||||||
|
fi ; \
|
||||||
|
if [ $$i = end ] ; then exit 1 ; fi ; \
|
||||||
|
done
|
||||||
cp $(BOOTIMAGE) $(obj)/isoimage/linux
|
cp $(BOOTIMAGE) $(obj)/isoimage/linux
|
||||||
echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg
|
echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg
|
||||||
if [ -f '$(FDINITRD)' ] ; then \
|
if [ -f '$(FDINITRD)' ] ; then \
|
||||||
|
@@ -24,14 +24,6 @@
|
|||||||
|
|
||||||
#undef memset
|
#undef memset
|
||||||
#undef memcpy
|
#undef memcpy
|
||||||
|
|
||||||
/*
|
|
||||||
* Why do we do this? Don't ask me..
|
|
||||||
*
|
|
||||||
* Incomprehensible are the ways of bootloaders.
|
|
||||||
*/
|
|
||||||
static void* memset(void *, int, size_t);
|
|
||||||
static void* memcpy(void *, __const void *, size_t);
|
|
||||||
#define memzero(s, n) memset ((s), 0, (n))
|
#define memzero(s, n) memset ((s), 0, (n))
|
||||||
|
|
||||||
typedef unsigned char uch;
|
typedef unsigned char uch;
|
||||||
@@ -93,7 +85,7 @@ static unsigned char *real_mode; /* Pointer to real-mode data */
|
|||||||
#endif
|
#endif
|
||||||
#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
|
#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
|
||||||
|
|
||||||
extern char input_data[];
|
extern unsigned char input_data[];
|
||||||
extern int input_len;
|
extern int input_len;
|
||||||
|
|
||||||
static long bytes_out = 0;
|
static long bytes_out = 0;
|
||||||
@@ -103,6 +95,9 @@ static unsigned long output_ptr = 0;
|
|||||||
static void *malloc(int size);
|
static void *malloc(int size);
|
||||||
static void free(void *where);
|
static void free(void *where);
|
||||||
|
|
||||||
|
static void *memset(void *s, int c, unsigned n);
|
||||||
|
static void *memcpy(void *dest, const void *src, unsigned n);
|
||||||
|
|
||||||
static void putstr(const char *);
|
static void putstr(const char *);
|
||||||
|
|
||||||
extern int end;
|
extern int end;
|
||||||
@@ -205,7 +200,7 @@ static void putstr(const char *s)
|
|||||||
outb_p(0xff & (pos >> 1), vidport+1);
|
outb_p(0xff & (pos >> 1), vidport+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* memset(void* s, int c, size_t n)
|
static void* memset(void* s, int c, unsigned n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char *ss = (char*)s;
|
char *ss = (char*)s;
|
||||||
@@ -214,14 +209,13 @@ static void* memset(void* s, int c, size_t n)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* memcpy(void* __dest, __const void* __src,
|
static void* memcpy(void* dest, const void* src, unsigned n)
|
||||||
size_t __n)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char *d = (char *)__dest, *s = (char *)__src;
|
char *d = (char *)dest, *s = (char *)src;
|
||||||
|
|
||||||
for (i=0;i<__n;i++) d[i] = s[i];
|
for (i=0;i<n;i++) d[i] = s[i];
|
||||||
return __dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===========================================================================
|
/* ===========================================================================
|
||||||
@@ -309,7 +303,7 @@ static void setup_normal_output_buffer(void)
|
|||||||
#else
|
#else
|
||||||
if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory");
|
if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory");
|
||||||
#endif
|
#endif
|
||||||
output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */
|
output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */
|
||||||
free_mem_end_ptr = (long)real_mode;
|
free_mem_end_ptr = (long)real_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,11 +318,9 @@ static void setup_output_buffer_if_we_run_high(struct moveparams *mv)
|
|||||||
#ifdef STANDARD_MEMORY_BIOS_CALL
|
#ifdef STANDARD_MEMORY_BIOS_CALL
|
||||||
if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory");
|
if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory");
|
||||||
#else
|
#else
|
||||||
if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) <
|
if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory");
|
||||||
(3*1024))
|
|
||||||
error("Less than 4MB of memory");
|
|
||||||
#endif
|
#endif
|
||||||
mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
|
mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START;
|
||||||
low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
|
low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
|
||||||
? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
|
? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
|
||||||
low_buffer_size = low_buffer_end - LOW_BUFFER_START;
|
low_buffer_size = low_buffer_end - LOW_BUFFER_START;
|
||||||
|
@@ -1929,7 +1929,7 @@ skip10: movb %ah, %al
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
store_edid:
|
store_edid:
|
||||||
#ifdef CONFIG_FB_FIRMWARE_EDID
|
#ifdef CONFIG_FIRMWARE_EDID
|
||||||
pushw %es # just save all registers
|
pushw %es # just save all registers
|
||||||
pushw %ax
|
pushw %ax
|
||||||
pushw %bx
|
pushw %bx
|
||||||
@@ -1947,6 +1947,22 @@ store_edid:
|
|||||||
rep
|
rep
|
||||||
stosl
|
stosl
|
||||||
|
|
||||||
|
pushw %es # save ES
|
||||||
|
xorw %di, %di # Report Capability
|
||||||
|
pushw %di
|
||||||
|
popw %es # ES:DI must be 0:0
|
||||||
|
movw $0x4f15, %ax
|
||||||
|
xorw %bx, %bx
|
||||||
|
xorw %cx, %cx
|
||||||
|
int $0x10
|
||||||
|
popw %es # restore ES
|
||||||
|
|
||||||
|
cmpb $0x00, %ah # call successful
|
||||||
|
jne no_edid
|
||||||
|
|
||||||
|
cmpb $0x4f, %al # function supported
|
||||||
|
jne no_edid
|
||||||
|
|
||||||
movw $0x4f15, %ax # do VBE/DDC
|
movw $0x4f15, %ax # do VBE/DDC
|
||||||
movw $0x01, %bx
|
movw $0x01, %bx
|
||||||
movw $0x00, %cx
|
movw $0x00, %cx
|
||||||
@@ -1954,6 +1970,7 @@ store_edid:
|
|||||||
movw $0x140, %di
|
movw $0x140, %di
|
||||||
int $0x10
|
int $0x10
|
||||||
|
|
||||||
|
no_edid:
|
||||||
popw %di # restore all registers
|
popw %di # restore all registers
|
||||||
popw %dx
|
popw %dx
|
||||||
popw %cx
|
popw %cx
|
||||||
|
@@ -36,22 +36,19 @@
|
|||||||
.file "aes-i586-asm.S"
|
.file "aes-i586-asm.S"
|
||||||
.text
|
.text
|
||||||
|
|
||||||
// aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])//
|
#include <asm/asm-offsets.h>
|
||||||
// aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])//
|
|
||||||
|
|
||||||
#define tlen 1024 // length of each of 4 'xor' arrays (256 32-bit words)
|
#define tlen 1024 // length of each of 4 'xor' arrays (256 32-bit words)
|
||||||
|
|
||||||
// offsets to parameters with one register pushed onto stack
|
/* offsets to parameters with one register pushed onto stack */
|
||||||
|
#define tfm 8
|
||||||
|
#define out_blk 12
|
||||||
|
#define in_blk 16
|
||||||
|
|
||||||
#define in_blk 8 // input byte array address parameter
|
/* offsets in crypto_tfm structure */
|
||||||
#define out_blk 12 // output byte array address parameter
|
#define ekey (crypto_tfm_ctx_offset + 0)
|
||||||
#define ctx 16 // AES context structure
|
#define nrnd (crypto_tfm_ctx_offset + 256)
|
||||||
|
#define dkey (crypto_tfm_ctx_offset + 260)
|
||||||
// offsets in context structure
|
|
||||||
|
|
||||||
#define ekey 0 // encryption key schedule base address
|
|
||||||
#define nrnd 256 // number of rounds
|
|
||||||
#define dkey 260 // decryption key schedule base address
|
|
||||||
|
|
||||||
// register mapping for encrypt and decrypt subroutines
|
// register mapping for encrypt and decrypt subroutines
|
||||||
|
|
||||||
@@ -220,6 +217,7 @@
|
|||||||
do_col (table, r5,r0,r1,r4, r2,r3); /* idx=r5 */
|
do_col (table, r5,r0,r1,r4, r2,r3); /* idx=r5 */
|
||||||
|
|
||||||
// AES (Rijndael) Encryption Subroutine
|
// AES (Rijndael) Encryption Subroutine
|
||||||
|
/* void aes_enc_blk(struct crypto_tfm *tfm, u8 *out_blk, const u8 *in_blk) */
|
||||||
|
|
||||||
.global aes_enc_blk
|
.global aes_enc_blk
|
||||||
|
|
||||||
@@ -230,7 +228,7 @@
|
|||||||
|
|
||||||
aes_enc_blk:
|
aes_enc_blk:
|
||||||
push %ebp
|
push %ebp
|
||||||
mov ctx(%esp),%ebp // pointer to context
|
mov tfm(%esp),%ebp
|
||||||
|
|
||||||
// CAUTION: the order and the values used in these assigns
|
// CAUTION: the order and the values used in these assigns
|
||||||
// rely on the register mappings
|
// rely on the register mappings
|
||||||
@@ -295,6 +293,7 @@ aes_enc_blk:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
// AES (Rijndael) Decryption Subroutine
|
// AES (Rijndael) Decryption Subroutine
|
||||||
|
/* void aes_dec_blk(struct crypto_tfm *tfm, u8 *out_blk, const u8 *in_blk) */
|
||||||
|
|
||||||
.global aes_dec_blk
|
.global aes_dec_blk
|
||||||
|
|
||||||
@@ -305,7 +304,7 @@ aes_enc_blk:
|
|||||||
|
|
||||||
aes_dec_blk:
|
aes_dec_blk:
|
||||||
push %ebp
|
push %ebp
|
||||||
mov ctx(%esp),%ebp // pointer to context
|
mov tfm(%esp),%ebp
|
||||||
|
|
||||||
// CAUTION: the order and the values used in these assigns
|
// CAUTION: the order and the values used in these assigns
|
||||||
// rely on the register mappings
|
// rely on the register mappings
|
||||||
|
@@ -45,8 +45,8 @@
|
|||||||
#include <linux/crypto.h>
|
#include <linux/crypto.h>
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
asmlinkage void aes_enc_blk(const u8 *src, u8 *dst, void *ctx);
|
asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
|
||||||
asmlinkage void aes_dec_blk(const u8 *src, u8 *dst, void *ctx);
|
asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
|
||||||
|
|
||||||
#define AES_MIN_KEY_SIZE 16
|
#define AES_MIN_KEY_SIZE 16
|
||||||
#define AES_MAX_KEY_SIZE 32
|
#define AES_MAX_KEY_SIZE 32
|
||||||
@@ -378,12 +378,12 @@ static void gen_tabs(void)
|
|||||||
k[8*(i)+11] = ss[3]; \
|
k[8*(i)+11] = ss[3]; \
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
|
||||||
aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
|
unsigned int key_len, u32 *flags)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
u32 ss[8];
|
u32 ss[8];
|
||||||
struct aes_ctx *ctx = ctx_arg;
|
struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||||
const __le32 *key = (const __le32 *)in_key;
|
const __le32 *key = (const __le32 *)in_key;
|
||||||
|
|
||||||
/* encryption schedule */
|
/* encryption schedule */
|
||||||
@@ -464,15 +464,15 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void aes_encrypt(void *ctx, u8 *dst, const u8 *src)
|
static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||||
{
|
{
|
||||||
aes_enc_blk(src, dst, ctx);
|
aes_enc_blk(tfm, dst, src);
|
||||||
}
|
|
||||||
static inline void aes_decrypt(void *ctx, u8 *dst, const u8 *src)
|
|
||||||
{
|
|
||||||
aes_dec_blk(src, dst, ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||||
|
{
|
||||||
|
aes_dec_blk(tfm, dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
static struct crypto_alg aes_alg = {
|
static struct crypto_alg aes_alg = {
|
||||||
.cra_name = "aes",
|
.cra_name = "aes",
|
||||||
|
@@ -7,10 +7,9 @@ extra-y := head.o init_task.o vmlinux.lds
|
|||||||
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
|
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
|
||||||
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
|
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
|
||||||
pci-dma.o i386_ksyms.o i387.o bootflag.o \
|
pci-dma.o i386_ksyms.o i387.o bootflag.o \
|
||||||
quirks.o i8237.o topology.o alternative.o
|
quirks.o i8237.o topology.o alternative.o i8253.o tsc.o
|
||||||
|
|
||||||
obj-y += cpu/
|
obj-y += cpu/
|
||||||
obj-y += timers/
|
|
||||||
obj-y += acpi/
|
obj-y += acpi/
|
||||||
obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o
|
obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o
|
||||||
obj-$(CONFIG_MCA) += mca.o
|
obj-$(CONFIG_MCA) += mca.o
|
||||||
@@ -37,6 +36,8 @@ obj-$(CONFIG_EFI) += efi.o efi_stub.o
|
|||||||
obj-$(CONFIG_DOUBLEFAULT) += doublefault.o
|
obj-$(CONFIG_DOUBLEFAULT) += doublefault.o
|
||||||
obj-$(CONFIG_VM86) += vm86.o
|
obj-$(CONFIG_VM86) += vm86.o
|
||||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||||
|
obj-$(CONFIG_HPET_TIMER) += hpet.o
|
||||||
|
obj-$(CONFIG_K8_NB) += k8.o
|
||||||
|
|
||||||
EXTRA_AFLAGS := -traditional
|
EXTRA_AFLAGS := -traditional
|
||||||
|
|
||||||
@@ -76,3 +77,6 @@ SYSCFLAGS_vsyscall-syms.o = -r
|
|||||||
$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
|
$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
|
||||||
$(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE
|
$(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE
|
||||||
$(call if_changed,syscall)
|
$(call if_changed,syscall)
|
||||||
|
|
||||||
|
k8-y += ../../x86_64/kernel/k8.o
|
||||||
|
|
||||||
|
@@ -4,27 +4,41 @@
|
|||||||
#include <asm/alternative.h>
|
#include <asm/alternative.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
|
|
||||||
#define DEBUG 0
|
static int no_replacement = 0;
|
||||||
#if DEBUG
|
static int smp_alt_once = 0;
|
||||||
# define DPRINTK(fmt, args...) printk(fmt, args)
|
static int debug_alternative = 0;
|
||||||
#else
|
|
||||||
# define DPRINTK(fmt, args...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
static int __init noreplacement_setup(char *s)
|
||||||
|
{
|
||||||
|
no_replacement = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int __init bootonly(char *str)
|
||||||
|
{
|
||||||
|
smp_alt_once = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int __init debug_alt(char *str)
|
||||||
|
{
|
||||||
|
debug_alternative = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__setup("noreplacement", noreplacement_setup);
|
||||||
|
__setup("smp-alt-boot", bootonly);
|
||||||
|
__setup("debug-alternative", debug_alt);
|
||||||
|
|
||||||
|
#define DPRINTK(fmt, args...) if (debug_alternative) \
|
||||||
|
printk(KERN_DEBUG fmt, args)
|
||||||
|
|
||||||
|
#ifdef GENERIC_NOP1
|
||||||
/* Use inline assembly to define this because the nops are defined
|
/* Use inline assembly to define this because the nops are defined
|
||||||
as inline assembly strings in the include files and we cannot
|
as inline assembly strings in the include files and we cannot
|
||||||
get them easily into strings. */
|
get them easily into strings. */
|
||||||
asm("\t.data\nintelnops: "
|
asm("\t.data\nintelnops: "
|
||||||
GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
|
GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
|
||||||
GENERIC_NOP7 GENERIC_NOP8);
|
GENERIC_NOP7 GENERIC_NOP8);
|
||||||
asm("\t.data\nk8nops: "
|
extern unsigned char intelnops[];
|
||||||
K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
|
|
||||||
K8_NOP7 K8_NOP8);
|
|
||||||
asm("\t.data\nk7nops: "
|
|
||||||
K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
|
|
||||||
K7_NOP7 K7_NOP8);
|
|
||||||
|
|
||||||
extern unsigned char intelnops[], k8nops[], k7nops[];
|
|
||||||
static unsigned char *intel_nops[ASM_NOP_MAX+1] = {
|
static unsigned char *intel_nops[ASM_NOP_MAX+1] = {
|
||||||
NULL,
|
NULL,
|
||||||
intelnops,
|
intelnops,
|
||||||
@@ -36,6 +50,13 @@ static unsigned char *intel_nops[ASM_NOP_MAX+1] = {
|
|||||||
intelnops + 1 + 2 + 3 + 4 + 5 + 6,
|
intelnops + 1 + 2 + 3 + 4 + 5 + 6,
|
||||||
intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
|
intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef K8_NOP1
|
||||||
|
asm("\t.data\nk8nops: "
|
||||||
|
K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
|
||||||
|
K8_NOP7 K8_NOP8);
|
||||||
|
extern unsigned char k8nops[];
|
||||||
static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
|
static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
|
||||||
NULL,
|
NULL,
|
||||||
k8nops,
|
k8nops,
|
||||||
@@ -47,6 +68,13 @@ static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
|
|||||||
k8nops + 1 + 2 + 3 + 4 + 5 + 6,
|
k8nops + 1 + 2 + 3 + 4 + 5 + 6,
|
||||||
k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
|
k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef K7_NOP1
|
||||||
|
asm("\t.data\nk7nops: "
|
||||||
|
K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
|
||||||
|
K7_NOP7 K7_NOP8);
|
||||||
|
extern unsigned char k7nops[];
|
||||||
static unsigned char *k7_nops[ASM_NOP_MAX+1] = {
|
static unsigned char *k7_nops[ASM_NOP_MAX+1] = {
|
||||||
NULL,
|
NULL,
|
||||||
k7nops,
|
k7nops,
|
||||||
@@ -58,6 +86,18 @@ static unsigned char *k7_nops[ASM_NOP_MAX+1] = {
|
|||||||
k7nops + 1 + 2 + 3 + 4 + 5 + 6,
|
k7nops + 1 + 2 + 3 + 4 + 5 + 6,
|
||||||
k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
|
k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
|
||||||
|
extern char __vsyscall_0;
|
||||||
|
static inline unsigned char** find_nop_table(void)
|
||||||
|
{
|
||||||
|
return k8_nops;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* CONFIG_X86_64 */
|
||||||
|
|
||||||
static struct nop {
|
static struct nop {
|
||||||
int cpuid;
|
int cpuid;
|
||||||
unsigned char **noptable;
|
unsigned char **noptable;
|
||||||
@@ -67,14 +107,6 @@ static struct nop {
|
|||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
|
|
||||||
extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[];
|
|
||||||
extern u8 *__smp_locks[], *__smp_locks_end[];
|
|
||||||
|
|
||||||
extern u8 __smp_alt_begin[], __smp_alt_end[];
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned char** find_nop_table(void)
|
static unsigned char** find_nop_table(void)
|
||||||
{
|
{
|
||||||
unsigned char **noptable = intel_nops;
|
unsigned char **noptable = intel_nops;
|
||||||
@@ -89,6 +121,14 @@ static unsigned char** find_nop_table(void)
|
|||||||
return noptable;
|
return noptable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_X86_64 */
|
||||||
|
|
||||||
|
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
|
||||||
|
extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[];
|
||||||
|
extern u8 *__smp_locks[], *__smp_locks_end[];
|
||||||
|
|
||||||
|
extern u8 __smp_alt_begin[], __smp_alt_end[];
|
||||||
|
|
||||||
/* Replace instructions with better alternatives for this CPU type.
|
/* Replace instructions with better alternatives for this CPU type.
|
||||||
This runs before SMP is initialized to avoid SMP problems with
|
This runs before SMP is initialized to avoid SMP problems with
|
||||||
self modifying code. This implies that assymetric systems where
|
self modifying code. This implies that assymetric systems where
|
||||||
@@ -99,6 +139,7 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
|
|||||||
{
|
{
|
||||||
unsigned char **noptable = find_nop_table();
|
unsigned char **noptable = find_nop_table();
|
||||||
struct alt_instr *a;
|
struct alt_instr *a;
|
||||||
|
u8 *instr;
|
||||||
int diff, i, k;
|
int diff, i, k;
|
||||||
|
|
||||||
DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end);
|
DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end);
|
||||||
@@ -106,7 +147,16 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
|
|||||||
BUG_ON(a->replacementlen > a->instrlen);
|
BUG_ON(a->replacementlen > a->instrlen);
|
||||||
if (!boot_cpu_has(a->cpuid))
|
if (!boot_cpu_has(a->cpuid))
|
||||||
continue;
|
continue;
|
||||||
memcpy(a->instr, a->replacement, a->replacementlen);
|
instr = a->instr;
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
/* vsyscall code is not mapped yet. resolve it manually. */
|
||||||
|
if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) {
|
||||||
|
instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
|
||||||
|
DPRINTK("%s: vsyscall fixup: %p => %p\n",
|
||||||
|
__FUNCTION__, a->instr, instr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
memcpy(instr, a->replacement, a->replacementlen);
|
||||||
diff = a->instrlen - a->replacementlen;
|
diff = a->instrlen - a->replacementlen;
|
||||||
/* Pad the rest with nops */
|
/* Pad the rest with nops */
|
||||||
for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
|
for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
|
||||||
@@ -186,14 +236,6 @@ struct smp_alt_module {
|
|||||||
static LIST_HEAD(smp_alt_modules);
|
static LIST_HEAD(smp_alt_modules);
|
||||||
static DEFINE_SPINLOCK(smp_alt);
|
static DEFINE_SPINLOCK(smp_alt);
|
||||||
|
|
||||||
static int smp_alt_once = 0;
|
|
||||||
static int __init bootonly(char *str)
|
|
||||||
{
|
|
||||||
smp_alt_once = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
__setup("smp-alt-boot", bootonly);
|
|
||||||
|
|
||||||
void alternatives_smp_module_add(struct module *mod, char *name,
|
void alternatives_smp_module_add(struct module *mod, char *name,
|
||||||
void *locks, void *locks_end,
|
void *locks, void *locks_end,
|
||||||
void *text, void *text_end)
|
void *text, void *text_end)
|
||||||
@@ -201,6 +243,9 @@ void alternatives_smp_module_add(struct module *mod, char *name,
|
|||||||
struct smp_alt_module *smp;
|
struct smp_alt_module *smp;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (no_replacement)
|
||||||
|
return;
|
||||||
|
|
||||||
if (smp_alt_once) {
|
if (smp_alt_once) {
|
||||||
if (boot_cpu_has(X86_FEATURE_UP))
|
if (boot_cpu_has(X86_FEATURE_UP))
|
||||||
alternatives_smp_unlock(locks, locks_end,
|
alternatives_smp_unlock(locks, locks_end,
|
||||||
@@ -235,7 +280,7 @@ void alternatives_smp_module_del(struct module *mod)
|
|||||||
struct smp_alt_module *item;
|
struct smp_alt_module *item;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (smp_alt_once)
|
if (no_replacement || smp_alt_once)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&smp_alt, flags);
|
spin_lock_irqsave(&smp_alt, flags);
|
||||||
@@ -256,7 +301,7 @@ void alternatives_smp_switch(int smp)
|
|||||||
struct smp_alt_module *mod;
|
struct smp_alt_module *mod;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (smp_alt_once)
|
if (no_replacement || smp_alt_once)
|
||||||
return;
|
return;
|
||||||
BUG_ON(!smp && (num_online_cpus() > 1));
|
BUG_ON(!smp && (num_online_cpus() > 1));
|
||||||
|
|
||||||
@@ -285,6 +330,13 @@ void alternatives_smp_switch(int smp)
|
|||||||
|
|
||||||
void __init alternative_instructions(void)
|
void __init alternative_instructions(void)
|
||||||
{
|
{
|
||||||
|
if (no_replacement) {
|
||||||
|
printk(KERN_INFO "(SMP-)alternatives turned off\n");
|
||||||
|
free_init_pages("SMP alternatives",
|
||||||
|
(unsigned long)__smp_alt_begin,
|
||||||
|
(unsigned long)__smp_alt_end);
|
||||||
|
return;
|
||||||
|
}
|
||||||
apply_alternatives(__alt_instructions, __alt_instructions_end);
|
apply_alternatives(__alt_instructions, __alt_instructions_end);
|
||||||
|
|
||||||
/* switch to patch-once-at-boottime-only mode and free the
|
/* switch to patch-once-at-boottime-only mode and free the
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include <asm/arch_hooks.h>
|
#include <asm/arch_hooks.h>
|
||||||
#include <asm/hpet.h>
|
#include <asm/hpet.h>
|
||||||
#include <asm/i8253.h>
|
#include <asm/i8253.h>
|
||||||
|
#include <asm/nmi.h>
|
||||||
|
|
||||||
#include <mach_apic.h>
|
#include <mach_apic.h>
|
||||||
#include <mach_apicdef.h>
|
#include <mach_apicdef.h>
|
||||||
@@ -156,7 +157,7 @@ void clear_local_APIC(void)
|
|||||||
maxlvt = get_maxlvt();
|
maxlvt = get_maxlvt();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Masking an LVT entry on a P6 can trigger a local APIC error
|
* Masking an LVT entry can trigger a local APIC error
|
||||||
* if the vector is zero. Mask LVTERR first to prevent this.
|
* if the vector is zero. Mask LVTERR first to prevent this.
|
||||||
*/
|
*/
|
||||||
if (maxlvt >= 3) {
|
if (maxlvt >= 3) {
|
||||||
@@ -1117,7 +1118,18 @@ void disable_APIC_timer(void)
|
|||||||
unsigned long v;
|
unsigned long v;
|
||||||
|
|
||||||
v = apic_read(APIC_LVTT);
|
v = apic_read(APIC_LVTT);
|
||||||
apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
|
/*
|
||||||
|
* When an illegal vector value (0-15) is written to an LVT
|
||||||
|
* entry and delivery mode is Fixed, the APIC may signal an
|
||||||
|
* illegal vector error, with out regard to whether the mask
|
||||||
|
* bit is set or whether an interrupt is actually seen on input.
|
||||||
|
*
|
||||||
|
* Boot sequence might call this function when the LVTT has
|
||||||
|
* '0' vector value. So make sure vector field is set to
|
||||||
|
* valid value.
|
||||||
|
*/
|
||||||
|
v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
|
||||||
|
apic_write_around(APIC_LVTT, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -764,9 +764,9 @@ static int apm_do_idle(void)
|
|||||||
int idled = 0;
|
int idled = 0;
|
||||||
int polling;
|
int polling;
|
||||||
|
|
||||||
polling = test_thread_flag(TIF_POLLING_NRFLAG);
|
polling = !!(current_thread_info()->status & TS_POLLING);
|
||||||
if (polling) {
|
if (polling) {
|
||||||
clear_thread_flag(TIF_POLLING_NRFLAG);
|
current_thread_info()->status &= ~TS_POLLING;
|
||||||
smp_mb__after_clear_bit();
|
smp_mb__after_clear_bit();
|
||||||
}
|
}
|
||||||
if (!need_resched()) {
|
if (!need_resched()) {
|
||||||
@@ -774,7 +774,7 @@ static int apm_do_idle(void)
|
|||||||
ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax);
|
ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax);
|
||||||
}
|
}
|
||||||
if (polling)
|
if (polling)
|
||||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
current_thread_info()->status |= TS_POLLING;
|
||||||
|
|
||||||
if (!idled)
|
if (!idled)
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
* to extract and format the required data.
|
* to extract and format the required data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/crypto.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/signal.h>
|
#include <linux/signal.h>
|
||||||
#include <linux/personality.h>
|
#include <linux/personality.h>
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
#include <asm/fixmap.h>
|
#include <asm/fixmap.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/thread_info.h>
|
#include <asm/thread_info.h>
|
||||||
|
#include <asm/elf.h>
|
||||||
|
|
||||||
#define DEFINE(sym, val) \
|
#define DEFINE(sym, val) \
|
||||||
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
|
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
|
||||||
@@ -53,6 +55,7 @@ void foo(void)
|
|||||||
OFFSET(TI_preempt_count, thread_info, preempt_count);
|
OFFSET(TI_preempt_count, thread_info, preempt_count);
|
||||||
OFFSET(TI_addr_limit, thread_info, addr_limit);
|
OFFSET(TI_addr_limit, thread_info, addr_limit);
|
||||||
OFFSET(TI_restart_block, thread_info, restart_block);
|
OFFSET(TI_restart_block, thread_info, restart_block);
|
||||||
|
OFFSET(TI_sysenter_return, thread_info, sysenter_return);
|
||||||
BLANK();
|
BLANK();
|
||||||
|
|
||||||
OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
|
OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
|
||||||
@@ -68,5 +71,7 @@ void foo(void)
|
|||||||
sizeof(struct tss_struct));
|
sizeof(struct tss_struct));
|
||||||
|
|
||||||
DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
|
DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
|
||||||
DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL));
|
DEFINE(VDSO_PRELINK, VDSO_PRELINK);
|
||||||
|
|
||||||
|
OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
|
||||||
}
|
}
|
||||||
|
@@ -224,22 +224,26 @@ static void __init init_amd(struct cpuinfo_x86 *c)
|
|||||||
|
|
||||||
#ifdef CONFIG_X86_HT
|
#ifdef CONFIG_X86_HT
|
||||||
/*
|
/*
|
||||||
* On a AMD dual core setup the lower bits of the APIC id
|
* On a AMD multi core setup the lower bits of the APIC id
|
||||||
* distingush the cores. Assumes number of cores is a power
|
* distingush the cores.
|
||||||
* of two.
|
|
||||||
*/
|
*/
|
||||||
if (c->x86_max_cores > 1) {
|
if (c->x86_max_cores > 1) {
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
unsigned bits = 0;
|
unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf;
|
||||||
while ((1 << bits) < c->x86_max_cores)
|
|
||||||
bits++;
|
if (bits == 0) {
|
||||||
cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
|
while ((1 << bits) < c->x86_max_cores)
|
||||||
phys_proc_id[cpu] >>= bits;
|
bits++;
|
||||||
|
}
|
||||||
|
c->cpu_core_id = c->phys_proc_id & ((1<<bits)-1);
|
||||||
|
c->phys_proc_id >>= bits;
|
||||||
printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
|
printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
|
||||||
cpu, c->x86_max_cores, cpu_core_id[cpu]);
|
cpu, c->x86_max_cores, c->cpu_core_id);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (cpuid_eax(0x80000000) >= 0x80000006)
|
||||||
|
num_cache_leaves = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
|
static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
|
||||||
|
@@ -294,7 +294,7 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c)
|
|||||||
if (c->x86 >= 0x6)
|
if (c->x86 >= 0x6)
|
||||||
c->x86_model += ((tfms >> 16) & 0xF) << 4;
|
c->x86_model += ((tfms >> 16) & 0xF) << 4;
|
||||||
c->x86_mask = tfms & 15;
|
c->x86_mask = tfms & 15;
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_X86_HT
|
||||||
c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
|
c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
|
||||||
#else
|
#else
|
||||||
c->apicid = (ebx >> 24) & 0xFF;
|
c->apicid = (ebx >> 24) & 0xFF;
|
||||||
@@ -319,7 +319,7 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c)
|
|||||||
early_intel_workaround(c);
|
early_intel_workaround(c);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_HT
|
#ifdef CONFIG_X86_HT
|
||||||
phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
|
c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,11 +477,9 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
|||||||
{
|
{
|
||||||
u32 eax, ebx, ecx, edx;
|
u32 eax, ebx, ecx, edx;
|
||||||
int index_msb, core_bits;
|
int index_msb, core_bits;
|
||||||
int cpu = smp_processor_id();
|
|
||||||
|
|
||||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
|
|
||||||
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
|
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -492,16 +490,17 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
|||||||
} else if (smp_num_siblings > 1 ) {
|
} else if (smp_num_siblings > 1 ) {
|
||||||
|
|
||||||
if (smp_num_siblings > NR_CPUS) {
|
if (smp_num_siblings > NR_CPUS) {
|
||||||
printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
|
printk(KERN_WARNING "CPU: Unsupported number of the "
|
||||||
|
"siblings %d", smp_num_siblings);
|
||||||
smp_num_siblings = 1;
|
smp_num_siblings = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
index_msb = get_count_order(smp_num_siblings);
|
index_msb = get_count_order(smp_num_siblings);
|
||||||
phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
|
c->phys_proc_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
|
||||||
|
|
||||||
printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
|
printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
|
||||||
phys_proc_id[cpu]);
|
c->phys_proc_id);
|
||||||
|
|
||||||
smp_num_siblings = smp_num_siblings / c->x86_max_cores;
|
smp_num_siblings = smp_num_siblings / c->x86_max_cores;
|
||||||
|
|
||||||
@@ -509,12 +508,12 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
|||||||
|
|
||||||
core_bits = get_count_order(c->x86_max_cores);
|
core_bits = get_count_order(c->x86_max_cores);
|
||||||
|
|
||||||
cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
|
c->cpu_core_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
|
||||||
((1 << core_bits) - 1);
|
((1 << core_bits) - 1);
|
||||||
|
|
||||||
if (c->x86_max_cores > 1)
|
if (c->x86_max_cores > 1)
|
||||||
printk(KERN_INFO "CPU: Processor Core ID: %d\n",
|
printk(KERN_INFO "CPU: Processor Core ID: %d\n",
|
||||||
cpu_core_id[cpu]);
|
c->cpu_core_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -613,6 +612,12 @@ void __cpuinit cpu_init(void)
|
|||||||
set_in_cr4(X86_CR4_TSD);
|
set_in_cr4(X86_CR4_TSD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The CPU hotplug case */
|
||||||
|
if (cpu_gdt_descr->address) {
|
||||||
|
gdt = (struct desc_struct *)cpu_gdt_descr->address;
|
||||||
|
memset(gdt, 0, PAGE_SIZE);
|
||||||
|
goto old_gdt;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* This is a horrible hack to allocate the GDT. The problem
|
* This is a horrible hack to allocate the GDT. The problem
|
||||||
* is that cpu_init() is called really early for the boot CPU
|
* is that cpu_init() is called really early for the boot CPU
|
||||||
@@ -631,7 +636,7 @@ void __cpuinit cpu_init(void)
|
|||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
old_gdt:
|
||||||
/*
|
/*
|
||||||
* Initialize the per-CPU GDT with the boot GDT,
|
* Initialize the per-CPU GDT with the boot GDT,
|
||||||
* and set up the GDT descriptor:
|
* and set up the GDT descriptor:
|
||||||
|
@@ -354,7 +354,7 @@ static void __init init_nsc(struct cpuinfo_x86 *c)
|
|||||||
* This function only handles the GX processor, and kicks every
|
* This function only handles the GX processor, and kicks every
|
||||||
* thing else to the Cyrix init function above - that should
|
* thing else to the Cyrix init function above - that should
|
||||||
* cover any processors that might have been branded differently
|
* cover any processors that might have been branded differently
|
||||||
* after NSC aquired Cyrix.
|
* after NSC acquired Cyrix.
|
||||||
*
|
*
|
||||||
* If this breaks your GX1 horribly, please e-mail
|
* If this breaks your GX1 horribly, please e-mail
|
||||||
* info-linux@ldcmail.amd.com to tell us.
|
* info-linux@ldcmail.amd.com to tell us.
|
||||||
|
@@ -122,6 +122,12 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
|
|||||||
|
|
||||||
select_idle_routine(c);
|
select_idle_routine(c);
|
||||||
l2 = init_intel_cacheinfo(c);
|
l2 = init_intel_cacheinfo(c);
|
||||||
|
if (c->cpuid_level > 9 ) {
|
||||||
|
unsigned eax = cpuid_eax(10);
|
||||||
|
/* Check for version and the number of counters */
|
||||||
|
if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
|
||||||
|
set_bit(X86_FEATURE_ARCH_PERFMON, c->x86_capability);
|
||||||
|
}
|
||||||
|
|
||||||
/* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */
|
/* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */
|
||||||
if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
|
if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
* Changes:
|
* Changes:
|
||||||
* Venkatesh Pallipadi : Adding cache identification through cpuid(4)
|
* Venkatesh Pallipadi : Adding cache identification through cpuid(4)
|
||||||
* Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure.
|
* Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure.
|
||||||
|
* Andi Kleen : CPUID4 emulation on AMD.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@@ -130,25 +131,111 @@ struct _cpuid4_info {
|
|||||||
cpumask_t shared_cpu_map;
|
cpumask_t shared_cpu_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned short num_cache_leaves;
|
unsigned short num_cache_leaves;
|
||||||
|
|
||||||
|
/* AMD doesn't have CPUID4. Emulate it here to report the same
|
||||||
|
information to the user. This makes some assumptions about the machine:
|
||||||
|
No L3, L2 not shared, no SMT etc. that is currently true on AMD CPUs.
|
||||||
|
|
||||||
|
In theory the TLBs could be reported as fake type (they are in "dummy").
|
||||||
|
Maybe later */
|
||||||
|
union l1_cache {
|
||||||
|
struct {
|
||||||
|
unsigned line_size : 8;
|
||||||
|
unsigned lines_per_tag : 8;
|
||||||
|
unsigned assoc : 8;
|
||||||
|
unsigned size_in_kb : 8;
|
||||||
|
};
|
||||||
|
unsigned val;
|
||||||
|
};
|
||||||
|
|
||||||
|
union l2_cache {
|
||||||
|
struct {
|
||||||
|
unsigned line_size : 8;
|
||||||
|
unsigned lines_per_tag : 4;
|
||||||
|
unsigned assoc : 4;
|
||||||
|
unsigned size_in_kb : 16;
|
||||||
|
};
|
||||||
|
unsigned val;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned short assocs[] = {
|
||||||
|
[1] = 1, [2] = 2, [4] = 4, [6] = 8,
|
||||||
|
[8] = 16,
|
||||||
|
[0xf] = 0xffff // ??
|
||||||
|
};
|
||||||
|
static const unsigned char levels[] = { 1, 1, 2 };
|
||||||
|
static const unsigned char types[] = { 1, 2, 3 };
|
||||||
|
|
||||||
|
static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
|
||||||
|
union _cpuid4_leaf_ebx *ebx,
|
||||||
|
union _cpuid4_leaf_ecx *ecx)
|
||||||
|
{
|
||||||
|
unsigned dummy;
|
||||||
|
unsigned line_size, lines_per_tag, assoc, size_in_kb;
|
||||||
|
union l1_cache l1i, l1d;
|
||||||
|
union l2_cache l2;
|
||||||
|
|
||||||
|
eax->full = 0;
|
||||||
|
ebx->full = 0;
|
||||||
|
ecx->full = 0;
|
||||||
|
|
||||||
|
cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val);
|
||||||
|
cpuid(0x80000006, &dummy, &dummy, &l2.val, &dummy);
|
||||||
|
|
||||||
|
if (leaf > 2 || !l1d.val || !l1i.val || !l2.val)
|
||||||
|
return;
|
||||||
|
|
||||||
|
eax->split.is_self_initializing = 1;
|
||||||
|
eax->split.type = types[leaf];
|
||||||
|
eax->split.level = levels[leaf];
|
||||||
|
eax->split.num_threads_sharing = 0;
|
||||||
|
eax->split.num_cores_on_die = current_cpu_data.x86_max_cores - 1;
|
||||||
|
|
||||||
|
if (leaf <= 1) {
|
||||||
|
union l1_cache *l1 = leaf == 0 ? &l1d : &l1i;
|
||||||
|
assoc = l1->assoc;
|
||||||
|
line_size = l1->line_size;
|
||||||
|
lines_per_tag = l1->lines_per_tag;
|
||||||
|
size_in_kb = l1->size_in_kb;
|
||||||
|
} else {
|
||||||
|
assoc = l2.assoc;
|
||||||
|
line_size = l2.line_size;
|
||||||
|
lines_per_tag = l2.lines_per_tag;
|
||||||
|
/* cpu_data has errata corrections for K7 applied */
|
||||||
|
size_in_kb = current_cpu_data.x86_cache_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assoc == 0xf)
|
||||||
|
eax->split.is_fully_associative = 1;
|
||||||
|
ebx->split.coherency_line_size = line_size - 1;
|
||||||
|
ebx->split.ways_of_associativity = assocs[assoc] - 1;
|
||||||
|
ebx->split.physical_line_partition = lines_per_tag - 1;
|
||||||
|
ecx->split.number_of_sets = (size_in_kb * 1024) / line_size /
|
||||||
|
(ebx->split.ways_of_associativity + 1) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
|
static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
|
||||||
{
|
{
|
||||||
unsigned int eax, ebx, ecx, edx;
|
union _cpuid4_leaf_eax eax;
|
||||||
union _cpuid4_leaf_eax cache_eax;
|
union _cpuid4_leaf_ebx ebx;
|
||||||
|
union _cpuid4_leaf_ecx ecx;
|
||||||
|
unsigned edx;
|
||||||
|
|
||||||
cpuid_count(4, index, &eax, &ebx, &ecx, &edx);
|
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
|
||||||
cache_eax.full = eax;
|
amd_cpuid4(index, &eax, &ebx, &ecx);
|
||||||
if (cache_eax.split.type == CACHE_TYPE_NULL)
|
else
|
||||||
|
cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
|
||||||
|
if (eax.split.type == CACHE_TYPE_NULL)
|
||||||
return -EIO; /* better error ? */
|
return -EIO; /* better error ? */
|
||||||
|
|
||||||
this_leaf->eax.full = eax;
|
this_leaf->eax = eax;
|
||||||
this_leaf->ebx.full = ebx;
|
this_leaf->ebx = ebx;
|
||||||
this_leaf->ecx.full = ecx;
|
this_leaf->ecx = ecx;
|
||||||
this_leaf->size = (this_leaf->ecx.split.number_of_sets + 1) *
|
this_leaf->size = (ecx.split.number_of_sets + 1) *
|
||||||
(this_leaf->ebx.split.coherency_line_size + 1) *
|
(ebx.split.coherency_line_size + 1) *
|
||||||
(this_leaf->ebx.split.physical_line_partition + 1) *
|
(ebx.split.physical_line_partition + 1) *
|
||||||
(this_leaf->ebx.split.ways_of_associativity + 1);
|
(ebx.split.ways_of_associativity + 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +261,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
|
|||||||
unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
|
unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
|
||||||
unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
|
unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
|
||||||
unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
|
unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_X86_HT
|
||||||
unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data);
|
unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -296,14 +383,14 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
|
|||||||
|
|
||||||
if (new_l2) {
|
if (new_l2) {
|
||||||
l2 = new_l2;
|
l2 = new_l2;
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_X86_HT
|
||||||
cpu_llc_id[cpu] = l2_id;
|
cpu_llc_id[cpu] = l2_id;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_l3) {
|
if (new_l3) {
|
||||||
l3 = new_l3;
|
l3 = new_l3;
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_X86_HT
|
||||||
cpu_llc_id[cpu] = l3_id;
|
cpu_llc_id[cpu] = l3_id;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -642,7 +729,7 @@ static void __cpuexit cache_remove_dev(struct sys_device * sys_dev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cacheinfo_cpu_callback(struct notifier_block *nfb,
|
static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
|
||||||
unsigned long action, void *hcpu)
|
unsigned long action, void *hcpu)
|
||||||
{
|
{
|
||||||
unsigned int cpu = (unsigned long)hcpu;
|
unsigned int cpu = (unsigned long)hcpu;
|
||||||
@@ -660,7 +747,7 @@ static int cacheinfo_cpu_callback(struct notifier_block *nfb,
|
|||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct notifier_block cacheinfo_cpu_notifier =
|
static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier =
|
||||||
{
|
{
|
||||||
.notifier_call = cacheinfo_cpu_callback,
|
.notifier_call = cacheinfo_cpu_callback,
|
||||||
};
|
};
|
||||||
|
@@ -18,7 +18,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||||||
* applications want to get the raw CPUID data, they should access
|
* applications want to get the raw CPUID data, they should access
|
||||||
* /dev/cpu/<cpu_nr>/cpuid instead.
|
* /dev/cpu/<cpu_nr>/cpuid instead.
|
||||||
*/
|
*/
|
||||||
static char *x86_cap_flags[] = {
|
static const char * const x86_cap_flags[] = {
|
||||||
/* Intel-defined */
|
/* Intel-defined */
|
||||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||||
"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
|
"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
|
||||||
@@ -62,7 +62,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
};
|
};
|
||||||
static char *x86_power_flags[] = {
|
static const char * const x86_power_flags[] = {
|
||||||
"ts", /* temperature sensor */
|
"ts", /* temperature sensor */
|
||||||
"fid", /* frequency id control */
|
"fid", /* frequency id control */
|
||||||
"vid", /* voltage id control */
|
"vid", /* voltage id control */
|
||||||
@@ -109,9 +109,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||||||
seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
|
seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
|
||||||
#ifdef CONFIG_X86_HT
|
#ifdef CONFIG_X86_HT
|
||||||
if (c->x86_max_cores * smp_num_siblings > 1) {
|
if (c->x86_max_cores * smp_num_siblings > 1) {
|
||||||
seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);
|
seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
|
||||||
seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n]));
|
seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n]));
|
||||||
seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]);
|
seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
|
||||||
seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
|
seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -183,7 +183,7 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac
|
|||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct notifier_block cpuid_class_cpu_notifier =
|
static struct notifier_block __cpuinitdata cpuid_class_cpu_notifier =
|
||||||
{
|
{
|
||||||
.notifier_call = cpuid_class_cpu_callback,
|
.notifier_call = cpuid_class_cpu_callback,
|
||||||
};
|
};
|
||||||
|
@@ -120,14 +120,9 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* By using the NMI code instead of a vector we just sneak thru the
|
|
||||||
* word generator coming out with just what we want. AND it does
|
|
||||||
* not matter if clustered_apic_mode is set or not.
|
|
||||||
*/
|
|
||||||
static void smp_send_nmi_allbutself(void)
|
static void smp_send_nmi_allbutself(void)
|
||||||
{
|
{
|
||||||
send_IPI_allbutself(APIC_DM_NMI);
|
send_IPI_allbutself(NMI_VECTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nmi_shootdown_cpus(void)
|
static void nmi_shootdown_cpus(void)
|
||||||
@@ -163,7 +158,7 @@ static void nmi_shootdown_cpus(void)
|
|||||||
void machine_crash_shutdown(struct pt_regs *regs)
|
void machine_crash_shutdown(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
/* This function is only called after the system
|
/* This function is only called after the system
|
||||||
* has paniced or is otherwise in a critical state.
|
* has panicked or is otherwise in a critical state.
|
||||||
* The minimum amount of code to allow a kexec'd kernel
|
* The minimum amount of code to allow a kexec'd kernel
|
||||||
* to run successfully needs to happen here.
|
* to run successfully needs to happen here.
|
||||||
*
|
*
|
||||||
|
@@ -48,6 +48,7 @@
|
|||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
|
#include <asm/dwarf2.h>
|
||||||
#include "irq_vectors.h"
|
#include "irq_vectors.h"
|
||||||
|
|
||||||
#define nr_syscalls ((syscall_table_size)/4)
|
#define nr_syscalls ((syscall_table_size)/4)
|
||||||
@@ -82,34 +83,76 @@ VM_MASK = 0x00020000
|
|||||||
#define resume_kernel restore_nocheck
|
#define resume_kernel restore_nocheck
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_VM86
|
||||||
|
#define resume_userspace_sig check_userspace
|
||||||
|
#else
|
||||||
|
#define resume_userspace_sig resume_userspace
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SAVE_ALL \
|
#define SAVE_ALL \
|
||||||
cld; \
|
cld; \
|
||||||
pushl %es; \
|
pushl %es; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4;\
|
||||||
|
/*CFI_REL_OFFSET es, 0;*/\
|
||||||
pushl %ds; \
|
pushl %ds; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4;\
|
||||||
|
/*CFI_REL_OFFSET ds, 0;*/\
|
||||||
pushl %eax; \
|
pushl %eax; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4;\
|
||||||
|
CFI_REL_OFFSET eax, 0;\
|
||||||
pushl %ebp; \
|
pushl %ebp; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4;\
|
||||||
|
CFI_REL_OFFSET ebp, 0;\
|
||||||
pushl %edi; \
|
pushl %edi; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4;\
|
||||||
|
CFI_REL_OFFSET edi, 0;\
|
||||||
pushl %esi; \
|
pushl %esi; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4;\
|
||||||
|
CFI_REL_OFFSET esi, 0;\
|
||||||
pushl %edx; \
|
pushl %edx; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4;\
|
||||||
|
CFI_REL_OFFSET edx, 0;\
|
||||||
pushl %ecx; \
|
pushl %ecx; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4;\
|
||||||
|
CFI_REL_OFFSET ecx, 0;\
|
||||||
pushl %ebx; \
|
pushl %ebx; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4;\
|
||||||
|
CFI_REL_OFFSET ebx, 0;\
|
||||||
movl $(__USER_DS), %edx; \
|
movl $(__USER_DS), %edx; \
|
||||||
movl %edx, %ds; \
|
movl %edx, %ds; \
|
||||||
movl %edx, %es;
|
movl %edx, %es;
|
||||||
|
|
||||||
#define RESTORE_INT_REGS \
|
#define RESTORE_INT_REGS \
|
||||||
popl %ebx; \
|
popl %ebx; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4;\
|
||||||
|
CFI_RESTORE ebx;\
|
||||||
popl %ecx; \
|
popl %ecx; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4;\
|
||||||
|
CFI_RESTORE ecx;\
|
||||||
popl %edx; \
|
popl %edx; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4;\
|
||||||
|
CFI_RESTORE edx;\
|
||||||
popl %esi; \
|
popl %esi; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4;\
|
||||||
|
CFI_RESTORE esi;\
|
||||||
popl %edi; \
|
popl %edi; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4;\
|
||||||
|
CFI_RESTORE edi;\
|
||||||
popl %ebp; \
|
popl %ebp; \
|
||||||
popl %eax
|
CFI_ADJUST_CFA_OFFSET -4;\
|
||||||
|
CFI_RESTORE ebp;\
|
||||||
|
popl %eax; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4;\
|
||||||
|
CFI_RESTORE eax
|
||||||
|
|
||||||
#define RESTORE_REGS \
|
#define RESTORE_REGS \
|
||||||
RESTORE_INT_REGS; \
|
RESTORE_INT_REGS; \
|
||||||
1: popl %ds; \
|
1: popl %ds; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4;\
|
||||||
|
/*CFI_RESTORE ds;*/\
|
||||||
2: popl %es; \
|
2: popl %es; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4;\
|
||||||
|
/*CFI_RESTORE es;*/\
|
||||||
.section .fixup,"ax"; \
|
.section .fixup,"ax"; \
|
||||||
3: movl $0,(%esp); \
|
3: movl $0,(%esp); \
|
||||||
jmp 1b; \
|
jmp 1b; \
|
||||||
@@ -122,13 +165,43 @@ VM_MASK = 0x00020000
|
|||||||
.long 2b,4b; \
|
.long 2b,4b; \
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
|
#define RING0_INT_FRAME \
|
||||||
|
CFI_STARTPROC simple;\
|
||||||
|
CFI_DEF_CFA esp, 3*4;\
|
||||||
|
/*CFI_OFFSET cs, -2*4;*/\
|
||||||
|
CFI_OFFSET eip, -3*4
|
||||||
|
|
||||||
|
#define RING0_EC_FRAME \
|
||||||
|
CFI_STARTPROC simple;\
|
||||||
|
CFI_DEF_CFA esp, 4*4;\
|
||||||
|
/*CFI_OFFSET cs, -2*4;*/\
|
||||||
|
CFI_OFFSET eip, -3*4
|
||||||
|
|
||||||
|
#define RING0_PTREGS_FRAME \
|
||||||
|
CFI_STARTPROC simple;\
|
||||||
|
CFI_DEF_CFA esp, OLDESP-EBX;\
|
||||||
|
/*CFI_OFFSET cs, CS-OLDESP;*/\
|
||||||
|
CFI_OFFSET eip, EIP-OLDESP;\
|
||||||
|
/*CFI_OFFSET es, ES-OLDESP;*/\
|
||||||
|
/*CFI_OFFSET ds, DS-OLDESP;*/\
|
||||||
|
CFI_OFFSET eax, EAX-OLDESP;\
|
||||||
|
CFI_OFFSET ebp, EBP-OLDESP;\
|
||||||
|
CFI_OFFSET edi, EDI-OLDESP;\
|
||||||
|
CFI_OFFSET esi, ESI-OLDESP;\
|
||||||
|
CFI_OFFSET edx, EDX-OLDESP;\
|
||||||
|
CFI_OFFSET ecx, ECX-OLDESP;\
|
||||||
|
CFI_OFFSET ebx, EBX-OLDESP
|
||||||
|
|
||||||
ENTRY(ret_from_fork)
|
ENTRY(ret_from_fork)
|
||||||
|
CFI_STARTPROC
|
||||||
pushl %eax
|
pushl %eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4
|
||||||
call schedule_tail
|
call schedule_tail
|
||||||
GET_THREAD_INFO(%ebp)
|
GET_THREAD_INFO(%ebp)
|
||||||
popl %eax
|
popl %eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4
|
||||||
jmp syscall_exit
|
jmp syscall_exit
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return to user mode is not as complex as all this looks,
|
* Return to user mode is not as complex as all this looks,
|
||||||
@@ -139,10 +212,12 @@ ENTRY(ret_from_fork)
|
|||||||
|
|
||||||
# userspace resumption stub bypassing syscall exit tracing
|
# userspace resumption stub bypassing syscall exit tracing
|
||||||
ALIGN
|
ALIGN
|
||||||
|
RING0_PTREGS_FRAME
|
||||||
ret_from_exception:
|
ret_from_exception:
|
||||||
preempt_stop
|
preempt_stop
|
||||||
ret_from_intr:
|
ret_from_intr:
|
||||||
GET_THREAD_INFO(%ebp)
|
GET_THREAD_INFO(%ebp)
|
||||||
|
check_userspace:
|
||||||
movl EFLAGS(%esp), %eax # mix EFLAGS and CS
|
movl EFLAGS(%esp), %eax # mix EFLAGS and CS
|
||||||
movb CS(%esp), %al
|
movb CS(%esp), %al
|
||||||
testl $(VM_MASK | 3), %eax
|
testl $(VM_MASK | 3), %eax
|
||||||
@@ -171,20 +246,38 @@ need_resched:
|
|||||||
call preempt_schedule_irq
|
call preempt_schedule_irq
|
||||||
jmp need_resched
|
jmp need_resched
|
||||||
#endif
|
#endif
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
/* SYSENTER_RETURN points to after the "sysenter" instruction in
|
/* SYSENTER_RETURN points to after the "sysenter" instruction in
|
||||||
the vsyscall page. See vsyscall-sysentry.S, which defines the symbol. */
|
the vsyscall page. See vsyscall-sysentry.S, which defines the symbol. */
|
||||||
|
|
||||||
# sysenter call handler stub
|
# sysenter call handler stub
|
||||||
ENTRY(sysenter_entry)
|
ENTRY(sysenter_entry)
|
||||||
|
CFI_STARTPROC simple
|
||||||
|
CFI_DEF_CFA esp, 0
|
||||||
|
CFI_REGISTER esp, ebp
|
||||||
movl TSS_sysenter_esp0(%esp),%esp
|
movl TSS_sysenter_esp0(%esp),%esp
|
||||||
sysenter_past_esp:
|
sysenter_past_esp:
|
||||||
sti
|
sti
|
||||||
pushl $(__USER_DS)
|
pushl $(__USER_DS)
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
/*CFI_REL_OFFSET ss, 0*/
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
CFI_REL_OFFSET esp, 0
|
||||||
pushfl
|
pushfl
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
pushl $(__USER_CS)
|
pushl $(__USER_CS)
|
||||||
pushl $SYSENTER_RETURN
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
/*CFI_REL_OFFSET cs, 0*/
|
||||||
|
/*
|
||||||
|
* Push current_thread_info()->sysenter_return to the stack.
|
||||||
|
* A tiny bit of offset fixup is necessary - 4*4 means the 4 words
|
||||||
|
* pushed above; +8 corresponds to copy_thread's esp0 setting.
|
||||||
|
*/
|
||||||
|
pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
CFI_REL_OFFSET eip, 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load the potential sixth argument from user stack.
|
* Load the potential sixth argument from user stack.
|
||||||
@@ -199,6 +292,7 @@ sysenter_past_esp:
|
|||||||
.previous
|
.previous
|
||||||
|
|
||||||
pushl %eax
|
pushl %eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
GET_THREAD_INFO(%ebp)
|
GET_THREAD_INFO(%ebp)
|
||||||
|
|
||||||
@@ -219,11 +313,14 @@ sysenter_past_esp:
|
|||||||
xorl %ebp,%ebp
|
xorl %ebp,%ebp
|
||||||
sti
|
sti
|
||||||
sysexit
|
sysexit
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
|
|
||||||
# system call handler stub
|
# system call handler stub
|
||||||
ENTRY(system_call)
|
ENTRY(system_call)
|
||||||
|
RING0_INT_FRAME # can't unwind into user space anyway
|
||||||
pushl %eax # save orig_eax
|
pushl %eax # save orig_eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
GET_THREAD_INFO(%ebp)
|
GET_THREAD_INFO(%ebp)
|
||||||
testl $TF_MASK,EFLAGS(%esp)
|
testl $TF_MASK,EFLAGS(%esp)
|
||||||
@@ -256,10 +353,12 @@ restore_all:
|
|||||||
movb CS(%esp), %al
|
movb CS(%esp), %al
|
||||||
andl $(VM_MASK | (4 << 8) | 3), %eax
|
andl $(VM_MASK | (4 << 8) | 3), %eax
|
||||||
cmpl $((4 << 8) | 3), %eax
|
cmpl $((4 << 8) | 3), %eax
|
||||||
|
CFI_REMEMBER_STATE
|
||||||
je ldt_ss # returning to user-space with LDT SS
|
je ldt_ss # returning to user-space with LDT SS
|
||||||
restore_nocheck:
|
restore_nocheck:
|
||||||
RESTORE_REGS
|
RESTORE_REGS
|
||||||
addl $4, %esp
|
addl $4, %esp
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4
|
||||||
1: iret
|
1: iret
|
||||||
.section .fixup,"ax"
|
.section .fixup,"ax"
|
||||||
iret_exc:
|
iret_exc:
|
||||||
@@ -273,6 +372,7 @@ iret_exc:
|
|||||||
.long 1b,iret_exc
|
.long 1b,iret_exc
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
|
CFI_RESTORE_STATE
|
||||||
ldt_ss:
|
ldt_ss:
|
||||||
larl OLDSS(%esp), %eax
|
larl OLDSS(%esp), %eax
|
||||||
jnz restore_nocheck
|
jnz restore_nocheck
|
||||||
@@ -285,11 +385,13 @@ ldt_ss:
|
|||||||
* CPUs, which we can try to work around to make
|
* CPUs, which we can try to work around to make
|
||||||
* dosemu and wine happy. */
|
* dosemu and wine happy. */
|
||||||
subl $8, %esp # reserve space for switch16 pointer
|
subl $8, %esp # reserve space for switch16 pointer
|
||||||
|
CFI_ADJUST_CFA_OFFSET 8
|
||||||
cli
|
cli
|
||||||
movl %esp, %eax
|
movl %esp, %eax
|
||||||
/* Set up the 16bit stack frame with switch32 pointer on top,
|
/* Set up the 16bit stack frame with switch32 pointer on top,
|
||||||
* and a switch16 pointer on top of the current frame. */
|
* and a switch16 pointer on top of the current frame. */
|
||||||
call setup_x86_bogus_stack
|
call setup_x86_bogus_stack
|
||||||
|
CFI_ADJUST_CFA_OFFSET -8 # frame has moved
|
||||||
RESTORE_REGS
|
RESTORE_REGS
|
||||||
lss 20+4(%esp), %esp # switch to 16bit stack
|
lss 20+4(%esp), %esp # switch to 16bit stack
|
||||||
1: iret
|
1: iret
|
||||||
@@ -297,9 +399,11 @@ ldt_ss:
|
|||||||
.align 4
|
.align 4
|
||||||
.long 1b,iret_exc
|
.long 1b,iret_exc
|
||||||
.previous
|
.previous
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
# perform work that needs to be done immediately before resumption
|
# perform work that needs to be done immediately before resumption
|
||||||
ALIGN
|
ALIGN
|
||||||
|
RING0_PTREGS_FRAME # can't unwind into user space anyway
|
||||||
work_pending:
|
work_pending:
|
||||||
testb $_TIF_NEED_RESCHED, %cl
|
testb $_TIF_NEED_RESCHED, %cl
|
||||||
jz work_notifysig
|
jz work_notifysig
|
||||||
@@ -323,18 +427,20 @@ work_notifysig: # deal with pending signals and
|
|||||||
# vm86-space
|
# vm86-space
|
||||||
xorl %edx, %edx
|
xorl %edx, %edx
|
||||||
call do_notify_resume
|
call do_notify_resume
|
||||||
jmp resume_userspace
|
jmp resume_userspace_sig
|
||||||
|
|
||||||
ALIGN
|
ALIGN
|
||||||
work_notifysig_v86:
|
work_notifysig_v86:
|
||||||
#ifdef CONFIG_VM86
|
#ifdef CONFIG_VM86
|
||||||
pushl %ecx # save ti_flags for do_notify_resume
|
pushl %ecx # save ti_flags for do_notify_resume
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
call save_v86_state # %eax contains pt_regs pointer
|
call save_v86_state # %eax contains pt_regs pointer
|
||||||
popl %ecx
|
popl %ecx
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4
|
||||||
movl %eax, %esp
|
movl %eax, %esp
|
||||||
xorl %edx, %edx
|
xorl %edx, %edx
|
||||||
call do_notify_resume
|
call do_notify_resume
|
||||||
jmp resume_userspace
|
jmp resume_userspace_sig
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# perform syscall exit tracing
|
# perform syscall exit tracing
|
||||||
@@ -363,19 +469,21 @@ syscall_exit_work:
|
|||||||
movl $1, %edx
|
movl $1, %edx
|
||||||
call do_syscall_trace
|
call do_syscall_trace
|
||||||
jmp resume_userspace
|
jmp resume_userspace
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
ALIGN
|
RING0_INT_FRAME # can't unwind into user space anyway
|
||||||
syscall_fault:
|
syscall_fault:
|
||||||
pushl %eax # save orig_eax
|
pushl %eax # save orig_eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
GET_THREAD_INFO(%ebp)
|
GET_THREAD_INFO(%ebp)
|
||||||
movl $-EFAULT,EAX(%esp)
|
movl $-EFAULT,EAX(%esp)
|
||||||
jmp resume_userspace
|
jmp resume_userspace
|
||||||
|
|
||||||
ALIGN
|
|
||||||
syscall_badsys:
|
syscall_badsys:
|
||||||
movl $-ENOSYS,EAX(%esp)
|
movl $-ENOSYS,EAX(%esp)
|
||||||
jmp resume_userspace
|
jmp resume_userspace
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
#define FIXUP_ESPFIX_STACK \
|
#define FIXUP_ESPFIX_STACK \
|
||||||
movl %esp, %eax; \
|
movl %esp, %eax; \
|
||||||
@@ -387,16 +495,21 @@ syscall_badsys:
|
|||||||
movl %eax, %esp;
|
movl %eax, %esp;
|
||||||
#define UNWIND_ESPFIX_STACK \
|
#define UNWIND_ESPFIX_STACK \
|
||||||
pushl %eax; \
|
pushl %eax; \
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4; \
|
||||||
movl %ss, %eax; \
|
movl %ss, %eax; \
|
||||||
/* see if on 16bit stack */ \
|
/* see if on 16bit stack */ \
|
||||||
cmpw $__ESPFIX_SS, %ax; \
|
cmpw $__ESPFIX_SS, %ax; \
|
||||||
jne 28f; \
|
je 28f; \
|
||||||
movl $__KERNEL_DS, %edx; \
|
27: popl %eax; \
|
||||||
movl %edx, %ds; \
|
CFI_ADJUST_CFA_OFFSET -4; \
|
||||||
movl %edx, %es; \
|
.section .fixup,"ax"; \
|
||||||
|
28: movl $__KERNEL_DS, %eax; \
|
||||||
|
movl %eax, %ds; \
|
||||||
|
movl %eax, %es; \
|
||||||
/* switch to 32bit stack */ \
|
/* switch to 32bit stack */ \
|
||||||
FIXUP_ESPFIX_STACK \
|
FIXUP_ESPFIX_STACK; \
|
||||||
28: popl %eax;
|
jmp 27b; \
|
||||||
|
.previous
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build the entry stubs and pointer table with
|
* Build the entry stubs and pointer table with
|
||||||
@@ -408,9 +521,14 @@ ENTRY(interrupt)
|
|||||||
|
|
||||||
vector=0
|
vector=0
|
||||||
ENTRY(irq_entries_start)
|
ENTRY(irq_entries_start)
|
||||||
|
RING0_INT_FRAME
|
||||||
.rept NR_IRQS
|
.rept NR_IRQS
|
||||||
ALIGN
|
ALIGN
|
||||||
1: pushl $vector-256
|
.if vector
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4
|
||||||
|
.endif
|
||||||
|
1: pushl $~(vector)
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp common_interrupt
|
jmp common_interrupt
|
||||||
.data
|
.data
|
||||||
.long 1b
|
.long 1b
|
||||||
@@ -424,60 +542,99 @@ common_interrupt:
|
|||||||
movl %esp,%eax
|
movl %esp,%eax
|
||||||
call do_IRQ
|
call do_IRQ
|
||||||
jmp ret_from_intr
|
jmp ret_from_intr
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
#define BUILD_INTERRUPT(name, nr) \
|
#define BUILD_INTERRUPT(name, nr) \
|
||||||
ENTRY(name) \
|
ENTRY(name) \
|
||||||
pushl $nr-256; \
|
RING0_INT_FRAME; \
|
||||||
SAVE_ALL \
|
pushl $~(nr); \
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4; \
|
||||||
|
SAVE_ALL; \
|
||||||
movl %esp,%eax; \
|
movl %esp,%eax; \
|
||||||
call smp_/**/name; \
|
call smp_/**/name; \
|
||||||
jmp ret_from_intr;
|
jmp ret_from_intr; \
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
/* The include is where all of the SMP etc. interrupts come from */
|
/* The include is where all of the SMP etc. interrupts come from */
|
||||||
#include "entry_arch.h"
|
#include "entry_arch.h"
|
||||||
|
|
||||||
ENTRY(divide_error)
|
ENTRY(divide_error)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl $0 # no error code
|
pushl $0 # no error code
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
pushl $do_divide_error
|
pushl $do_divide_error
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
ALIGN
|
ALIGN
|
||||||
error_code:
|
error_code:
|
||||||
pushl %ds
|
pushl %ds
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
/*CFI_REL_OFFSET ds, 0*/
|
||||||
pushl %eax
|
pushl %eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
CFI_REL_OFFSET eax, 0
|
||||||
xorl %eax, %eax
|
xorl %eax, %eax
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
CFI_REL_OFFSET ebp, 0
|
||||||
pushl %edi
|
pushl %edi
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
CFI_REL_OFFSET edi, 0
|
||||||
pushl %esi
|
pushl %esi
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
CFI_REL_OFFSET esi, 0
|
||||||
pushl %edx
|
pushl %edx
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
CFI_REL_OFFSET edx, 0
|
||||||
decl %eax # eax = -1
|
decl %eax # eax = -1
|
||||||
pushl %ecx
|
pushl %ecx
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
CFI_REL_OFFSET ecx, 0
|
||||||
pushl %ebx
|
pushl %ebx
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
CFI_REL_OFFSET ebx, 0
|
||||||
cld
|
cld
|
||||||
pushl %es
|
pushl %es
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
|
/*CFI_REL_OFFSET es, 0*/
|
||||||
UNWIND_ESPFIX_STACK
|
UNWIND_ESPFIX_STACK
|
||||||
popl %ecx
|
popl %ecx
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4
|
||||||
|
/*CFI_REGISTER es, ecx*/
|
||||||
movl ES(%esp), %edi # get the function address
|
movl ES(%esp), %edi # get the function address
|
||||||
movl ORIG_EAX(%esp), %edx # get the error code
|
movl ORIG_EAX(%esp), %edx # get the error code
|
||||||
movl %eax, ORIG_EAX(%esp)
|
movl %eax, ORIG_EAX(%esp)
|
||||||
movl %ecx, ES(%esp)
|
movl %ecx, ES(%esp)
|
||||||
|
/*CFI_REL_OFFSET es, ES*/
|
||||||
movl $(__USER_DS), %ecx
|
movl $(__USER_DS), %ecx
|
||||||
movl %ecx, %ds
|
movl %ecx, %ds
|
||||||
movl %ecx, %es
|
movl %ecx, %es
|
||||||
movl %esp,%eax # pt_regs pointer
|
movl %esp,%eax # pt_regs pointer
|
||||||
call *%edi
|
call *%edi
|
||||||
jmp ret_from_exception
|
jmp ret_from_exception
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
ENTRY(coprocessor_error)
|
ENTRY(coprocessor_error)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl $0
|
pushl $0
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
pushl $do_coprocessor_error
|
pushl $do_coprocessor_error
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
ENTRY(simd_coprocessor_error)
|
ENTRY(simd_coprocessor_error)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl $0
|
pushl $0
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
pushl $do_simd_coprocessor_error
|
pushl $do_simd_coprocessor_error
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
ENTRY(device_not_available)
|
ENTRY(device_not_available)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl $-1 # mark this as an int
|
pushl $-1 # mark this as an int
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
movl %cr0, %eax
|
movl %cr0, %eax
|
||||||
testl $0x4, %eax # EM (math emulation bit)
|
testl $0x4, %eax # EM (math emulation bit)
|
||||||
@@ -487,9 +644,12 @@ ENTRY(device_not_available)
|
|||||||
jmp ret_from_exception
|
jmp ret_from_exception
|
||||||
device_not_available_emulate:
|
device_not_available_emulate:
|
||||||
pushl $0 # temporary storage for ORIG_EIP
|
pushl $0 # temporary storage for ORIG_EIP
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
call math_emulate
|
call math_emulate
|
||||||
addl $4, %esp
|
addl $4, %esp
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4
|
||||||
jmp ret_from_exception
|
jmp ret_from_exception
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Debug traps and NMI can happen at the one SYSENTER instruction
|
* Debug traps and NMI can happen at the one SYSENTER instruction
|
||||||
@@ -514,16 +674,19 @@ label: \
|
|||||||
pushl $sysenter_past_esp
|
pushl $sysenter_past_esp
|
||||||
|
|
||||||
KPROBE_ENTRY(debug)
|
KPROBE_ENTRY(debug)
|
||||||
|
RING0_INT_FRAME
|
||||||
cmpl $sysenter_entry,(%esp)
|
cmpl $sysenter_entry,(%esp)
|
||||||
jne debug_stack_correct
|
jne debug_stack_correct
|
||||||
FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
|
FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
|
||||||
debug_stack_correct:
|
debug_stack_correct:
|
||||||
pushl $-1 # mark this as an int
|
pushl $-1 # mark this as an int
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
xorl %edx,%edx # error code 0
|
xorl %edx,%edx # error code 0
|
||||||
movl %esp,%eax # pt_regs pointer
|
movl %esp,%eax # pt_regs pointer
|
||||||
call do_debug
|
call do_debug
|
||||||
jmp ret_from_exception
|
jmp ret_from_exception
|
||||||
|
CFI_ENDPROC
|
||||||
.previous .text
|
.previous .text
|
||||||
/*
|
/*
|
||||||
* NMI is doubly nasty. It can happen _while_ we're handling
|
* NMI is doubly nasty. It can happen _while_ we're handling
|
||||||
@@ -534,14 +697,18 @@ debug_stack_correct:
|
|||||||
* fault happened on the sysenter path.
|
* fault happened on the sysenter path.
|
||||||
*/
|
*/
|
||||||
ENTRY(nmi)
|
ENTRY(nmi)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl %eax
|
pushl %eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
movl %ss, %eax
|
movl %ss, %eax
|
||||||
cmpw $__ESPFIX_SS, %ax
|
cmpw $__ESPFIX_SS, %ax
|
||||||
popl %eax
|
popl %eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4
|
||||||
je nmi_16bit_stack
|
je nmi_16bit_stack
|
||||||
cmpl $sysenter_entry,(%esp)
|
cmpl $sysenter_entry,(%esp)
|
||||||
je nmi_stack_fixup
|
je nmi_stack_fixup
|
||||||
pushl %eax
|
pushl %eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
movl %esp,%eax
|
movl %esp,%eax
|
||||||
/* Do not access memory above the end of our stack page,
|
/* Do not access memory above the end of our stack page,
|
||||||
* it might not exist.
|
* it might not exist.
|
||||||
@@ -549,16 +716,19 @@ ENTRY(nmi)
|
|||||||
andl $(THREAD_SIZE-1),%eax
|
andl $(THREAD_SIZE-1),%eax
|
||||||
cmpl $(THREAD_SIZE-20),%eax
|
cmpl $(THREAD_SIZE-20),%eax
|
||||||
popl %eax
|
popl %eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET -4
|
||||||
jae nmi_stack_correct
|
jae nmi_stack_correct
|
||||||
cmpl $sysenter_entry,12(%esp)
|
cmpl $sysenter_entry,12(%esp)
|
||||||
je nmi_debug_stack_check
|
je nmi_debug_stack_check
|
||||||
nmi_stack_correct:
|
nmi_stack_correct:
|
||||||
pushl %eax
|
pushl %eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
xorl %edx,%edx # zero error code
|
xorl %edx,%edx # zero error code
|
||||||
movl %esp,%eax # pt_regs pointer
|
movl %esp,%eax # pt_regs pointer
|
||||||
call do_nmi
|
call do_nmi
|
||||||
jmp restore_all
|
jmp restore_all
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
nmi_stack_fixup:
|
nmi_stack_fixup:
|
||||||
FIX_STACK(12,nmi_stack_correct, 1)
|
FIX_STACK(12,nmi_stack_correct, 1)
|
||||||
@@ -574,94 +744,177 @@ nmi_debug_stack_check:
|
|||||||
jmp nmi_stack_correct
|
jmp nmi_stack_correct
|
||||||
|
|
||||||
nmi_16bit_stack:
|
nmi_16bit_stack:
|
||||||
|
RING0_INT_FRAME
|
||||||
/* create the pointer to lss back */
|
/* create the pointer to lss back */
|
||||||
pushl %ss
|
pushl %ss
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
pushl %esp
|
pushl %esp
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
movzwl %sp, %esp
|
movzwl %sp, %esp
|
||||||
addw $4, (%esp)
|
addw $4, (%esp)
|
||||||
/* copy the iret frame of 12 bytes */
|
/* copy the iret frame of 12 bytes */
|
||||||
.rept 3
|
.rept 3
|
||||||
pushl 16(%esp)
|
pushl 16(%esp)
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
.endr
|
.endr
|
||||||
pushl %eax
|
pushl %eax
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
FIXUP_ESPFIX_STACK # %eax == %esp
|
FIXUP_ESPFIX_STACK # %eax == %esp
|
||||||
|
CFI_ADJUST_CFA_OFFSET -20 # the frame has now moved
|
||||||
xorl %edx,%edx # zero error code
|
xorl %edx,%edx # zero error code
|
||||||
call do_nmi
|
call do_nmi
|
||||||
RESTORE_REGS
|
RESTORE_REGS
|
||||||
lss 12+4(%esp), %esp # back to 16bit stack
|
lss 12+4(%esp), %esp # back to 16bit stack
|
||||||
1: iret
|
1: iret
|
||||||
|
CFI_ENDPROC
|
||||||
.section __ex_table,"a"
|
.section __ex_table,"a"
|
||||||
.align 4
|
.align 4
|
||||||
.long 1b,iret_exc
|
.long 1b,iret_exc
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
KPROBE_ENTRY(int3)
|
KPROBE_ENTRY(int3)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl $-1 # mark this as an int
|
pushl $-1 # mark this as an int
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
xorl %edx,%edx # zero error code
|
xorl %edx,%edx # zero error code
|
||||||
movl %esp,%eax # pt_regs pointer
|
movl %esp,%eax # pt_regs pointer
|
||||||
call do_int3
|
call do_int3
|
||||||
jmp ret_from_exception
|
jmp ret_from_exception
|
||||||
|
CFI_ENDPROC
|
||||||
.previous .text
|
.previous .text
|
||||||
|
|
||||||
ENTRY(overflow)
|
ENTRY(overflow)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl $0
|
pushl $0
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
pushl $do_overflow
|
pushl $do_overflow
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
ENTRY(bounds)
|
ENTRY(bounds)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl $0
|
pushl $0
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
pushl $do_bounds
|
pushl $do_bounds
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
ENTRY(invalid_op)
|
ENTRY(invalid_op)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl $0
|
pushl $0
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
pushl $do_invalid_op
|
pushl $do_invalid_op
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
ENTRY(coprocessor_segment_overrun)
|
ENTRY(coprocessor_segment_overrun)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl $0
|
pushl $0
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
pushl $do_coprocessor_segment_overrun
|
pushl $do_coprocessor_segment_overrun
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
ENTRY(invalid_TSS)
|
ENTRY(invalid_TSS)
|
||||||
|
RING0_EC_FRAME
|
||||||
pushl $do_invalid_TSS
|
pushl $do_invalid_TSS
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
ENTRY(segment_not_present)
|
ENTRY(segment_not_present)
|
||||||
|
RING0_EC_FRAME
|
||||||
pushl $do_segment_not_present
|
pushl $do_segment_not_present
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
ENTRY(stack_segment)
|
ENTRY(stack_segment)
|
||||||
|
RING0_EC_FRAME
|
||||||
pushl $do_stack_segment
|
pushl $do_stack_segment
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
KPROBE_ENTRY(general_protection)
|
KPROBE_ENTRY(general_protection)
|
||||||
|
RING0_EC_FRAME
|
||||||
pushl $do_general_protection
|
pushl $do_general_protection
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
.previous .text
|
.previous .text
|
||||||
|
|
||||||
ENTRY(alignment_check)
|
ENTRY(alignment_check)
|
||||||
|
RING0_EC_FRAME
|
||||||
pushl $do_alignment_check
|
pushl $do_alignment_check
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
KPROBE_ENTRY(page_fault)
|
KPROBE_ENTRY(page_fault)
|
||||||
|
RING0_EC_FRAME
|
||||||
pushl $do_page_fault
|
pushl $do_page_fault
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
.previous .text
|
.previous .text
|
||||||
|
|
||||||
#ifdef CONFIG_X86_MCE
|
#ifdef CONFIG_X86_MCE
|
||||||
ENTRY(machine_check)
|
ENTRY(machine_check)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl $0
|
pushl $0
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
pushl machine_check_vector
|
pushl machine_check_vector
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ENTRY(spurious_interrupt_bug)
|
ENTRY(spurious_interrupt_bug)
|
||||||
|
RING0_INT_FRAME
|
||||||
pushl $0
|
pushl $0
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
pushl $do_spurious_interrupt_bug
|
pushl $do_spurious_interrupt_bug
|
||||||
|
CFI_ADJUST_CFA_OFFSET 4
|
||||||
jmp error_code
|
jmp error_code
|
||||||
|
CFI_ENDPROC
|
||||||
|
|
||||||
|
#ifdef CONFIG_STACK_UNWIND
|
||||||
|
ENTRY(arch_unwind_init_running)
|
||||||
|
CFI_STARTPROC
|
||||||
|
movl 4(%esp), %edx
|
||||||
|
movl (%esp), %ecx
|
||||||
|
leal 4(%esp), %eax
|
||||||
|
movl %ebx, EBX(%edx)
|
||||||
|
xorl %ebx, %ebx
|
||||||
|
movl %ebx, ECX(%edx)
|
||||||
|
movl %ebx, EDX(%edx)
|
||||||
|
movl %esi, ESI(%edx)
|
||||||
|
movl %edi, EDI(%edx)
|
||||||
|
movl %ebp, EBP(%edx)
|
||||||
|
movl %ebx, EAX(%edx)
|
||||||
|
movl $__USER_DS, DS(%edx)
|
||||||
|
movl $__USER_DS, ES(%edx)
|
||||||
|
movl %ebx, ORIG_EAX(%edx)
|
||||||
|
movl %ecx, EIP(%edx)
|
||||||
|
movl 12(%esp), %ecx
|
||||||
|
movl $__KERNEL_CS, CS(%edx)
|
||||||
|
movl %ebx, EFLAGS(%edx)
|
||||||
|
movl %eax, OLDESP(%edx)
|
||||||
|
movl 8(%esp), %eax
|
||||||
|
movl %ecx, 8(%esp)
|
||||||
|
movl EBX(%edx), %ebx
|
||||||
|
movl $__KERNEL_DS, OLDSS(%edx)
|
||||||
|
jmpl *%eax
|
||||||
|
CFI_ENDPROC
|
||||||
|
ENDPROC(arch_unwind_init_running)
|
||||||
|
#endif
|
||||||
|
|
||||||
.section .rodata,"a"
|
.section .rodata,"a"
|
||||||
#include "syscall_table.S"
|
#include "syscall_table.S"
|
||||||
|
67
arch/i386/kernel/hpet.c
Normal file
67
arch/i386/kernel/hpet.c
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include <linux/clocksource.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/hpet.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
|
||||||
|
#include <asm/hpet.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#define HPET_MASK CLOCKSOURCE_MASK(32)
|
||||||
|
#define HPET_SHIFT 22
|
||||||
|
|
||||||
|
/* FSEC = 10^-15 NSEC = 10^-9 */
|
||||||
|
#define FSEC_PER_NSEC 1000000
|
||||||
|
|
||||||
|
static void *hpet_ptr;
|
||||||
|
|
||||||
|
static cycle_t read_hpet(void)
|
||||||
|
{
|
||||||
|
return (cycle_t)readl(hpet_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct clocksource clocksource_hpet = {
|
||||||
|
.name = "hpet",
|
||||||
|
.rating = 250,
|
||||||
|
.read = read_hpet,
|
||||||
|
.mask = HPET_MASK,
|
||||||
|
.mult = 0, /* set below */
|
||||||
|
.shift = HPET_SHIFT,
|
||||||
|
.is_continuous = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init init_hpet_clocksource(void)
|
||||||
|
{
|
||||||
|
unsigned long hpet_period;
|
||||||
|
void __iomem* hpet_base;
|
||||||
|
u64 tmp;
|
||||||
|
|
||||||
|
if (!hpet_address)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/* calculate the hpet address: */
|
||||||
|
hpet_base =
|
||||||
|
(void __iomem*)ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
|
||||||
|
hpet_ptr = hpet_base + HPET_COUNTER;
|
||||||
|
|
||||||
|
/* calculate the frequency: */
|
||||||
|
hpet_period = readl(hpet_base + HPET_PERIOD);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hpet period is in femto seconds per cycle
|
||||||
|
* so we need to convert this to ns/cyc units
|
||||||
|
* aproximated by mult/2^shift
|
||||||
|
*
|
||||||
|
* fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
|
||||||
|
* fsec/cyc * 1ns/1000000fsec * 2^shift = mult
|
||||||
|
* fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
|
||||||
|
* (fsec/cyc << shift)/1000000 = mult
|
||||||
|
* (hpet_period << shift)/FSEC_PER_NSEC = mult
|
||||||
|
*/
|
||||||
|
tmp = (u64)hpet_period << HPET_SHIFT;
|
||||||
|
do_div(tmp, FSEC_PER_NSEC);
|
||||||
|
clocksource_hpet.mult = (u32)tmp;
|
||||||
|
|
||||||
|
return clocksource_register(&clocksource_hpet);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(init_hpet_clocksource);
|
118
arch/i386/kernel/i8253.c
Normal file
118
arch/i386/kernel/i8253.c
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* i8253.c 8253/PIT functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <linux/clocksource.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/sysdev.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
|
||||||
|
#include <asm/smp.h>
|
||||||
|
#include <asm/delay.h>
|
||||||
|
#include <asm/i8253.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#include "io_ports.h"
|
||||||
|
|
||||||
|
DEFINE_SPINLOCK(i8253_lock);
|
||||||
|
EXPORT_SYMBOL(i8253_lock);
|
||||||
|
|
||||||
|
void setup_pit_timer(void)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&i8253_lock, flags);
|
||||||
|
outb_p(0x34,PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */
|
||||||
|
udelay(10);
|
||||||
|
outb_p(LATCH & 0xff , PIT_CH0); /* LSB */
|
||||||
|
udelay(10);
|
||||||
|
outb(LATCH >> 8 , PIT_CH0); /* MSB */
|
||||||
|
spin_unlock_irqrestore(&i8253_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since the PIT overflows every tick, its not very useful
|
||||||
|
* to just read by itself. So use jiffies to emulate a free
|
||||||
|
* running counter:
|
||||||
|
*/
|
||||||
|
static cycle_t pit_read(void)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int count;
|
||||||
|
u32 jifs;
|
||||||
|
static int old_count;
|
||||||
|
static u32 old_jifs;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&i8253_lock, flags);
|
||||||
|
/*
|
||||||
|
* Although our caller may have the read side of xtime_lock,
|
||||||
|
* this is now a seqlock, and we are cheating in this routine
|
||||||
|
* by having side effects on state that we cannot undo if
|
||||||
|
* there is a collision on the seqlock and our caller has to
|
||||||
|
* retry. (Namely, old_jifs and old_count.) So we must treat
|
||||||
|
* jiffies as volatile despite the lock. We read jiffies
|
||||||
|
* before latching the timer count to guarantee that although
|
||||||
|
* the jiffies value might be older than the count (that is,
|
||||||
|
* the counter may underflow between the last point where
|
||||||
|
* jiffies was incremented and the point where we latch the
|
||||||
|
* count), it cannot be newer.
|
||||||
|
*/
|
||||||
|
jifs = jiffies;
|
||||||
|
outb_p(0x00, PIT_MODE); /* latch the count ASAP */
|
||||||
|
count = inb_p(PIT_CH0); /* read the latched count */
|
||||||
|
count |= inb_p(PIT_CH0) << 8;
|
||||||
|
|
||||||
|
/* VIA686a test code... reset the latch if count > max + 1 */
|
||||||
|
if (count > LATCH) {
|
||||||
|
outb_p(0x34, PIT_MODE);
|
||||||
|
outb_p(LATCH & 0xff, PIT_CH0);
|
||||||
|
outb(LATCH >> 8, PIT_CH0);
|
||||||
|
count = LATCH - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's possible for count to appear to go the wrong way for a
|
||||||
|
* couple of reasons:
|
||||||
|
*
|
||||||
|
* 1. The timer counter underflows, but we haven't handled the
|
||||||
|
* resulting interrupt and incremented jiffies yet.
|
||||||
|
* 2. Hardware problem with the timer, not giving us continuous time,
|
||||||
|
* the counter does small "jumps" upwards on some Pentium systems,
|
||||||
|
* (see c't 95/10 page 335 for Neptun bug.)
|
||||||
|
*
|
||||||
|
* Previous attempts to handle these cases intelligently were
|
||||||
|
* buggy, so we just do the simple thing now.
|
||||||
|
*/
|
||||||
|
if (count > old_count && jifs == old_jifs) {
|
||||||
|
count = old_count;
|
||||||
|
}
|
||||||
|
old_count = count;
|
||||||
|
old_jifs = jifs;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&i8253_lock, flags);
|
||||||
|
|
||||||
|
count = (LATCH - 1) - count;
|
||||||
|
|
||||||
|
return (cycle_t)(jifs * LATCH) + count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct clocksource clocksource_pit = {
|
||||||
|
.name = "pit",
|
||||||
|
.rating = 110,
|
||||||
|
.read = pit_read,
|
||||||
|
.mask = CLOCKSOURCE_MASK(32),
|
||||||
|
.mult = 0,
|
||||||
|
.shift = 20,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init init_pit_clocksource(void)
|
||||||
|
{
|
||||||
|
if (num_possible_cpus() > 4) /* PIT does not scale! */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
|
||||||
|
return clocksource_register(&clocksource_pit);
|
||||||
|
}
|
||||||
|
module_init(init_pit_clocksource);
|
@@ -175,7 +175,7 @@ static void mask_and_ack_8259A(unsigned int irq)
|
|||||||
* Lightweight spurious IRQ detection. We do not want
|
* Lightweight spurious IRQ detection. We do not want
|
||||||
* to overdo spurious IRQ handling - it's usually a sign
|
* to overdo spurious IRQ handling - it's usually a sign
|
||||||
* of hardware problems, so we only do the checks we can
|
* of hardware problems, so we only do the checks we can
|
||||||
* do without slowing down good hardware unnecesserily.
|
* do without slowing down good hardware unnecessarily.
|
||||||
*
|
*
|
||||||
* Note that IRQ7 and IRQ15 (the two spurious IRQs
|
* Note that IRQ7 and IRQ15 (the two spurious IRQs
|
||||||
* usually resulting from the 8259A-1|2 PICs) occur
|
* usually resulting from the 8259A-1|2 PICs) occur
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
#include <asm/timer.h>
|
#include <asm/timer.h>
|
||||||
#include <asm/i8259.h>
|
#include <asm/i8259.h>
|
||||||
|
#include <asm/nmi.h>
|
||||||
|
|
||||||
#include <mach_apic.h>
|
#include <mach_apic.h>
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ atomic_t irq_mis_count;
|
|||||||
static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
|
static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(ioapic_lock);
|
static DEFINE_SPINLOCK(ioapic_lock);
|
||||||
|
static DEFINE_SPINLOCK(vector_lock);
|
||||||
|
|
||||||
int timer_over_8254 __initdata = 1;
|
int timer_over_8254 __initdata = 1;
|
||||||
|
|
||||||
@@ -1161,10 +1163,17 @@ u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
|
|||||||
int assign_irq_vector(int irq)
|
int assign_irq_vector(int irq)
|
||||||
{
|
{
|
||||||
static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
|
static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
|
||||||
|
unsigned long flags;
|
||||||
|
int vector;
|
||||||
|
|
||||||
BUG_ON(irq >= NR_IRQ_VECTORS);
|
BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
|
||||||
if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
|
|
||||||
|
spin_lock_irqsave(&vector_lock, flags);
|
||||||
|
|
||||||
|
if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
|
||||||
|
spin_unlock_irqrestore(&vector_lock, flags);
|
||||||
return IO_APIC_VECTOR(irq);
|
return IO_APIC_VECTOR(irq);
|
||||||
|
}
|
||||||
next:
|
next:
|
||||||
current_vector += 8;
|
current_vector += 8;
|
||||||
if (current_vector == SYSCALL_VECTOR)
|
if (current_vector == SYSCALL_VECTOR)
|
||||||
@@ -1172,16 +1181,21 @@ next:
|
|||||||
|
|
||||||
if (current_vector >= FIRST_SYSTEM_VECTOR) {
|
if (current_vector >= FIRST_SYSTEM_VECTOR) {
|
||||||
offset++;
|
offset++;
|
||||||
if (!(offset%8))
|
if (!(offset%8)) {
|
||||||
|
spin_unlock_irqrestore(&vector_lock, flags);
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
}
|
||||||
current_vector = FIRST_DEVICE_VECTOR + offset;
|
current_vector = FIRST_DEVICE_VECTOR + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector_irq[current_vector] = irq;
|
vector = current_vector;
|
||||||
|
vector_irq[vector] = irq;
|
||||||
if (irq != AUTO_ASSIGN)
|
if (irq != AUTO_ASSIGN)
|
||||||
IO_APIC_VECTOR(irq) = current_vector;
|
IO_APIC_VECTOR(irq) = vector;
|
||||||
|
|
||||||
return current_vector;
|
spin_unlock_irqrestore(&vector_lock, flags);
|
||||||
|
|
||||||
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct hw_interrupt_type ioapic_level_type;
|
static struct hw_interrupt_type ioapic_level_type;
|
||||||
@@ -1193,21 +1207,14 @@ static struct hw_interrupt_type ioapic_edge_type;
|
|||||||
|
|
||||||
static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger)
|
static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger)
|
||||||
{
|
{
|
||||||
if (use_pci_vector() && !platform_legacy_irq(irq)) {
|
unsigned idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq;
|
||||||
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
|
|
||||||
trigger == IOAPIC_LEVEL)
|
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
|
||||||
irq_desc[vector].handler = &ioapic_level_type;
|
trigger == IOAPIC_LEVEL)
|
||||||
else
|
irq_desc[idx].handler = &ioapic_level_type;
|
||||||
irq_desc[vector].handler = &ioapic_edge_type;
|
else
|
||||||
set_intr_gate(vector, interrupt[vector]);
|
irq_desc[idx].handler = &ioapic_edge_type;
|
||||||
} else {
|
set_intr_gate(vector, interrupt[idx]);
|
||||||
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
|
|
||||||
trigger == IOAPIC_LEVEL)
|
|
||||||
irq_desc[irq].handler = &ioapic_level_type;
|
|
||||||
else
|
|
||||||
irq_desc[irq].handler = &ioapic_edge_type;
|
|
||||||
set_intr_gate(vector, interrupt[irq]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init setup_IO_APIC_irqs(void)
|
static void __init setup_IO_APIC_irqs(void)
|
||||||
|
@@ -53,8 +53,8 @@ static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
|
|||||||
*/
|
*/
|
||||||
fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
/* high bits used in ret_from_ code */
|
/* high bit used in ret_from_ code */
|
||||||
int irq = regs->orig_eax & 0xff;
|
int irq = ~regs->orig_eax;
|
||||||
#ifdef CONFIG_4KSTACKS
|
#ifdef CONFIG_4KSTACKS
|
||||||
union irq_ctx *curctx, *irqctx;
|
union irq_ctx *curctx, *irqctx;
|
||||||
u32 *isp;
|
u32 *isp;
|
||||||
@@ -100,8 +100,8 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
|||||||
* softirq checks work in the hardirq context.
|
* softirq checks work in the hardirq context.
|
||||||
*/
|
*/
|
||||||
irqctx->tinfo.preempt_count =
|
irqctx->tinfo.preempt_count =
|
||||||
irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK |
|
(irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
|
||||||
curctx->tinfo.preempt_count & SOFTIRQ_MASK;
|
(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
|
||||||
|
|
||||||
asm volatile(
|
asm volatile(
|
||||||
" xchgl %%ebx,%%esp \n"
|
" xchgl %%ebx,%%esp \n"
|
||||||
@@ -227,7 +227,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
seq_printf(p, " ");
|
seq_printf(p, " ");
|
||||||
for_each_online_cpu(j)
|
for_each_online_cpu(j)
|
||||||
seq_printf(p, "CPU%d ",j);
|
seq_printf(p, "CPU%-8d",j);
|
||||||
seq_putc(p, '\n');
|
seq_putc(p, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -57,34 +57,85 @@ static __always_inline void set_jmp_op(void *from, void *to)
|
|||||||
/*
|
/*
|
||||||
* returns non-zero if opcodes can be boosted.
|
* returns non-zero if opcodes can be boosted.
|
||||||
*/
|
*/
|
||||||
static __always_inline int can_boost(kprobe_opcode_t opcode)
|
static __always_inline int can_boost(kprobe_opcode_t *opcodes)
|
||||||
{
|
{
|
||||||
switch (opcode & 0xf0 ) {
|
#define W(row,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf) \
|
||||||
|
(((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \
|
||||||
|
(b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) | \
|
||||||
|
(b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) | \
|
||||||
|
(bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf)) \
|
||||||
|
<< (row % 32))
|
||||||
|
/*
|
||||||
|
* Undefined/reserved opcodes, conditional jump, Opcode Extension
|
||||||
|
* Groups, and some special opcodes can not be boost.
|
||||||
|
*/
|
||||||
|
static const unsigned long twobyte_is_boostable[256 / 32] = {
|
||||||
|
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
|
||||||
|
/* ------------------------------- */
|
||||||
|
W(0x00, 0,0,1,1,0,0,1,0,1,1,0,0,0,0,0,0)| /* 00 */
|
||||||
|
W(0x10, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 10 */
|
||||||
|
W(0x20, 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0)| /* 20 */
|
||||||
|
W(0x30, 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 30 */
|
||||||
|
W(0x40, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 40 */
|
||||||
|
W(0x50, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 50 */
|
||||||
|
W(0x60, 1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1)| /* 60 */
|
||||||
|
W(0x70, 0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1), /* 70 */
|
||||||
|
W(0x80, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 80 */
|
||||||
|
W(0x90, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), /* 90 */
|
||||||
|
W(0xa0, 1,1,0,1,1,1,0,0,1,1,0,1,1,1,0,1)| /* a0 */
|
||||||
|
W(0xb0, 1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1), /* b0 */
|
||||||
|
W(0xc0, 1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1)| /* c0 */
|
||||||
|
W(0xd0, 0,1,1,1,0,1,0,0,1,1,0,1,1,1,0,1), /* d0 */
|
||||||
|
W(0xe0, 0,1,1,0,0,1,0,0,1,1,0,1,1,1,0,1)| /* e0 */
|
||||||
|
W(0xf0, 0,1,1,1,0,1,0,0,1,1,1,0,1,1,1,0) /* f0 */
|
||||||
|
/* ------------------------------- */
|
||||||
|
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
|
||||||
|
};
|
||||||
|
#undef W
|
||||||
|
kprobe_opcode_t opcode;
|
||||||
|
kprobe_opcode_t *orig_opcodes = opcodes;
|
||||||
|
retry:
|
||||||
|
if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
|
||||||
|
return 0;
|
||||||
|
opcode = *(opcodes++);
|
||||||
|
|
||||||
|
/* 2nd-byte opcode */
|
||||||
|
if (opcode == 0x0f) {
|
||||||
|
if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
|
||||||
|
return 0;
|
||||||
|
return test_bit(*opcodes, twobyte_is_boostable);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opcode & 0xf0) {
|
||||||
|
case 0x60:
|
||||||
|
if (0x63 < opcode && opcode < 0x67)
|
||||||
|
goto retry; /* prefixes */
|
||||||
|
/* can't boost Address-size override and bound */
|
||||||
|
return (opcode != 0x62 && opcode != 0x67);
|
||||||
case 0x70:
|
case 0x70:
|
||||||
return 0; /* can't boost conditional jump */
|
return 0; /* can't boost conditional jump */
|
||||||
case 0x90:
|
|
||||||
/* can't boost call and pushf */
|
|
||||||
return opcode != 0x9a && opcode != 0x9c;
|
|
||||||
case 0xc0:
|
case 0xc0:
|
||||||
/* can't boost undefined opcodes and soft-interruptions */
|
/* can't boost software-interruptions */
|
||||||
return (0xc1 < opcode && opcode < 0xc6) ||
|
return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf;
|
||||||
(0xc7 < opcode && opcode < 0xcc) || opcode == 0xcf;
|
|
||||||
case 0xd0:
|
case 0xd0:
|
||||||
/* can boost AA* and XLAT */
|
/* can boost AA* and XLAT */
|
||||||
return (opcode == 0xd4 || opcode == 0xd5 || opcode == 0xd7);
|
return (opcode == 0xd4 || opcode == 0xd5 || opcode == 0xd7);
|
||||||
case 0xe0:
|
case 0xe0:
|
||||||
/* can boost in/out and (may be) jmps */
|
/* can boost in/out and absolute jmps */
|
||||||
return (0xe3 < opcode && opcode != 0xe8);
|
return ((opcode & 0x04) || opcode == 0xea);
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
|
if ((opcode & 0x0c) == 0 && opcode != 0xf1)
|
||||||
|
goto retry; /* lock/rep(ne) prefix */
|
||||||
/* clear and set flags can be boost */
|
/* clear and set flags can be boost */
|
||||||
return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
|
return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
|
||||||
default:
|
default:
|
||||||
/* currently, can't boost 2 bytes opcodes */
|
if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e)
|
||||||
return opcode != 0x0f;
|
goto retry; /* prefixes */
|
||||||
|
/* can't boost CS override and call */
|
||||||
|
return (opcode != 0x2e && opcode != 0x9a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns non-zero if opcode modifies the interrupt flag.
|
* returns non-zero if opcode modifies the interrupt flag.
|
||||||
*/
|
*/
|
||||||
@@ -109,7 +160,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
|
|||||||
|
|
||||||
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
|
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
|
||||||
p->opcode = *p->addr;
|
p->opcode = *p->addr;
|
||||||
if (can_boost(p->opcode)) {
|
if (can_boost(p->addr)) {
|
||||||
p->ainsn.boostable = 0;
|
p->ainsn.boostable = 0;
|
||||||
} else {
|
} else {
|
||||||
p->ainsn.boostable = -1;
|
p->ainsn.boostable = -1;
|
||||||
@@ -208,7 +259,9 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
struct kprobe_ctlblk *kcb;
|
struct kprobe_ctlblk *kcb;
|
||||||
#ifdef CONFIG_PREEMPT
|
#ifdef CONFIG_PREEMPT
|
||||||
unsigned pre_preempt_count = preempt_count();
|
unsigned pre_preempt_count = preempt_count();
|
||||||
#endif /* CONFIG_PREEMPT */
|
#else
|
||||||
|
unsigned pre_preempt_count = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
|
addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
|
||||||
|
|
||||||
@@ -285,22 +338,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
/* handler has already set things up, so skip ss setup */
|
/* handler has already set things up, so skip ss setup */
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (p->ainsn.boostable == 1 &&
|
ss_probe:
|
||||||
#ifdef CONFIG_PREEMPT
|
if (pre_preempt_count && p->ainsn.boostable == 1 && !p->post_handler){
|
||||||
!(pre_preempt_count) && /*
|
|
||||||
* This enables booster when the direct
|
|
||||||
* execution path aren't preempted.
|
|
||||||
*/
|
|
||||||
#endif /* CONFIG_PREEMPT */
|
|
||||||
!p->post_handler && !p->break_handler ) {
|
|
||||||
/* Boost up -- we can execute copied instructions directly */
|
/* Boost up -- we can execute copied instructions directly */
|
||||||
reset_current_kprobe();
|
reset_current_kprobe();
|
||||||
regs->eip = (unsigned long)p->ainsn.insn;
|
regs->eip = (unsigned long)p->ainsn.insn;
|
||||||
preempt_enable_no_resched();
|
preempt_enable_no_resched();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ss_probe:
|
|
||||||
prepare_singlestep(p, regs);
|
prepare_singlestep(p, regs);
|
||||||
kcb->kprobe_status = KPROBE_HIT_SS;
|
kcb->kprobe_status = KPROBE_HIT_SS;
|
||||||
return 1;
|
return 1;
|
||||||
|
@@ -133,9 +133,9 @@ typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
|
|||||||
unsigned long start_address,
|
unsigned long start_address,
|
||||||
unsigned int has_pae) ATTRIB_NORET;
|
unsigned int has_pae) ATTRIB_NORET;
|
||||||
|
|
||||||
const extern unsigned char relocate_new_kernel[];
|
extern const unsigned char relocate_new_kernel[];
|
||||||
extern void relocate_new_kernel_end(void);
|
extern void relocate_new_kernel_end(void);
|
||||||
const extern unsigned int relocate_new_kernel_size;
|
extern const unsigned int relocate_new_kernel_size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A architecture hook called to validate the
|
* A architecture hook called to validate the
|
||||||
|
@@ -266,7 +266,7 @@ static int msr_class_cpu_callback(struct notifier_block *nfb, unsigned long acti
|
|||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct notifier_block msr_class_cpu_notifier =
|
static struct notifier_block __cpuinitdata msr_class_cpu_notifier =
|
||||||
{
|
{
|
||||||
.notifier_call = msr_class_cpu_callback,
|
.notifier_call = msr_class_cpu_callback,
|
||||||
};
|
};
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user