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:
Коммит
f28e71617d
5
CREDITS
5
CREDITS
|
@ -24,6 +24,11 @@ S: C. Negri 6, bl. D3
|
|||
S: Iasi 6600
|
||||
S: Romania
|
||||
|
||||
N: Mark Adler
|
||||
E: madler@alumni.caltech.edu
|
||||
W: http://alumnus.caltech.edu/~madler/
|
||||
D: zlib decompression
|
||||
|
||||
N: Monalisa Agrawal
|
||||
E: magrawal@nortelnetworks.com
|
||||
D: Basic Interphase 5575 driver with UBR and ABR support.
|
||||
|
|
|
@ -1590,7 +1590,7 @@ the amount of locking which needs to be done.
|
|||
<para>
|
||||
Our final dilemma is this: when can we actually destroy the
|
||||
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
|
||||
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
|
||||
|
|
|
@ -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
|
||||
be loaded to run a torture test. The test periodically outputs
|
||||
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.
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
|
@ -42,14 +55,14 @@ OUTPUT
|
|||
|
||||
The statistics output is as follows:
|
||||
|
||||
rcutorture: --- Start of test: nreaders=16 stat_interval=0 verbose=0
|
||||
rcutorture: 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
|
||||
rcutorture: 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
|
||||
rcutorture: --- End of test
|
||||
rcu-torture: --- Start of test: nreaders=16 stat_interval=0 verbose=0
|
||||
rcu-torture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915
|
||||
rcu-torture: Reader Pipe: 1466408 9747 0 0 0 0 0 0 0 0 0
|
||||
rcu-torture: Reader Batch: 1464477 11678 0 0 0 0 0 0 0 0
|
||||
rcu-torture: Free-Block Circulation: 1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0
|
||||
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
|
||||
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
|
||||
|
@ -115,8 +128,9 @@ The following script may be used to torture RCU:
|
|||
modprobe rcutorture
|
||||
sleep 100
|
||||
rmmod rcutorture
|
||||
dmesg | grep rcutorture:
|
||||
dmesg | grep torture:
|
||||
|
||||
The output can be manually inspected for the error flag of "!!!".
|
||||
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
|
||||
by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 and
|
||||
the S3C2440 are supported CPUs.
|
||||
by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
|
||||
S3C2440 and S3C2442 devices are supported.
|
||||
|
||||
Support for the S3C2400 series is in progress.
|
||||
|
||||
Support for the S3C2412 and S3C2413 CPUs is being merged.
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
@ -43,9 +45,18 @@ Machines
|
|||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
@ -211,24 +222,6 @@ Port Contributors
|
|||
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
|
||||
---------------
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
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
|
||||
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
|
||||
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
|
||||
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()).
|
||||
|
||||
A missing memory barrier in the cases where they are required by the
|
||||
atomic_t implementation above can have disasterous results. Here is
|
||||
an example, which follows a pattern occuring frequently in the Linux
|
||||
atomic_t implementation above can have disastrous results. Here is
|
||||
an example, which follows a pattern occurring frequently in the Linux
|
||||
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
|
||||
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)
|
||||
{
|
||||
|
@ -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
|
||||
native endianness of the cpu.
|
||||
|
||||
void set_bit(unsigned long nr, volatils unsigned long *addr);
|
||||
void clear_bit(unsigned long nr, volatils unsigned long *addr);
|
||||
void change_bit(unsigned long nr, volatils unsigned long *addr);
|
||||
void set_bit(unsigned long nr, volatile unsigned long *addr);
|
||||
void clear_bit(unsigned long nr, volatile unsigned long *addr);
|
||||
void change_bit(unsigned long nr, volatile unsigned long *addr);
|
||||
|
||||
These routines set, clear, and change, respectively, the bit number
|
||||
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
|
||||
semantics required of these interfaces.
|
||||
|
||||
int test_and_set_bit(unsigned long nr, volatils unsigned long *addr);
|
||||
int test_and_clear_bit(unsigned long nr, volatils unsigned long *addr);
|
||||
int test_and_change_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, volatile 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
|
||||
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;
|
||||
|
||||
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
|
||||
done by test_and_set_bit() becomes visible. Likewise, the atomic
|
||||
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
|
||||
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
|
||||
spinlock being acquired.
|
||||
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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
|
||||
|
|
|
@ -135,10 +135,10 @@ C. Boot options
|
|||
|
||||
The angle can be changed anytime afterwards by 'echoing' the same
|
||||
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
|
||||
con_rotate_all - rotate the display of all consoles
|
||||
rotate - rotate the display of the active console
|
||||
rotate_all - rotate the display of all consoles
|
||||
|
||||
Console rotation will only become available if Console Rotation
|
||||
Support is compiled in your kernel.
|
||||
|
@ -148,5 +148,177 @@ C. Boot options
|
|||
Actually, the underlying fb driver is totally ignorant of console
|
||||
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>
|
||||
|
|
|
@ -113,6 +113,14 @@ noquota
|
|||
grpquota
|
||||
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
|
||||
=============
|
||||
|
|
|
@ -1123,6 +1123,14 @@ The top Makefile exports the following variables:
|
|||
$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE). The user may
|
||||
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
|
||||
|
||||
The kernel Makefiles are designed to run with GNU Make. The Makefiles
|
||||
|
|
|
@ -175,7 +175,7 @@ end
|
|||
document trapinfo
|
||||
Run info threads and lookup pid of thread #1
|
||||
'trapinfo <pid>' will tell you by which trap & possibly
|
||||
addresthe kernel paniced.
|
||||
address the kernel panicked.
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ parameter is applicable:
|
|||
MTD MTD support is enabled.
|
||||
NET Appropriate network support is enabled.
|
||||
NUMA NUMA support is enabled.
|
||||
GENERIC_TIME The generic timeofday code is enabled.
|
||||
NFS Appropriate NFS support is enabled.
|
||||
OSS OSS sound support is enabled.
|
||||
PARIDE The ParIDE subsystem is enabled.
|
||||
|
@ -179,6 +180,11 @@ running once the system is up.
|
|||
override platform specific driver.
|
||||
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 PIN 1 of APIC timer
|
||||
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
|
||||
/selinux/checkreqprot.
|
||||
|
||||
clock= [BUGS=IA-32,HW] gettimeofday timesource override.
|
||||
Forces specified timesource (if avaliable) to be used
|
||||
when calculating gettimeofday(). If specicified
|
||||
timesource is not avalible, it defaults to PIT.
|
||||
clock= [BUGS=IA-32, HW] gettimeofday clocksource override.
|
||||
[Deprecated]
|
||||
Forces specified clocksource (if avaliable) to be used
|
||||
when calculating gettimeofday(). If specified
|
||||
clocksource is not avalible, it defaults to PIT.
|
||||
Format: { pit | tsc | cyclone | pmtmr }
|
||||
|
||||
disable_8254_timer
|
||||
|
@ -1617,6 +1624,10 @@ running once the system is up.
|
|||
|
||||
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]
|
||||
Set communications timeout in tenths of a second
|
||||
(default 15).
|
||||
|
@ -1658,6 +1669,10 @@ running once the system is up.
|
|||
usbhid.mousepoll=
|
||||
[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
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
Each key is labeled with the same context as the task to which it belongs.
|
||||
Typically, this is the same task that was running when the key was created.
|
||||
The default keyrings are handled differently, but in a way that is very
|
||||
intuitive:
|
||||
The value of the file /proc/self/attr/keycreate influences the labeling of
|
||||
newly-created keys. If the contents of that file correspond to an SELinux
|
||||
security context, then the key will be assigned that context. Otherwise, the
|
||||
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
|
||||
are currently labeled with the context of the login manager.
|
||||
|
||||
(*) 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.
|
||||
The default keyrings associated with users will be labeled with the default
|
||||
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
|
||||
be labeled with the context of the login program itself.
|
||||
|
||||
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
|
||||
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
|
||||
|
@ -270,9 +275,17 @@ about the status of the key service:
|
|||
|
||||
(*) /proc/keys
|
||||
|
||||
This lists all the keys on the system, giving information about their
|
||||
type, description and permissions. The payload of the key is not available
|
||||
this way:
|
||||
This lists the keys that are currently viewable by the task reading the
|
||||
file, giving information about their type, description and permissions.
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
This file can be written but not read. The value written should
|
||||
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
|
||||
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_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
|
||||
a detected fault
|
||||
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.
|
||||
This includes spares that are in the process
|
||||
of being recoverred to
|
||||
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
|
||||
An approximate count of read errors that have been detected on
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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).
|
||||
|
||||
The list is guaranteed to be private and per-thread at do_exit() time,
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
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
|
||||
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.
|
||||
The TTY_DO_WRITE_WAKEUP flag indicates if a call
|
||||
is needed but always races versus calls. Thus the
|
||||
|
|
|
@ -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ö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.
|
||||
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
|
||||
|
||||
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/
|
||||
S: Maintained
|
||||
|
||||
HARDWARE RANDOM NUMBER GENERATOR CORE
|
||||
P: Michael Buesch
|
||||
M: mb@bu3sch.de
|
||||
S: Maintained
|
||||
|
||||
HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
|
||||
P: Robert Love
|
||||
M: rlove@rlove.org
|
||||
|
@ -1396,7 +1401,8 @@ S: Supported
|
|||
|
||||
INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
|
||||
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-joystick@atrey.karlin.mff.cuni.cz
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git
|
||||
|
@ -1436,6 +1442,11 @@ P: Tigran Aivazian
|
|||
M: tigran@veritas.com
|
||||
S: Maintained
|
||||
|
||||
INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
|
||||
P: Deepak Saxena
|
||||
M: dsaxena@plexity.net
|
||||
S: Maintained
|
||||
|
||||
INTEL PRO/100 ETHERNET SUPPORT
|
||||
P: John Ronciak
|
||||
M: john.ronciak@intel.com
|
||||
|
@ -2725,6 +2736,11 @@ P: Christoph Hellwig
|
|||
M: hch@infradead.org
|
||||
S: Maintained
|
||||
|
||||
TI OMAP RANDOM NUMBER GENERATOR SUPPORT
|
||||
P: Deepak Saxena
|
||||
M: dsaxena@plexity.net
|
||||
S: Maintained
|
||||
|
||||
TI PARALLEL LINK CABLE DRIVER
|
||||
P: Romain Lievin
|
||||
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.
|
||||
# 1) O=
|
||||
# Use "make O=dir/to/store/output/files/"
|
||||
#
|
||||
#
|
||||
# 2) Set KBUILD_OUTPUT
|
||||
# Set the environment variable KBUILD_OUTPUT to point to the directory
|
||||
# where the output files shall be placed.
|
||||
|
@ -178,18 +178,20 @@ CROSS_COMPILE ?=
|
|||
# Architecture as present in compile.h
|
||||
UTS_MACHINE := $(ARCH)
|
||||
|
||||
KCONFIG_CONFIG ?= .config
|
||||
|
||||
# SHELL used by kbuild
|
||||
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
|
||||
else if [ -x /bin/bash ]; then echo /bin/bash; \
|
||||
else echo sh; fi ; fi)
|
||||
|
||||
HOSTCC = gcc
|
||||
HOSTCXX = g++
|
||||
HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
|
||||
HOSTCXXFLAGS = -O2
|
||||
HOSTCC = gcc
|
||||
HOSTCXX = g++
|
||||
HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
|
||||
HOSTCXXFLAGS = -O2
|
||||
|
||||
# Decide whether to build built-in, modular, or both.
|
||||
# Normally, just do built-in.
|
||||
# Decide whether to build built-in, modular, or both.
|
||||
# Normally, just do built-in.
|
||||
|
||||
KBUILD_MODULES :=
|
||||
KBUILD_BUILTIN := 1
|
||||
|
@ -197,7 +199,7 @@ KBUILD_BUILTIN := 1
|
|||
# If we have only "make modules", don't compile built-in objects.
|
||||
# When we're building modules with modversions, we need to consider
|
||||
# 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)
|
||||
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 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.
|
||||
#
|
||||
# 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
|
||||
include $(srctree)/scripts/Kbuild.include
|
||||
|
||||
# For maximum performance (+ possibly random breakage, uncomment
|
||||
# the following)
|
||||
|
||||
#MAKEFLAGS += -rR
|
||||
# Do not use make's built-in rules and variables
|
||||
# This increases performance and avoid hard-to-debug behavour
|
||||
MAKEFLAGS += -rR
|
||||
|
||||
# Make variables (CC, etc...)
|
||||
|
||||
|
@ -305,21 +306,21 @@ LINUXINCLUDE := -Iinclude \
|
|||
|
||||
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
||||
|
||||
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
|
||||
-fno-strict-aliasing -fno-common
|
||||
AFLAGS := -D__ASSEMBLY__
|
||||
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
|
||||
-fno-strict-aliasing -fno-common
|
||||
AFLAGS := -D__ASSEMBLY__
|
||||
|
||||
# Read KERNELRELEASE from .kernelrelease (if it exists)
|
||||
KERNELRELEASE = $(shell cat .kernelrelease 2> /dev/null)
|
||||
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
|
||||
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
|
||||
KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
|
||||
|
||||
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION \
|
||||
ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
|
||||
CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
|
||||
HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
|
||||
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
|
||||
export ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
|
||||
export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
|
||||
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
|
||||
|
||||
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
|
||||
|
||||
# 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
|
||||
# It is allowed to specify more targets when calling make, including
|
||||
# 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
|
||||
# of make so .config is not included in this case either (for *config).
|
||||
|
||||
no-dot-config-targets := clean mrproper distclean \
|
||||
cscope TAGS tags help %docs check%
|
||||
cscope TAGS tags help %docs check% \
|
||||
kernelrelease kernelversion
|
||||
|
||||
config-targets := 0
|
||||
mixed-targets := 0
|
||||
|
@ -404,9 +406,8 @@ include $(srctree)/arch/$(ARCH)/Makefile
|
|||
export KBUILD_DEFCONFIG
|
||||
|
||||
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) -C $(srctree) KBUILD_SRC= .kernelrelease
|
||||
|
||||
else
|
||||
# ===========================================================================
|
||||
|
@ -416,13 +417,11 @@ else
|
|||
ifeq ($(KBUILD_EXTMOD),)
|
||||
# Additional helpers built in scripts/
|
||||
# Carefully list dependencies so we do not try to build scripts twice
|
||||
# in parrallel
|
||||
# in parallel
|
||||
PHONY += scripts
|
||||
scripts: scripts_basic include/config/MARKER
|
||||
scripts: scripts_basic include/config/auto.conf
|
||||
$(Q)$(MAKE) $(build)=$(@)
|
||||
|
||||
scripts_basic: include/linux/autoconf.h
|
||||
|
||||
# Objects we will link into vmlinux / subdirs we need to visit
|
||||
init-y := init/
|
||||
drivers-y := drivers/ sound/
|
||||
|
@ -436,31 +435,32 @@ ifeq ($(dot-config),1)
|
|||
|
||||
# Read in dependencies to all Kconfig* files, make sure to run
|
||||
# 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
|
||||
.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.
|
||||
# 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
|
||||
include/linux/autoconf.h: .kconfig.d .config
|
||||
$(Q)mkdir -p include/linux
|
||||
include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
|
||||
ifeq ($(KBUILD_EXTMOD),)
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
|
||||
else
|
||||
$(error kernel configuration not valid - run 'make prepare' in $(srctree) to update it)
|
||||
endif
|
||||
|
||||
else
|
||||
# Dummy target needed, because used as prerequisite
|
||||
include/linux/autoconf.h: ;
|
||||
include/config/auto.conf: ;
|
||||
endif
|
||||
|
||||
# The all: target is the default when no target is given on the
|
||||
# command line.
|
||||
# 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
|
||||
|
||||
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||
|
@ -492,11 +492,11 @@ CHECKFLAGS += $(NOSTDINC_FLAGS)
|
|||
# warn about C99 declaration 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,)
|
||||
|
||||
# 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
|
||||
# Also any assignments in arch/$(ARCH)/Makefile take precedence over
|
||||
# this default value
|
||||
|
@ -510,12 +510,29 @@ export INSTALL_PATH ?= /boot
|
|||
#
|
||||
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
|
||||
# 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)
|
||||
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),)
|
||||
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
|
||||
|
@ -539,7 +556,7 @@ libs-y := $(libs-y1) $(libs-y2)
|
|||
|
||||
# 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
|
||||
# in the kernel tree, others are specified in arch/$(ARCH)Makefile.
|
||||
# Ordering when linking is important, and $(vmlinux-init) must be first.
|
||||
|
@ -590,7 +607,7 @@ quiet_cmd_vmlinux_version = GEN .version
|
|||
$(MAKE) $(build)=init
|
||||
|
||||
# Generate System.map
|
||||
quiet_cmd_sysmap = SYSMAP
|
||||
quiet_cmd_sysmap = SYSMAP
|
||||
cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
|
||||
|
||||
# Link of vmlinux
|
||||
|
@ -719,7 +736,7 @@ $(vmlinux-dirs): prepare scripts
|
|||
$(Q)$(MAKE) $(build)=$@
|
||||
|
||||
# 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
|
||||
#
|
||||
# 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),, \
|
||||
$(shell cat /dev/null $(_localver)) \
|
||||
$(patsubst "%",%,$(CONFIG_LOCALVERSION)))
|
||||
|
||||
|
||||
# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
|
||||
# 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.
|
||||
# Other SCMs can edit scripts/setlocalversion and add the appropriate
|
||||
|
@ -753,9 +770,9 @@ endif
|
|||
|
||||
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: FORCE
|
||||
include/config/kernel.release: include/config/auto.conf FORCE
|
||||
$(Q)rm -f $@
|
||||
$(Q)echo $(kernelrelease) > $@
|
||||
|
||||
|
@ -776,10 +793,10 @@ PHONY += prepare-all
|
|||
# and if so do:
|
||||
# 1) Check that make has not been executed in the kernel src $(srctree)
|
||||
# 2) Create the include2 directory, used for the second asm symlink
|
||||
prepare3: .kernelrelease
|
||||
prepare3: include/config/kernel.release
|
||||
ifneq ($(KBUILD_SRC),)
|
||||
@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 " in the '$(srctree)' directory.";\
|
||||
/bin/false; \
|
||||
|
@ -792,7 +809,7 @@ endif
|
|||
prepare2: prepare3 outputmakefile
|
||||
|
||||
prepare1: prepare2 include/linux/version.h include/asm \
|
||||
include/config/MARKER
|
||||
include/config/auto.conf
|
||||
ifneq ($(KBUILD_MODULES),)
|
||||
$(Q)mkdir -p $(MODVERDIR)
|
||||
$(Q)rm -f $(MODVERDIR)/*
|
||||
|
@ -806,27 +823,20 @@ prepare0: archprepare FORCE
|
|||
# All the preparing..
|
||||
prepare prepare-all: prepare0
|
||||
|
||||
# Leave this as default for preprocessing vmlinux.lds.S, which is now
|
||||
# done in arch/$(ARCH)/kernel/Makefile
|
||||
# Leave this as default for preprocessing vmlinux.lds.S, which is now
|
||||
# done in arch/$(ARCH)/kernel/Makefile
|
||||
|
||||
export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
|
||||
|
||||
# FIXME: The asm symlink changes when $(ARCH) changes. That's
|
||||
# hard to detect, but I suppose "make mrproper" is a good idea
|
||||
# before switching between archs anyway.
|
||||
# FIXME: The asm symlink changes when $(ARCH) changes. That's
|
||||
# hard to detect, but I suppose "make mrproper" is a good idea
|
||||
# before switching between archs anyway.
|
||||
|
||||
include/asm:
|
||||
@echo ' SYMLINK $@ -> include/asm-$(ARCH)'
|
||||
$(Q)if [ ! -d include ]; then mkdir -p include; fi;
|
||||
@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
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
@ -846,7 +856,7 @@ define filechk_version.h
|
|||
)
|
||||
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)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
@ -860,7 +870,7 @@ depend dep:
|
|||
|
||||
ifdef CONFIG_MODULES
|
||||
|
||||
# By default, build modules as well
|
||||
# By default, build modules as well
|
||||
|
||||
all: modules
|
||||
|
||||
|
@ -942,7 +952,7 @@ CLEAN_FILES += vmlinux System.map \
|
|||
MRPROPER_DIRS += include/config include2
|
||||
MRPROPER_FILES += .config .config.old include/asm .version .old_version \
|
||||
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
|
||||
#
|
||||
|
@ -958,8 +968,9 @@ clean: archclean $(clean-dirs)
|
|||
$(call cmd,rmdirs)
|
||||
$(call cmd,rmfiles)
|
||||
@find . $(RCS_FIND_IGNORE) \
|
||||
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
|
||||
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
|
||||
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
|
||||
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
|
||||
-o -name '*.symtypes' \) \
|
||||
-type f -print | xargs rm -f
|
||||
|
||||
# mrproper - Delete all generated files, including .config
|
||||
|
@ -982,9 +993,9 @@ PHONY += distclean
|
|||
|
||||
distclean: mrproper
|
||||
@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 '.*.rej' -o -size 0 \
|
||||
-o -name '.*.rej' -o -size 0 \
|
||||
-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
|
||||
-type f -print | xargs rm -f
|
||||
|
||||
|
@ -994,9 +1005,9 @@ distclean: mrproper
|
|||
# rpm target kept for backward compatibility
|
||||
package-dir := $(srctree)/scripts/package
|
||||
|
||||
%pkg: FORCE
|
||||
%pkg: include/config/kernel.release FORCE
|
||||
$(Q)$(MAKE) $(build)=$(package-dir) $@
|
||||
rpm: FORCE
|
||||
rpm: include/config/kernel.release FORCE
|
||||
$(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 Same as 'make M=dir modules'
|
||||
# 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
|
||||
|
||||
# We are always building modules
|
||||
|
@ -1136,7 +1147,7 @@ clean: rm-dirs := $(MODVERDIR)
|
|||
clean: $(clean-dirs)
|
||||
$(call cmd,rmdirs)
|
||||
@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' \) \
|
||||
-type f -print | xargs rm -f
|
||||
|
||||
|
@ -1175,31 +1186,41 @@ else
|
|||
ALLINCLUDE_ARCHS := $(ARCH)
|
||||
endif
|
||||
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)
|
||||
endif
|
||||
|
||||
ALLSOURCE_ARCHS := $(ARCH)
|
||||
|
||||
define all-sources
|
||||
( find $(__srctree) $(RCS_FIND_IGNORE) \
|
||||
define find-sources
|
||||
( find $(__srctree) $(RCS_FIND_IGNORE) \
|
||||
\( -name include -o -name arch \) -prune -o \
|
||||
-name '*.[chS]' -print; \
|
||||
-name $1 -print; \
|
||||
for ARCH in $(ALLSOURCE_ARCHS) ; do \
|
||||
find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
|
||||
-name '*.[chS]' -print; \
|
||||
-name $1 -print; \
|
||||
done ; \
|
||||
find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
|
||||
-name '*.[chS]' -print; \
|
||||
-name $1 -print; \
|
||||
find $(__srctree)include $(RCS_FIND_IGNORE) \
|
||||
\( -name config -o -name 'asm-*' \) -prune \
|
||||
-o -name '*.[chS]' -print; \
|
||||
-o -name $1 -print; \
|
||||
for ARCH in $(ALLINCLUDE_ARCHS) ; do \
|
||||
find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
|
||||
-name '*.[chS]' -print; \
|
||||
-name $1 -print; \
|
||||
done ; \
|
||||
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
|
||||
|
||||
quiet_cmd_cscope-file = FILELST cscope.files
|
||||
|
@ -1219,7 +1240,13 @@ define cmd_TAGS
|
|||
echo "-I __initdata,__exitdata,__acquires,__releases \
|
||||
-I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
|
||||
--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
|
||||
|
||||
TAGS: FORCE
|
||||
|
@ -1259,14 +1286,14 @@ namespacecheck:
|
|||
endif #ifeq ($(config-targets),1)
|
||||
endif #ifeq ($(mixed-targets),1)
|
||||
|
||||
PHONY += checkstack
|
||||
PHONY += checkstack kernelrelease kernelversion
|
||||
checkstack:
|
||||
$(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
|
||||
$(PERL) $(src)/scripts/checkstack.pl $(ARCH)
|
||||
|
||||
kernelrelease:
|
||||
$(if $(wildcard .kernelrelease), $(Q)echo $(KERNELRELEASE), \
|
||||
$(error kernelrelease not valid - run 'make *config' to update it))
|
||||
$(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
|
||||
$(error kernelrelease not valid - run 'make prepare' to update it))
|
||||
kernelversion:
|
||||
@echo $(KERNELVERSION)
|
||||
|
||||
|
@ -1301,6 +1328,8 @@ endif
|
|||
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
|
||||
%.o: %.S prepare scripts FORCE
|
||||
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
|
||||
%.symtypes: %.c prepare scripts FORCE
|
||||
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
|
||||
|
||||
# Modules
|
||||
/ %/: prepare scripts FORCE
|
||||
|
|
|
@ -481,7 +481,7 @@ register_cpus(void)
|
|||
struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
register_cpu(p, i, NULL);
|
||||
register_cpu(p, i);
|
||||
}
|
||||
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) {
|
||||
struct dentry *dir;
|
||||
char buf[3];
|
||||
char buf[4];
|
||||
|
||||
snprintf(buf, sizeof buf, "%d", i);
|
||||
dir = oprofilefs_mkdir(sb, root, buf);
|
||||
|
|
|
@ -253,7 +253,7 @@ config ARCH_SA1100
|
|||
Support for StrongARM 11x0 based boards.
|
||||
|
||||
config ARCH_S3C2410
|
||||
bool "Samsung S3C2410"
|
||||
bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442"
|
||||
help
|
||||
Samsung S3C2410X CPU based systems, such as the Simtec Electronics
|
||||
BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
|
||||
|
@ -372,7 +372,7 @@ config ISA_DMA_API
|
|||
bool
|
||||
|
||||
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
|
||||
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
|
||||
|
|
|
@ -177,7 +177,7 @@ boot := arch/arm/boot
|
|||
# them changed. We use .arch to indicate when they were updated
|
||||
# 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)'
|
||||
ifneq ($(KBUILD_SRC),)
|
||||
$(Q)mkdir -p include/asm-arm
|
||||
|
|
|
@ -61,6 +61,12 @@
|
|||
cmp r7, r3
|
||||
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
|
||||
@ mov r7, #MACH_TYPE_AT91RM9200
|
||||
mov r7, #(MACH_TYPE_AT91RM9200DK & 0xff)
|
||||
|
|
|
@ -77,7 +77,7 @@ Lrow4bpplp:
|
|||
subne r1, r1, #1
|
||||
ldrneb r7, [r6, r1]
|
||||
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)
|
||||
|
@ -105,7 +105,7 @@ Lrow8bpplp:
|
|||
subne r1, r1, #1
|
||||
ldrneb r7, [r6, r1]
|
||||
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)
|
||||
|
@ -127,7 +127,7 @@ Lrow1bpp:
|
|||
strb r7, [r0], r5
|
||||
mov r7, r7, lsr #8
|
||||
strb r7, [r0], r5
|
||||
LOADREGS(fd, sp!, {r4 - r7, pc})
|
||||
ldmfd sp!, {r4 - r7, pc}
|
||||
|
||||
.bss
|
||||
ENTRY(con_charconvtable)
|
||||
|
|
|
@ -629,21 +629,6 @@ static int locomo_resume(struct platform_device *dev)
|
|||
#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.
|
||||
* @phys_addr: physical address of device.
|
||||
|
@ -698,14 +683,10 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
|
|||
, lchip->base + LOCOMO_GPD);
|
||||
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_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 */
|
||||
locomo_writel(0, lchip->base + LOCOMO_LTINT);
|
||||
/* SPI */
|
||||
|
@ -1062,6 +1043,30 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int
|
|||
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."
|
||||
*
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.17
|
||||
# Tue Jun 20 18:57:01 2006
|
||||
# Linux kernel version: 2.6.17-git9
|
||||
# Sun Jun 25 23:56:32 2006
|
||||
#
|
||||
CONFIG_ARM=y
|
||||
CONFIG_MMU=y
|
||||
|
@ -49,7 +49,6 @@ CONFIG_SLAB=y
|
|||
# CONFIG_TINY_SHMEM is not set
|
||||
CONFIG_BASE_SMALL=0
|
||||
# CONFIG_SLOB is not set
|
||||
CONFIG_OBSOLETE_INTERMODULE=y
|
||||
|
||||
#
|
||||
# Loadable module support
|
||||
|
@ -81,18 +80,26 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
|
|||
#
|
||||
# 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_CLPS711X is not set
|
||||
# CONFIG_ARCH_CO285 is not set
|
||||
# CONFIG_ARCH_EBSA110 is not set
|
||||
# CONFIG_ARCH_EP93XX 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_IXP4XX is not set
|
||||
# CONFIG_ARCH_IXP2000 is not set
|
||||
# CONFIG_ARCH_IXP23XX is not set
|
||||
# CONFIG_ARCH_L7200 is not set
|
||||
# CONFIG_ARCH_PNX4008 is not set
|
||||
# CONFIG_ARCH_PXA is not set
|
||||
# CONFIG_ARCH_RPC 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_LH7A40X 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
|
||||
|
@ -123,11 +122,14 @@ CONFIG_ARCH_SMDK2410=y
|
|||
CONFIG_ARCH_S3C2440=y
|
||||
CONFIG_SMDK2440_CPU2440=y
|
||||
CONFIG_SMDK2440_CPU2442=y
|
||||
CONFIG_MACH_SMDK2413=y
|
||||
CONFIG_MACH_VR1000=y
|
||||
CONFIG_MACH_RX3715=y
|
||||
CONFIG_MACH_OTOM=y
|
||||
CONFIG_MACH_NEXCODER_2440=y
|
||||
CONFIG_S3C2410_CLOCK=y
|
||||
CONFIG_CPU_S3C2410=y
|
||||
CONFIG_CPU_S3C2412=y
|
||||
CONFIG_CPU_S3C244X=y
|
||||
CONFIG_CPU_S3C2440=y
|
||||
CONFIG_CPU_S3C2442=y
|
||||
|
@ -153,8 +155,11 @@ CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
|
|||
#
|
||||
CONFIG_CPU_32=y
|
||||
CONFIG_CPU_ARM920T=y
|
||||
CONFIG_CPU_ARM926T=y
|
||||
CONFIG_CPU_32v4=y
|
||||
CONFIG_CPU_32v5=y
|
||||
CONFIG_CPU_ABRT_EV4T=y
|
||||
CONFIG_CPU_ABRT_EV5TJ=y
|
||||
CONFIG_CPU_CACHE_V4WT=y
|
||||
CONFIG_CPU_CACHE_VIVT=y
|
||||
CONFIG_CPU_COPY_V4WB=y
|
||||
|
@ -167,6 +172,7 @@ CONFIG_CPU_TLB_V4WBI=y
|
|||
# CONFIG_CPU_ICACHE_DISABLE is not set
|
||||
# CONFIG_CPU_DCACHE_DISABLE is not set
|
||||
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
|
||||
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
|
||||
|
||||
#
|
||||
# Bus support
|
||||
|
@ -214,6 +220,7 @@ CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
|
|||
CONFIG_FPE_NWFPE=y
|
||||
# CONFIG_FPE_NWFPE_XP is not set
|
||||
# CONFIG_FPE_FASTFPE is not set
|
||||
# CONFIG_VFP is not set
|
||||
|
||||
#
|
||||
# Userspace binary formats
|
||||
|
@ -242,6 +249,8 @@ CONFIG_NET=y
|
|||
# CONFIG_NETDEBUG is not set
|
||||
# CONFIG_PACKET is not set
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_XFRM=y
|
||||
# CONFIG_XFRM_USER is not set
|
||||
# CONFIG_NET_KEY is not set
|
||||
CONFIG_INET=y
|
||||
# CONFIG_IP_MULTICAST is not set
|
||||
|
@ -260,6 +269,8 @@ CONFIG_IP_PNP_BOOTP=y
|
|||
# CONFIG_INET_IPCOMP is not set
|
||||
# CONFIG_INET_XFRM_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_TCP_DIAG=y
|
||||
# CONFIG_TCP_CONG_ADVANCED is not set
|
||||
|
@ -267,6 +278,7 @@ CONFIG_TCP_CONG_BIC=y
|
|||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_INET6_XFRM_TUNNEL is not set
|
||||
# CONFIG_INET6_TUNNEL is not set
|
||||
# CONFIG_NETWORK_SECMARK is not set
|
||||
# CONFIG_NETFILTER is not set
|
||||
|
||||
#
|
||||
|
@ -321,6 +333,7 @@ CONFIG_STANDALONE=y
|
|||
CONFIG_PREVENT_FIRMWARE_BUILD=y
|
||||
# CONFIG_FW_LOADER is not set
|
||||
# CONFIG_DEBUG_DRIVER is not set
|
||||
# CONFIG_SYS_HYPERVISOR is not set
|
||||
|
||||
#
|
||||
# Connector - unified userspace <-> kernelspace linker
|
||||
|
@ -408,10 +421,12 @@ CONFIG_MTD_BAST_MAXSIZE=4
|
|||
#
|
||||
CONFIG_MTD_NAND=y
|
||||
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
|
||||
# CONFIG_MTD_NAND_ECC_SMC is not set
|
||||
CONFIG_MTD_NAND_IDS=y
|
||||
CONFIG_MTD_NAND_S3C2410=y
|
||||
# CONFIG_MTD_NAND_S3C2410_DEBUG 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_NANDSIM is not set
|
||||
|
||||
|
@ -425,8 +440,8 @@ CONFIG_MTD_NAND_S3C2410=y
|
|||
#
|
||||
CONFIG_PARPORT=y
|
||||
# CONFIG_PARPORT_PC is not set
|
||||
# CONFIG_PARPORT_ARC is not set
|
||||
# CONFIG_PARPORT_GSC is not set
|
||||
# CONFIG_PARPORT_AX88796 is not set
|
||||
CONFIG_PARPORT_1284=y
|
||||
|
||||
#
|
||||
|
@ -735,6 +750,7 @@ CONFIG_I2C_ALGOBIT=m
|
|||
#
|
||||
# CONFIG_I2C_ELEKTOR is not set
|
||||
CONFIG_I2C_ISA=m
|
||||
# CONFIG_I2C_OCORES is not set
|
||||
# CONFIG_I2C_PARPORT is not set
|
||||
# CONFIG_I2C_PARPORT_LIGHT is not set
|
||||
CONFIG_I2C_S3C2410=y
|
||||
|
@ -765,13 +781,13 @@ CONFIG_SENSORS_EEPROM=m
|
|||
#
|
||||
# Dallas's 1-wire bus
|
||||
#
|
||||
# CONFIG_W1 is not set
|
||||
|
||||
#
|
||||
# Hardware Monitoring support
|
||||
#
|
||||
CONFIG_HWMON=y
|
||||
CONFIG_HWMON_VID=m
|
||||
# CONFIG_SENSORS_ABITUGURU is not set
|
||||
# CONFIG_SENSORS_ADM1021 is not set
|
||||
# CONFIG_SENSORS_ADM1025 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_PC87360 is not set
|
||||
# CONFIG_SENSORS_SMSC47M1 is not set
|
||||
# CONFIG_SENSORS_SMSC47M192 is not set
|
||||
# CONFIG_SENSORS_SMSC47B397 is not set
|
||||
# CONFIG_SENSORS_W83781D is not set
|
||||
# CONFIG_SENSORS_W83791D is not set
|
||||
# CONFIG_SENSORS_W83792D is not set
|
||||
# CONFIG_SENSORS_W83L785TS 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_MACMODES is not set
|
||||
CONFIG_FB_FIRMWARE_EDID=y
|
||||
# CONFIG_FB_BACKLIGHT is not set
|
||||
CONFIG_FB_MODE_HELPERS=y
|
||||
# CONFIG_FB_TILEBLITTING 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_LCD is not set
|
||||
# CONFIG_USB_LED is not set
|
||||
# CONFIG_USB_CY7C63 is not set
|
||||
# CONFIG_USB_CYTHERM is not set
|
||||
# CONFIG_USB_PHIDGETKIT is not set
|
||||
# CONFIG_USB_PHIDGETSERVO is not set
|
||||
# CONFIG_USB_IDMOUSE is not set
|
||||
# CONFIG_USB_APPLEDISPLAY is not set
|
||||
# CONFIG_USB_LD is not set
|
||||
# CONFIG_USB_TEST is not set
|
||||
|
||||
|
@ -1024,6 +1045,7 @@ CONFIG_FS_MBCACHE=y
|
|||
# CONFIG_MINIX_FS is not set
|
||||
CONFIG_ROMFS_FS=y
|
||||
CONFIG_INOTIFY=y
|
||||
CONFIG_INOTIFY_USER=y
|
||||
# CONFIG_QUOTA is not set
|
||||
CONFIG_DNOTIFY=y
|
||||
# CONFIG_AUTOFS_FS is not set
|
||||
|
|
|
@ -340,7 +340,7 @@ sys_mmap2:
|
|||
streq r5, [sp, #4]
|
||||
beq do_mmap2
|
||||
mov r0, #-EINVAL
|
||||
RETINSTR(mov,pc, lr)
|
||||
mov pc, lr
|
||||
#else
|
||||
str r5, [sp, #4]
|
||||
b do_mmap2
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
__INIT
|
||||
.type stext, %function
|
||||
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
|
||||
mrc p15, 0, r9, c0, c0 @ get processor id
|
||||
bl __lookup_processor_type @ r5=procinfo r9=cpuid
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
__INIT
|
||||
.type stext, %function
|
||||
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
|
||||
mrc p15, 0, r9, c0, c0 @ get processor id
|
||||
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
|
||||
* 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
|
||||
bl __lookup_processor_type
|
||||
movs r10, r5 @ invalid processor?
|
||||
|
|
|
@ -808,7 +808,7 @@ static int __init topology_init(void)
|
|||
int 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;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ ENTRY(c_backtrace)
|
|||
movne r0, #0
|
||||
movs frame, r0
|
||||
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
|
||||
ldr r0, [sp], #4
|
||||
|
@ -85,7 +85,7 @@ ENTRY(c_backtrace)
|
|||
* A zero next framepointer means we're done.
|
||||
*/
|
||||
teq next, #0
|
||||
LOADREGS(eqfd, sp!, {r4 - r8, pc})
|
||||
ldmeqfd sp!, {r4 - r8, pc}
|
||||
|
||||
/*
|
||||
* The next framepointer must be above the
|
||||
|
@ -104,7 +104,7 @@ ENTRY(c_backtrace)
|
|||
1007: ldr r0, =.Lbad
|
||||
mov r1, frame
|
||||
bl printk
|
||||
LOADREGS(fd, sp!, {r4 - r8, pc})
|
||||
ldmfd sp!, {r4 - r8, pc}
|
||||
.ltorg
|
||||
.previous
|
||||
|
||||
|
@ -145,7 +145,7 @@ ENTRY(c_backtrace)
|
|||
adrne r0, .Lcr
|
||||
blne printk
|
||||
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"
|
||||
.Lcr: .asciz "\n"
|
||||
|
|
|
@ -43,10 +43,10 @@ USER( strnebt r2, [r0], #1)
|
|||
tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
|
||||
USER( strnebt r2, [r0], #1)
|
||||
mov r0, #0
|
||||
LOADREGS(fd,sp!, {r1, pc})
|
||||
ldmfd sp!, {r1, pc}
|
||||
|
||||
.section .fixup,"ax"
|
||||
.align 0
|
||||
9001: LOADREGS(fd,sp!, {r0, pc})
|
||||
9001: ldmfd sp!, {r0, pc}
|
||||
.previous
|
||||
|
||||
|
|
|
@ -43,4 +43,4 @@ ENTRY(copy_page)
|
|||
bgt 1b @ 1
|
||||
PLD( ldmeqia r1!, {r3, r4, ip, lr} )
|
||||
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, r2
|
||||
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
|
||||
mul r0, r2, r0 @ max = 2^32-1
|
||||
movs r0, r0, lsr #6
|
||||
RETINSTR(moveq,pc,lr)
|
||||
moveq pc, lr
|
||||
|
||||
/*
|
||||
* loops = r0 * HZ * loops_per_jiffy / 1000000
|
||||
|
@ -43,20 +43,20 @@ ENTRY(__const_udelay) @ 0 <= r0 <= 0x7fffff06
|
|||
ENTRY(__delay)
|
||||
subs r0, r0, #1
|
||||
#if 0
|
||||
RETINSTR(movls,pc,lr)
|
||||
movls pc, lr
|
||||
subs r0, r0, #1
|
||||
RETINSTR(movls,pc,lr)
|
||||
movls pc, lr
|
||||
subs r0, r0, #1
|
||||
RETINSTR(movls,pc,lr)
|
||||
movls pc, lr
|
||||
subs r0, r0, #1
|
||||
RETINSTR(movls,pc,lr)
|
||||
movls pc, lr
|
||||
subs r0, r0, #1
|
||||
RETINSTR(movls,pc,lr)
|
||||
movls pc, lr
|
||||
subs r0, r0, #1
|
||||
RETINSTR(movls,pc,lr)
|
||||
movls pc, lr
|
||||
subs r0, r0, #1
|
||||
RETINSTR(movls,pc,lr)
|
||||
movls pc, lr
|
||||
subs r0, r0, #1
|
||||
#endif
|
||||
bhi __delay
|
||||
RETINSTR(mov,pc,lr)
|
||||
mov pc, lr
|
||||
|
|
|
@ -29,7 +29,7 @@ ENTRY(ecard_loader_read)
|
|||
CPSR2SPSR(r0)
|
||||
mov lr, pc
|
||||
mov pc, r2
|
||||
LOADREGS(fd, sp!, {r4 - r12, pc})
|
||||
ldmfd sp!, {r4 - r12, pc}
|
||||
|
||||
@ Purpose: call an expansion card loader to reset the card
|
||||
@ Proto : void read_loader(int card_base, char *loader);
|
||||
|
@ -41,5 +41,5 @@ ENTRY(ecard_loader_reset)
|
|||
CPSR2SPSR(r0)
|
||||
mov lr, pc
|
||||
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?
|
||||
blo 1b
|
||||
3: mov r0, r1 @ no free bits
|
||||
RETINSTR(mov,pc,lr)
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* Purpose : Find next 'zero' bit
|
||||
|
@ -66,7 +66,7 @@ ENTRY(_find_first_bit_le)
|
|||
2: cmp r2, r1 @ any more?
|
||||
blo 1b
|
||||
3: mov r0, r1 @ no free bits
|
||||
RETINSTR(mov,pc,lr)
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* Purpose : Find next 'one' bit
|
||||
|
@ -98,7 +98,7 @@ ENTRY(_find_first_zero_bit_be)
|
|||
2: cmp r2, r1 @ any more?
|
||||
blo 1b
|
||||
3: mov r0, r1 @ no free bits
|
||||
RETINSTR(mov,pc,lr)
|
||||
mov pc, lr
|
||||
|
||||
ENTRY(_find_next_zero_bit_be)
|
||||
teq r1, #0
|
||||
|
@ -126,7 +126,7 @@ ENTRY(_find_first_bit_be)
|
|||
2: cmp r2, r1 @ any more?
|
||||
blo 1b
|
||||
3: mov r0, r1 @ no free bits
|
||||
RETINSTR(mov,pc,lr)
|
||||
mov pc, lr
|
||||
|
||||
ENTRY(_find_next_bit_be)
|
||||
teq r1, #0
|
||||
|
@ -164,5 +164,5 @@ ENTRY(_find_next_bit_be)
|
|||
addeq r2, r2, #1
|
||||
mov r0, r2
|
||||
#endif
|
||||
RETINSTR(mov,pc,lr)
|
||||
mov pc, lr
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ ENTRY(__raw_readsb)
|
|||
bpl .Linsb_16_lp
|
||||
|
||||
tst r2, #15
|
||||
LOADREGS(eqfd, sp!, {r4 - r6, pc})
|
||||
ldmeqfd sp!, {r4 - r6, pc}
|
||||
|
||||
.Linsb_no_16: tst r2, #8
|
||||
beq .Linsb_no_8
|
||||
|
@ -109,7 +109,7 @@ ENTRY(__raw_readsb)
|
|||
str r3, [r1], #4
|
||||
|
||||
.Linsb_no_4: ands r2, r2, #3
|
||||
LOADREGS(eqfd, sp!, {r4 - r6, pc})
|
||||
ldmeqfd sp!, {r4 - r6, pc}
|
||||
|
||||
cmp r2, #2
|
||||
ldrb r3, [r0]
|
||||
|
@ -119,4 +119,4 @@ ENTRY(__raw_readsb)
|
|||
ldrgtb r3, [r0]
|
||||
strgtb r3, [r1]
|
||||
|
||||
LOADREGS(fd, sp!, {r4 - r6, pc})
|
||||
ldmfd sp!, {r4 - r6, pc}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
strb r3, [r1], #1
|
||||
|
||||
subs r2, r2, #1
|
||||
RETINSTR(moveq, pc, lr)
|
||||
moveq pc, lr
|
||||
|
||||
ENTRY(__raw_readsw)
|
||||
teq r2, #0 @ do we have to check for the zero len?
|
||||
|
@ -69,7 +69,7 @@ ENTRY(__raw_readsw)
|
|||
bpl .Linsw_8_lp
|
||||
|
||||
tst r2, #7
|
||||
LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
|
||||
ldmeqfd sp!, {r4, r5, r6, pc}
|
||||
|
||||
.Lno_insw_8: tst r2, #4
|
||||
beq .Lno_insw_4
|
||||
|
@ -102,6 +102,6 @@ ENTRY(__raw_readsw)
|
|||
movne r3, r3, lsr #8
|
||||
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
|
||||
|
||||
tst r2, #15
|
||||
LOADREGS(eqfd, sp!, {r4, r5, pc})
|
||||
ldmeqfd sp!, {r4, r5, pc}
|
||||
|
||||
.Loutsb_no_16: tst r2, #8
|
||||
beq .Loutsb_no_8
|
||||
|
@ -80,7 +80,7 @@ ENTRY(__raw_writesb)
|
|||
outword r3
|
||||
|
||||
.Loutsb_no_4: ands r2, r2, #3
|
||||
LOADREGS(eqfd, sp!, {r4, r5, pc})
|
||||
ldmeqfd sp!, {r4, r5, pc}
|
||||
|
||||
cmp r2, #2
|
||||
ldrb r3, [r1], #1
|
||||
|
@ -90,4 +90,4 @@ ENTRY(__raw_writesb)
|
|||
ldrgtb r3, [r1]
|
||||
strgtb r3, [r0]
|
||||
|
||||
LOADREGS(fd, sp!, {r4, r5, pc})
|
||||
ldmfd sp!, {r4, r5, pc}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
orr r3, r3, r3, lsl #16
|
||||
str r3, [r0]
|
||||
subs r2, r2, #1
|
||||
RETINSTR(moveq, pc, lr)
|
||||
moveq pc, lr
|
||||
|
||||
ENTRY(__raw_writesw)
|
||||
teq r2, #0 @ do we have to check for the zero len?
|
||||
|
@ -80,7 +80,7 @@ ENTRY(__raw_writesw)
|
|||
bpl .Loutsw_8_lp
|
||||
|
||||
tst r2, #7
|
||||
LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
|
||||
ldmeqfd sp!, {r4, r5, r6, pc}
|
||||
|
||||
.Lno_outsw_8: tst r2, #4
|
||||
beq .Lno_outsw_4
|
||||
|
@ -124,4 +124,4 @@ ENTRY(__raw_writesw)
|
|||
orrne ip, ip, ip, lsr #16
|
||||
strne ip, [r0]
|
||||
|
||||
LOADREGS(fd, sp!, {r4, r5, r6, pc})
|
||||
ldmfd sp!, {r4, r5, r6, pc}
|
||||
|
|
|
@ -22,4 +22,4 @@ ENTRY(memchr)
|
|||
bne 1b
|
||||
sub r0, r0, #1
|
||||
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}
|
||||
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
|
||||
*/
|
||||
|
@ -77,4 +77,4 @@ ENTRY(memset)
|
|||
strneb r1, [r0], #1
|
||||
tst r2, #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
|
||||
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
|
||||
*/
|
||||
|
@ -77,4 +77,4 @@ ENTRY(__memzero)
|
|||
strneb r2, [r0], #1 @ 1
|
||||
tst r1, #1 @ 1 a byte left over
|
||||
strneb r2, [r0], #1 @ 1
|
||||
RETINSTR(mov,pc,lr) @ 1
|
||||
mov pc, lr @ 1
|
||||
|
|
|
@ -23,4 +23,4 @@ ENTRY(strchr)
|
|||
teq r2, r1
|
||||
movne r0, #0
|
||||
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
|
||||
*/
|
||||
ENTRY(__arch_strncpy_from_user)
|
||||
save_lr
|
||||
mov ip, r1
|
||||
1: subs r2, r2, #1
|
||||
USER( ldrplbt r3, [r1], #1)
|
||||
|
@ -31,13 +30,13 @@ USER( ldrplbt r3, [r1], #1)
|
|||
bne 1b
|
||||
sub r1, r1, #1 @ take NUL character out of count
|
||||
2: sub r0, r1, ip
|
||||
restore_pc
|
||||
mov pc, lr
|
||||
|
||||
.section .fixup,"ax"
|
||||
.align 0
|
||||
9001: mov r3, #0
|
||||
strb r3, [r0, #0] @ null terminate
|
||||
mov r0, #-EFAULT
|
||||
restore_pc
|
||||
mov pc, lr
|
||||
.previous
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
* or zero on exception, or n + 1 if too long
|
||||
*/
|
||||
ENTRY(__arch_strnlen_user)
|
||||
save_lr
|
||||
mov r2, r0
|
||||
1:
|
||||
USER( ldrbt r3, [r0], #1)
|
||||
|
@ -31,10 +30,10 @@ USER( ldrbt r3, [r0], #1)
|
|||
bne 1b
|
||||
add r0, r0, #1
|
||||
2: sub r0, r0, r2
|
||||
restore_pc
|
||||
mov pc, lr
|
||||
|
||||
.section .fixup,"ax"
|
||||
.align 0
|
||||
9001: mov r0, #0
|
||||
restore_pc
|
||||
mov pc, lr
|
||||
.previous
|
||||
|
|
|
@ -22,4 +22,4 @@ ENTRY(strrchr)
|
|||
teq r2, #0
|
||||
bne 1b
|
||||
mov r0, r3
|
||||
RETINSTR(mov,pc,lr)
|
||||
mov pc, lr
|
||||
|
|
|
@ -105,7 +105,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
|
|||
movs ip, r2
|
||||
bne .Lc2u_nowords
|
||||
.Lc2u_finished: mov r0, #0
|
||||
LOADREGS(fd,sp!,{r2, r4 - r7, pc})
|
||||
ldmfd sp!, {r2, r4 - r7, pc}
|
||||
|
||||
.Lc2u_src_not_aligned:
|
||||
bic r1, r1, #3
|
||||
|
@ -280,7 +280,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
|
|||
|
||||
.section .fixup,"ax"
|
||||
.align 0
|
||||
9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc})
|
||||
9001: ldmfd sp!, {r0, r4 - r7, pc}
|
||||
.previous
|
||||
|
||||
/* 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
|
||||
.Lcfu_finished: mov r0, #0
|
||||
add sp, sp, #8
|
||||
LOADREGS(fd,sp!,{r4 - r7, pc})
|
||||
ldmfd sp!, {r4 - r7, pc}
|
||||
|
||||
.Lcfu_src_not_aligned:
|
||||
bic r1, r1, #3
|
||||
|
@ -556,6 +556,6 @@ USER( ldrgtbt r3, [r1], #1) @ May fault
|
|||
movne r1, r4
|
||||
blne __memzero
|
||||
mov r0, r4
|
||||
LOADREGS(fd,sp!, {r4 - r7, pc})
|
||||
ldmfd sp!, {r4 - r7, pc}
|
||||
.previous
|
||||
|
||||
|
|
|
@ -4,6 +4,12 @@ menu "AT91RM9200 Implementations"
|
|||
|
||||
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
|
||||
bool "Atmel AT91RM9200-DK Development board"
|
||||
depends on ARCH_AT91RM9200
|
||||
|
|
|
@ -10,6 +10,7 @@ obj- :=
|
|||
obj-$(CONFIG_PM) += pm.o
|
||||
|
||||
# Board-specific support
|
||||
obj-$(CONFIG_MACH_ONEARM) += board-1arm.o
|
||||
obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o
|
||||
obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o
|
||||
obj-$(CONFIG_MACH_CSB337) += board-csb337.o
|
||||
|
|
|
@ -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
|
||||
bool "IXDP425"
|
||||
select PCI
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support Intel's
|
||||
IXDP425 Development Platform (Also known as Richfield).
|
||||
|
@ -43,7 +42,6 @@ config ARCH_IXDP425
|
|||
|
||||
config MACH_IXDPG425
|
||||
bool "IXDPG425"
|
||||
select PCI
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support Intel's
|
||||
IXDPG425 Development Platform (Also known as Montajade).
|
||||
|
@ -51,7 +49,6 @@ config MACH_IXDPG425
|
|||
|
||||
config MACH_IXDP465
|
||||
bool "IXDP465"
|
||||
select PCI
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support Intel's
|
||||
IXDP465 Development Platform (Also known as BMP).
|
||||
|
|
|
@ -2,13 +2,23 @@
|
|||
# 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-$(CONFIG_PCI) += common-pci.o
|
||||
obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o ixdp425-setup.o
|
||||
obj-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o coyote-setup.o
|
||||
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o coyote-setup.o
|
||||
obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o gtwx5715-setup.o
|
||||
obj-$(CONFIG_MACH_NSLU2) += nslu2-pci.o nslu2-setup.o nslu2-power.o
|
||||
obj-$(CONFIG_MACH_NAS100D) += nas100d-pci.o nas100d-setup.o nas100d-power.o
|
||||
obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-setup.o
|
||||
obj-$(CONFIG_MACH_IXDPG425) += coyote-setup.o
|
||||
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o
|
||||
obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o
|
||||
obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o
|
||||
obj-$(CONFIG_MACH_NAS100D) += 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
|
||||
.align 5
|
||||
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
|
||||
|
||||
ldr r0, sleep_save_sp @ stack phys addr
|
||||
|
|
|
@ -71,13 +71,13 @@ config ARCH_S3C2440
|
|||
Say Y here if you are using the SMDK2440.
|
||||
|
||||
config SMDK2440_CPU2440
|
||||
bool "SMDK2440 with S3C2440 cpu module"
|
||||
bool "SMDK2440 with S3C2440 CPU module"
|
||||
depends on ARCH_S3C2440
|
||||
default y if ARCH_S3C2440
|
||||
select CPU_S3C2440
|
||||
|
||||
config SMDK2440_CPU2442
|
||||
bool "SMDM2440 with S3C2442 cpu module"
|
||||
bool "SMDM2440 with S3C2442 CPU module"
|
||||
depends on ARCH_S3C2440
|
||||
select CPU_S3C2442
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ s3c2410_sleep_save_phys:
|
|||
*/
|
||||
|
||||
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
|
||||
|
||||
@@ load UART to allow us to print the two characters for
|
||||
|
|
|
@ -177,7 +177,7 @@ sa1110_sdram_controller_fix:
|
|||
.data
|
||||
.align 5
|
||||
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
|
||||
|
||||
ldr r0, sleep_save_sp @ stack phys addr
|
||||
|
|
|
@ -35,7 +35,7 @@ ENTRY(v3_copy_user_page)
|
|||
stmia r0!, {r3, r4, ip, lr} @ 4
|
||||
ldmneia r1!, {r3, r4, ip, lr} @ 4
|
||||
bne 1b @ 1
|
||||
LOADREGS(fd, sp!, {r4, pc}) @ 3
|
||||
ldmfd sp!, {r4, pc} @ 3
|
||||
|
||||
.align 5
|
||||
/*
|
||||
|
|
|
@ -29,38 +29,6 @@
|
|||
#define TTB_RGN_WT (2 << 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)
|
||||
mov pc, lr
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
It is called from the kernel with code similar to this:
|
||||
|
||||
mov fp, #0
|
||||
teqp pc, #PSR_I_BIT | MODE_SVC
|
||||
teqp pc, #PSR_I_BIT | SVC_MODE
|
||||
ldr r4, .LC2
|
||||
ldr pc, [r4] @ Call FP module USR entry point
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
# 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
|
||||
#
|
||||
|
@ -566,8 +566,8 @@ switchgrass MACH_SWITCHGRASS SWITCHGRASS 549
|
|||
ens_cmu MACH_ENS_CMU ENS_CMU 550
|
||||
mm6_sdb MACH_MM6_SDB MM6_SDB 551
|
||||
saturn MACH_SATURN SATURN 552
|
||||
i30030evb MACH_ARGONPLUSEVB ARGONPLUSEVB 553
|
||||
mxc27530evb MACH_SCMA11EVB SCMA11EVB 554
|
||||
i30030evb MACH_I30030EVB I30030EVB 553
|
||||
mxc27530evb MACH_MXC27530EVB MXC27530EVB 554
|
||||
smdk2800 MACH_SMDK2800 SMDK2800 555
|
||||
mtwilson MACH_MTWILSON MTWILSON 556
|
||||
ziti MACH_ZITI ZITI 557
|
||||
|
@ -647,7 +647,7 @@ sendt MACH_SENDT SENDT 630
|
|||
mx2jazz MACH_MX2JAZZ MX2JAZZ 631
|
||||
multiio MACH_MULTIIO MULTIIO 632
|
||||
hrdisplay MACH_HRDISPLAY HRDISPLAY 633
|
||||
mxc27530ads MACH_SCMA11BB SCMA11BB 634
|
||||
mxc27530ads MACH_MXC27530ADS MXC27530ADS 634
|
||||
trizeps3 MACH_TRIZEPS3 TRIZEPS3 635
|
||||
zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636
|
||||
zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637
|
||||
|
@ -721,7 +721,7 @@ gp32 MACH_GP32 GP32 706
|
|||
gem MACH_GEM GEM 707
|
||||
i858 MACH_I858 I858 708
|
||||
hx2750 MACH_HX2750 HX2750 709
|
||||
mxc91131evb MACH_ZEUSEVB ZEUSEVB 710
|
||||
mxc91131evb MACH_MXC91131EVB MXC91131EVB 710
|
||||
p700 MACH_P700 P700 711
|
||||
cpe MACH_CPE CPE 712
|
||||
spitz MACH_SPITZ SPITZ 713
|
||||
|
@ -802,7 +802,7 @@ cpuat91 MACH_CPUAT91 CPUAT91 787
|
|||
rea9200 MACH_REA9200 REA9200 788
|
||||
acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789
|
||||
ixp425 MACH_IXP425 IXP425 790
|
||||
i30030ads MACH_ARGONPLUSODYSSEY ARGONPLUSODYSSEY 791
|
||||
i30030ads MACH_I30030ADS I30030ADS 791
|
||||
perch MACH_PERCH PERCH 792
|
||||
eis05r1 MACH_EIS05R1 EIS05R1 793
|
||||
pepperpad MACH_PEPPERPAD PEPPERPAD 794
|
||||
|
@ -930,7 +930,7 @@ netclient MACH_NETCLIENT NETCLIENT 916
|
|||
xscale_palmtt5 MACH_XSCALE_PALMTT5 XSCALE_PALMTT5 917
|
||||
xscale_palmtc MACH_OMAP_PALMTC OMAP_PALMTC 918
|
||||
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
|
||||
eti3e524 MACH_TI3E524 TI3E524 922
|
||||
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
|
||||
tpf106 MACH_TPF106 TPF106 974
|
||||
at91rm9200kg MACH_AT91RM9200KG AT91RM9200KG 975
|
||||
racemt2 MACH_SLEDB SLEDB 976
|
||||
rcmt2 MACH_SLEDB SLEDB 976
|
||||
ontrack MACH_ONTRACK ONTRACK 977
|
||||
pm1200 MACH_PM1200 PM1200 978
|
||||
ess24562 MACH_ESS24XXX ESS24XXX 979
|
||||
|
@ -1022,7 +1022,7 @@ smdk2440 MACH_SMDK2440 SMDK2440 1008
|
|||
smdk2412 MACH_SMDK2412 SMDK2412 1009
|
||||
webbox MACH_WEBBOX WEBBOX 1010
|
||||
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
|
||||
ccm2200 MACH_CCM2200 CCM2200 1014
|
||||
etwarm MACH_ETWARM ETWARM 1015
|
||||
|
@ -1040,3 +1040,56 @@ edg79524 MACH_EDG79524 EDG79524 1026
|
|||
ai2410 MACH_AI2410 AI2410 1027
|
||||
ixp465 MACH_IXP465 IXP465 1028
|
||||
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
|
||||
AMD, Cyrix, and others.
|
||||
|
||||
config GENERIC_TIME
|
||||
bool
|
||||
default y
|
||||
|
||||
config SEMAPHORE_SLEEPERS
|
||||
bool
|
||||
default y
|
||||
|
@ -229,7 +233,7 @@ config NR_CPUS
|
|||
|
||||
config SCHED_SMT
|
||||
bool "SMT (Hyperthreading) scheduler support"
|
||||
depends on SMP
|
||||
depends on X86_HT
|
||||
help
|
||||
SMT scheduler support improves the CPU scheduler's decision making
|
||||
when dealing with Intel Pentium 4 chips with HyperThreading at a
|
||||
|
@ -238,7 +242,7 @@ config SCHED_SMT
|
|||
|
||||
config SCHED_MC
|
||||
bool "Multi-core scheduler support"
|
||||
depends on SMP
|
||||
depends on X86_HT
|
||||
default y
|
||||
help
|
||||
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
|
||||
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
|
||||
tristate "Toshiba Laptop support"
|
||||
---help---
|
||||
|
@ -721,7 +734,7 @@ config KEXEC
|
|||
help
|
||||
kexec is a system call that implements the ability to shutdown your
|
||||
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.
|
||||
|
||||
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
|
||||
/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
|
||||
|
||||
|
@ -1046,13 +1070,27 @@ config SCx200
|
|||
tristate "NatSemi SCx200 support"
|
||||
depends on !X86_VOYAGER
|
||||
help
|
||||
This provides basic support for the National Semiconductor SCx200
|
||||
processor. Right now this is just a driver for the GPIO pins.
|
||||
This provides basic support for National Semiconductor's
|
||||
(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
|
||||
module, it will be called scx200.
|
||||
config SCx200HR_TIMER
|
||||
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"
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ config M386
|
|||
- "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
|
||||
- "Geode GX/LX" For AMD Geode GX and LX processors.
|
||||
- "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".
|
||||
|
||||
|
|
|
@ -109,8 +109,13 @@ fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
|
|||
isoimage: $(BOOTIMAGE)
|
||||
-rm -rf $(obj)/isoimage
|
||||
mkdir $(obj)/isoimage
|
||||
cp `echo /usr/lib*/syslinux/isolinux.bin | awk '{ print $1; }'` \
|
||||
$(obj)/isoimage
|
||||
for i in lib lib64 share end ; do \
|
||||
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
|
||||
echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg
|
||||
if [ -f '$(FDINITRD)' ] ; then \
|
||||
|
|
|
@ -24,14 +24,6 @@
|
|||
|
||||
#undef memset
|
||||
#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))
|
||||
|
||||
typedef unsigned char uch;
|
||||
|
@ -93,7 +85,7 @@ static unsigned char *real_mode; /* Pointer to real-mode data */
|
|||
#endif
|
||||
#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
|
||||
|
||||
extern char input_data[];
|
||||
extern unsigned char input_data[];
|
||||
extern int input_len;
|
||||
|
||||
static long bytes_out = 0;
|
||||
|
@ -103,6 +95,9 @@ static unsigned long output_ptr = 0;
|
|||
static void *malloc(int size);
|
||||
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 *);
|
||||
|
||||
extern int end;
|
||||
|
@ -205,7 +200,7 @@ static void putstr(const char *s)
|
|||
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;
|
||||
char *ss = (char*)s;
|
||||
|
@ -214,14 +209,13 @@ static void* memset(void* s, int c, size_t n)
|
|||
return s;
|
||||
}
|
||||
|
||||
static void* memcpy(void* __dest, __const void* __src,
|
||||
size_t __n)
|
||||
static void* memcpy(void* dest, const void* src, unsigned n)
|
||||
{
|
||||
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];
|
||||
return __dest;
|
||||
for (i=0;i<n;i++) d[i] = s[i];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
|
@ -309,7 +303,7 @@ static void setup_normal_output_buffer(void)
|
|||
#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");
|
||||
#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;
|
||||
}
|
||||
|
||||
|
@ -324,11 +318,9 @@ static void setup_output_buffer_if_we_run_high(struct moveparams *mv)
|
|||
#ifdef STANDARD_MEMORY_BIOS_CALL
|
||||
if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory");
|
||||
#else
|
||||
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");
|
||||
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");
|
||||
#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_MAX : (unsigned int)real_mode) & ~0xfff;
|
||||
low_buffer_size = low_buffer_end - LOW_BUFFER_START;
|
||||
|
|
|
@ -1929,7 +1929,7 @@ skip10: movb %ah, %al
|
|||
ret
|
||||
|
||||
store_edid:
|
||||
#ifdef CONFIG_FB_FIRMWARE_EDID
|
||||
#ifdef CONFIG_FIRMWARE_EDID
|
||||
pushw %es # just save all registers
|
||||
pushw %ax
|
||||
pushw %bx
|
||||
|
@ -1947,6 +1947,22 @@ store_edid:
|
|||
rep
|
||||
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 $0x01, %bx
|
||||
movw $0x00, %cx
|
||||
|
@ -1954,6 +1970,7 @@ store_edid:
|
|||
movw $0x140, %di
|
||||
int $0x10
|
||||
|
||||
no_edid:
|
||||
popw %di # restore all registers
|
||||
popw %dx
|
||||
popw %cx
|
||||
|
|
|
@ -36,22 +36,19 @@
|
|||
.file "aes-i586-asm.S"
|
||||
.text
|
||||
|
||||
// aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])//
|
||||
// aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])//
|
||||
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
#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
|
||||
#define out_blk 12 // output byte array address parameter
|
||||
#define ctx 16 // AES context structure
|
||||
|
||||
// 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
|
||||
/* offsets in crypto_tfm structure */
|
||||
#define ekey (crypto_tfm_ctx_offset + 0)
|
||||
#define nrnd (crypto_tfm_ctx_offset + 256)
|
||||
#define dkey (crypto_tfm_ctx_offset + 260)
|
||||
|
||||
// register mapping for encrypt and decrypt subroutines
|
||||
|
||||
|
@ -220,6 +217,7 @@
|
|||
do_col (table, r5,r0,r1,r4, r2,r3); /* idx=r5 */
|
||||
|
||||
// AES (Rijndael) Encryption Subroutine
|
||||
/* void aes_enc_blk(struct crypto_tfm *tfm, u8 *out_blk, const u8 *in_blk) */
|
||||
|
||||
.global aes_enc_blk
|
||||
|
||||
|
@ -230,7 +228,7 @@
|
|||
|
||||
aes_enc_blk:
|
||||
push %ebp
|
||||
mov ctx(%esp),%ebp // pointer to context
|
||||
mov tfm(%esp),%ebp
|
||||
|
||||
// CAUTION: the order and the values used in these assigns
|
||||
// rely on the register mappings
|
||||
|
@ -295,6 +293,7 @@ aes_enc_blk:
|
|||
ret
|
||||
|
||||
// AES (Rijndael) Decryption Subroutine
|
||||
/* void aes_dec_blk(struct crypto_tfm *tfm, u8 *out_blk, const u8 *in_blk) */
|
||||
|
||||
.global aes_dec_blk
|
||||
|
||||
|
@ -305,7 +304,7 @@ aes_enc_blk:
|
|||
|
||||
aes_dec_blk:
|
||||
push %ebp
|
||||
mov ctx(%esp),%ebp // pointer to context
|
||||
mov tfm(%esp),%ebp
|
||||
|
||||
// CAUTION: the order and the values used in these assigns
|
||||
// rely on the register mappings
|
||||
|
|
|
@ -45,8 +45,8 @@
|
|||
#include <linux/crypto.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
asmlinkage void aes_enc_blk(const u8 *src, u8 *dst, void *ctx);
|
||||
asmlinkage void aes_dec_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(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
|
||||
|
||||
#define AES_MIN_KEY_SIZE 16
|
||||
#define AES_MAX_KEY_SIZE 32
|
||||
|
@ -378,12 +378,12 @@ static void gen_tabs(void)
|
|||
k[8*(i)+11] = ss[3]; \
|
||||
}
|
||||
|
||||
static int
|
||||
aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
|
||||
static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len, u32 *flags)
|
||||
{
|
||||
int i;
|
||||
u32 ss[8];
|
||||
struct aes_ctx *ctx = ctx_arg;
|
||||
struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
const __le32 *key = (const __le32 *)in_key;
|
||||
|
||||
/* encryption schedule */
|
||||
|
@ -464,15 +464,15 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
|
|||
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);
|
||||
}
|
||||
static inline void aes_decrypt(void *ctx, u8 *dst, const u8 *src)
|
||||
{
|
||||
aes_dec_blk(src, dst, ctx);
|
||||
aes_enc_blk(tfm, dst, src);
|
||||
}
|
||||
|
||||
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 = {
|
||||
.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 \
|
||||
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 \
|
||||
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 += timers/
|
||||
obj-y += acpi/
|
||||
obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.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_VM86) += vm86.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
obj-$(CONFIG_HPET_TIMER) += hpet.o
|
||||
obj-$(CONFIG_K8_NB) += k8.o
|
||||
|
||||
EXTRA_AFLAGS := -traditional
|
||||
|
||||
|
@ -76,3 +77,6 @@ SYSCFLAGS_vsyscall-syms.o = -r
|
|||
$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
|
||||
$(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE
|
||||
$(call if_changed,syscall)
|
||||
|
||||
k8-y += ../../x86_64/kernel/k8.o
|
||||
|
||||
|
|
|
@ -4,27 +4,41 @@
|
|||
#include <asm/alternative.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
# define DPRINTK(fmt, args...) printk(fmt, args)
|
||||
#else
|
||||
# define DPRINTK(fmt, args...)
|
||||
#endif
|
||||
static int no_replacement = 0;
|
||||
static int smp_alt_once = 0;
|
||||
static int debug_alternative = 0;
|
||||
|
||||
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
|
||||
as inline assembly strings in the include files and we cannot
|
||||
get them easily into strings. */
|
||||
asm("\t.data\nintelnops: "
|
||||
GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
|
||||
GENERIC_NOP7 GENERIC_NOP8);
|
||||
asm("\t.data\nk8nops: "
|
||||
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[];
|
||||
extern unsigned char intelnops[];
|
||||
static unsigned char *intel_nops[ASM_NOP_MAX+1] = {
|
||||
NULL,
|
||||
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 + 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] = {
|
||||
NULL,
|
||||
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 + 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] = {
|
||||
NULL,
|
||||
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 + 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 {
|
||||
int cpuid;
|
||||
unsigned char **noptable;
|
||||
|
@ -67,14 +107,6 @@ static struct nop {
|
|||
{ -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)
|
||||
{
|
||||
unsigned char **noptable = intel_nops;
|
||||
|
@ -89,6 +121,14 @@ static unsigned char** find_nop_table(void)
|
|||
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.
|
||||
This runs before SMP is initialized to avoid SMP problems with
|
||||
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();
|
||||
struct alt_instr *a;
|
||||
u8 *instr;
|
||||
int diff, i, k;
|
||||
|
||||
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);
|
||||
if (!boot_cpu_has(a->cpuid))
|
||||
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;
|
||||
/* Pad the rest with nops */
|
||||
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 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 *locks, void *locks_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;
|
||||
unsigned long flags;
|
||||
|
||||
if (no_replacement)
|
||||
return;
|
||||
|
||||
if (smp_alt_once) {
|
||||
if (boot_cpu_has(X86_FEATURE_UP))
|
||||
alternatives_smp_unlock(locks, locks_end,
|
||||
|
@ -235,7 +280,7 @@ void alternatives_smp_module_del(struct module *mod)
|
|||
struct smp_alt_module *item;
|
||||
unsigned long flags;
|
||||
|
||||
if (smp_alt_once)
|
||||
if (no_replacement || smp_alt_once)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&smp_alt, flags);
|
||||
|
@ -256,7 +301,7 @@ void alternatives_smp_switch(int smp)
|
|||
struct smp_alt_module *mod;
|
||||
unsigned long flags;
|
||||
|
||||
if (smp_alt_once)
|
||||
if (no_replacement || smp_alt_once)
|
||||
return;
|
||||
BUG_ON(!smp && (num_online_cpus() > 1));
|
||||
|
||||
|
@ -285,6 +330,13 @@ void alternatives_smp_switch(int smp)
|
|||
|
||||
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);
|
||||
|
||||
/* switch to patch-once-at-boottime-only mode and free the
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <asm/arch_hooks.h>
|
||||
#include <asm/hpet.h>
|
||||
#include <asm/i8253.h>
|
||||
#include <asm/nmi.h>
|
||||
|
||||
#include <mach_apic.h>
|
||||
#include <mach_apicdef.h>
|
||||
|
@ -156,7 +157,7 @@ void clear_local_APIC(void)
|
|||
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 (maxlvt >= 3) {
|
||||
|
@ -1117,7 +1118,18 @@ void disable_APIC_timer(void)
|
|||
unsigned long v;
|
||||
|
||||
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 polling;
|
||||
|
||||
polling = test_thread_flag(TIF_POLLING_NRFLAG);
|
||||
polling = !!(current_thread_info()->status & TS_POLLING);
|
||||
if (polling) {
|
||||
clear_thread_flag(TIF_POLLING_NRFLAG);
|
||||
current_thread_info()->status &= ~TS_POLLING;
|
||||
smp_mb__after_clear_bit();
|
||||
}
|
||||
if (!need_resched()) {
|
||||
|
@ -774,7 +774,7 @@ static int apm_do_idle(void)
|
|||
ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax);
|
||||
}
|
||||
if (polling)
|
||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||
current_thread_info()->status |= TS_POLLING;
|
||||
|
||||
if (!idled)
|
||||
return 0;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* to extract and format the required data.
|
||||
*/
|
||||
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/personality.h>
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include <asm/fixmap.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/elf.h>
|
||||
|
||||
#define DEFINE(sym, 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_addr_limit, thread_info, addr_limit);
|
||||
OFFSET(TI_restart_block, thread_info, restart_block);
|
||||
OFFSET(TI_sysenter_return, thread_info, sysenter_return);
|
||||
BLANK();
|
||||
|
||||
OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
|
||||
|
@ -68,5 +71,7 @@ void foo(void)
|
|||
sizeof(struct tss_struct));
|
||||
|
||||
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
|
||||
/*
|
||||
* On a AMD dual core setup the lower bits of the APIC id
|
||||
* distingush the cores. Assumes number of cores is a power
|
||||
* of two.
|
||||
* On a AMD multi core setup the lower bits of the APIC id
|
||||
* distingush the cores.
|
||||
*/
|
||||
if (c->x86_max_cores > 1) {
|
||||
int cpu = smp_processor_id();
|
||||
unsigned bits = 0;
|
||||
while ((1 << bits) < c->x86_max_cores)
|
||||
bits++;
|
||||
cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
|
||||
phys_proc_id[cpu] >>= bits;
|
||||
unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf;
|
||||
|
||||
if (bits == 0) {
|
||||
while ((1 << bits) < c->x86_max_cores)
|
||||
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",
|
||||
cpu, c->x86_max_cores, cpu_core_id[cpu]);
|
||||
cpu, c->x86_max_cores, c->cpu_core_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cpuid_eax(0x80000000) >= 0x80000006)
|
||||
num_cache_leaves = 3;
|
||||
}
|
||||
|
||||
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)
|
||||
c->x86_model += ((tfms >> 16) & 0xF) << 4;
|
||||
c->x86_mask = tfms & 15;
|
||||
#ifdef CONFIG_SMP
|
||||
#ifdef CONFIG_X86_HT
|
||||
c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
|
||||
#else
|
||||
c->apicid = (ebx >> 24) & 0xFF;
|
||||
|
@ -319,7 +319,7 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c)
|
|||
early_intel_workaround(c);
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
|
@ -477,11 +477,9 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
|||
{
|
||||
u32 eax, ebx, ecx, edx;
|
||||
int index_msb, core_bits;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
|
||||
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
|
||||
return;
|
||||
|
||||
|
@ -492,16 +490,17 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
|
|||
} else if (smp_num_siblings > 1 ) {
|
||||
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
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",
|
||||
phys_proc_id[cpu]);
|
||||
c->phys_proc_id);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
if (c->x86_max_cores > 1)
|
||||
printk(KERN_INFO "CPU: Processor Core ID: %d\n",
|
||||
cpu_core_id[cpu]);
|
||||
c->cpu_core_id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -613,6 +612,12 @@ void __cpuinit cpu_init(void)
|
|||
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
|
||||
* is that cpu_init() is called really early for the boot CPU
|
||||
|
@ -631,7 +636,7 @@ void __cpuinit cpu_init(void)
|
|||
local_irq_enable();
|
||||
}
|
||||
}
|
||||
|
||||
old_gdt:
|
||||
/*
|
||||
* Initialize the per-CPU GDT with the boot GDT,
|
||||
* 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
|
||||
* thing else to the Cyrix init function above - that should
|
||||
* 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
|
||||
* 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);
|
||||
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 */
|
||||
if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Changes:
|
||||
* Venkatesh Pallipadi : Adding cache identification through cpuid(4)
|
||||
* Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure.
|
||||
* Andi Kleen : CPUID4 emulation on AMD.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
@ -130,25 +131,111 @@ struct _cpuid4_info {
|
|||
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)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
union _cpuid4_leaf_eax cache_eax;
|
||||
union _cpuid4_leaf_eax eax;
|
||||
union _cpuid4_leaf_ebx ebx;
|
||||
union _cpuid4_leaf_ecx ecx;
|
||||
unsigned edx;
|
||||
|
||||
cpuid_count(4, index, &eax, &ebx, &ecx, &edx);
|
||||
cache_eax.full = eax;
|
||||
if (cache_eax.split.type == CACHE_TYPE_NULL)
|
||||
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
|
||||
amd_cpuid4(index, &eax, &ebx, &ecx);
|
||||
else
|
||||
cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
|
||||
if (eax.split.type == CACHE_TYPE_NULL)
|
||||
return -EIO; /* better error ? */
|
||||
|
||||
this_leaf->eax.full = eax;
|
||||
this_leaf->ebx.full = ebx;
|
||||
this_leaf->ecx.full = ecx;
|
||||
this_leaf->size = (this_leaf->ecx.split.number_of_sets + 1) *
|
||||
(this_leaf->ebx.split.coherency_line_size + 1) *
|
||||
(this_leaf->ebx.split.physical_line_partition + 1) *
|
||||
(this_leaf->ebx.split.ways_of_associativity + 1);
|
||||
this_leaf->eax = eax;
|
||||
this_leaf->ebx = ebx;
|
||||
this_leaf->ecx = ecx;
|
||||
this_leaf->size = (ecx.split.number_of_sets + 1) *
|
||||
(ebx.split.coherency_line_size + 1) *
|
||||
(ebx.split.physical_line_partition + 1) *
|
||||
(ebx.split.ways_of_associativity + 1);
|
||||
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_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
|
||||
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);
|
||||
#endif
|
||||
|
||||
|
@ -296,14 +383,14 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
|
|||
|
||||
if (new_l2) {
|
||||
l2 = new_l2;
|
||||
#ifdef CONFIG_SMP
|
||||
#ifdef CONFIG_X86_HT
|
||||
cpu_llc_id[cpu] = l2_id;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (new_l3) {
|
||||
l3 = new_l3;
|
||||
#ifdef CONFIG_SMP
|
||||
#ifdef CONFIG_X86_HT
|
||||
cpu_llc_id[cpu] = l3_id;
|
||||
#endif
|
||||
}
|
||||
|
@ -642,7 +729,7 @@ static void __cpuexit cache_remove_dev(struct sys_device * sys_dev)
|
|||
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 int cpu = (unsigned long)hcpu;
|
||||
|
@ -660,7 +747,7 @@ static int cacheinfo_cpu_callback(struct notifier_block *nfb,
|
|||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block cacheinfo_cpu_notifier =
|
||||
static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier =
|
||||
{
|
||||
.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
|
||||
* /dev/cpu/<cpu_nr>/cpuid instead.
|
||||
*/
|
||||
static char *x86_cap_flags[] = {
|
||||
static const char * const x86_cap_flags[] = {
|
||||
/* Intel-defined */
|
||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||
"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,
|
||||
};
|
||||
static char *x86_power_flags[] = {
|
||||
static const char * const x86_power_flags[] = {
|
||||
"ts", /* temperature sensor */
|
||||
"fid", /* frequency 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);
|
||||
#ifdef CONFIG_X86_HT
|
||||
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, "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);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -183,7 +183,7 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac
|
|||
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,
|
||||
};
|
||||
|
|
|
@ -120,14 +120,9 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu)
|
|||
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)
|
||||
{
|
||||
send_IPI_allbutself(APIC_DM_NMI);
|
||||
send_IPI_allbutself(NMI_VECTOR);
|
||||
}
|
||||
|
||||
static void nmi_shootdown_cpus(void)
|
||||
|
@ -163,7 +158,7 @@ static void nmi_shootdown_cpus(void)
|
|||
void machine_crash_shutdown(struct pt_regs *regs)
|
||||
{
|
||||
/* 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
|
||||
* to run successfully needs to happen here.
|
||||
*
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <asm/smp.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/dwarf2.h>
|
||||
#include "irq_vectors.h"
|
||||
|
||||
#define nr_syscalls ((syscall_table_size)/4)
|
||||
|
@ -82,34 +83,76 @@ VM_MASK = 0x00020000
|
|||
#define resume_kernel restore_nocheck
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VM86
|
||||
#define resume_userspace_sig check_userspace
|
||||
#else
|
||||
#define resume_userspace_sig resume_userspace
|
||||
#endif
|
||||
|
||||
#define SAVE_ALL \
|
||||
cld; \
|
||||
pushl %es; \
|
||||
CFI_ADJUST_CFA_OFFSET 4;\
|
||||
/*CFI_REL_OFFSET es, 0;*/\
|
||||
pushl %ds; \
|
||||
CFI_ADJUST_CFA_OFFSET 4;\
|
||||
/*CFI_REL_OFFSET ds, 0;*/\
|
||||
pushl %eax; \
|
||||
CFI_ADJUST_CFA_OFFSET 4;\
|
||||
CFI_REL_OFFSET eax, 0;\
|
||||
pushl %ebp; \
|
||||
CFI_ADJUST_CFA_OFFSET 4;\
|
||||
CFI_REL_OFFSET ebp, 0;\
|
||||
pushl %edi; \
|
||||
CFI_ADJUST_CFA_OFFSET 4;\
|
||||
CFI_REL_OFFSET edi, 0;\
|
||||
pushl %esi; \
|
||||
CFI_ADJUST_CFA_OFFSET 4;\
|
||||
CFI_REL_OFFSET esi, 0;\
|
||||
pushl %edx; \
|
||||
CFI_ADJUST_CFA_OFFSET 4;\
|
||||
CFI_REL_OFFSET edx, 0;\
|
||||
pushl %ecx; \
|
||||
CFI_ADJUST_CFA_OFFSET 4;\
|
||||
CFI_REL_OFFSET ecx, 0;\
|
||||
pushl %ebx; \
|
||||
CFI_ADJUST_CFA_OFFSET 4;\
|
||||
CFI_REL_OFFSET ebx, 0;\
|
||||
movl $(__USER_DS), %edx; \
|
||||
movl %edx, %ds; \
|
||||
movl %edx, %es;
|
||||
|
||||
#define RESTORE_INT_REGS \
|
||||
popl %ebx; \
|
||||
CFI_ADJUST_CFA_OFFSET -4;\
|
||||
CFI_RESTORE ebx;\
|
||||
popl %ecx; \
|
||||
CFI_ADJUST_CFA_OFFSET -4;\
|
||||
CFI_RESTORE ecx;\
|
||||
popl %edx; \
|
||||
CFI_ADJUST_CFA_OFFSET -4;\
|
||||
CFI_RESTORE edx;\
|
||||
popl %esi; \
|
||||
CFI_ADJUST_CFA_OFFSET -4;\
|
||||
CFI_RESTORE esi;\
|
||||
popl %edi; \
|
||||
CFI_ADJUST_CFA_OFFSET -4;\
|
||||
CFI_RESTORE edi;\
|
||||
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 \
|
||||
RESTORE_INT_REGS; \
|
||||
1: popl %ds; \
|
||||
CFI_ADJUST_CFA_OFFSET -4;\
|
||||
/*CFI_RESTORE ds;*/\
|
||||
2: popl %es; \
|
||||
CFI_ADJUST_CFA_OFFSET -4;\
|
||||
/*CFI_RESTORE es;*/\
|
||||
.section .fixup,"ax"; \
|
||||
3: movl $0,(%esp); \
|
||||
jmp 1b; \
|
||||
|
@ -122,13 +165,43 @@ VM_MASK = 0x00020000
|
|||
.long 2b,4b; \
|
||||
.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)
|
||||
CFI_STARTPROC
|
||||
pushl %eax
|
||||
CFI_ADJUST_CFA_OFFSET -4
|
||||
call schedule_tail
|
||||
GET_THREAD_INFO(%ebp)
|
||||
popl %eax
|
||||
CFI_ADJUST_CFA_OFFSET -4
|
||||
jmp syscall_exit
|
||||
CFI_ENDPROC
|
||||
|
||||
/*
|
||||
* 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
|
||||
ALIGN
|
||||
RING0_PTREGS_FRAME
|
||||
ret_from_exception:
|
||||
preempt_stop
|
||||
ret_from_intr:
|
||||
GET_THREAD_INFO(%ebp)
|
||||
check_userspace:
|
||||
movl EFLAGS(%esp), %eax # mix EFLAGS and CS
|
||||
movb CS(%esp), %al
|
||||
testl $(VM_MASK | 3), %eax
|
||||
|
@ -171,20 +246,38 @@ need_resched:
|
|||
call preempt_schedule_irq
|
||||
jmp need_resched
|
||||
#endif
|
||||
CFI_ENDPROC
|
||||
|
||||
/* SYSENTER_RETURN points to after the "sysenter" instruction in
|
||||
the vsyscall page. See vsyscall-sysentry.S, which defines the symbol. */
|
||||
|
||||
# sysenter call handler stub
|
||||
ENTRY(sysenter_entry)
|
||||
CFI_STARTPROC simple
|
||||
CFI_DEF_CFA esp, 0
|
||||
CFI_REGISTER esp, ebp
|
||||
movl TSS_sysenter_esp0(%esp),%esp
|
||||
sysenter_past_esp:
|
||||
sti
|
||||
pushl $(__USER_DS)
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
/*CFI_REL_OFFSET ss, 0*/
|
||||
pushl %ebp
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
CFI_REL_OFFSET esp, 0
|
||||
pushfl
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
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.
|
||||
|
@ -199,6 +292,7 @@ sysenter_past_esp:
|
|||
.previous
|
||||
|
||||
pushl %eax
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
SAVE_ALL
|
||||
GET_THREAD_INFO(%ebp)
|
||||
|
||||
|
@ -219,11 +313,14 @@ sysenter_past_esp:
|
|||
xorl %ebp,%ebp
|
||||
sti
|
||||
sysexit
|
||||
CFI_ENDPROC
|
||||
|
||||
|
||||
# system call handler stub
|
||||
ENTRY(system_call)
|
||||
RING0_INT_FRAME # can't unwind into user space anyway
|
||||
pushl %eax # save orig_eax
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
SAVE_ALL
|
||||
GET_THREAD_INFO(%ebp)
|
||||
testl $TF_MASK,EFLAGS(%esp)
|
||||
|
@ -256,10 +353,12 @@ restore_all:
|
|||
movb CS(%esp), %al
|
||||
andl $(VM_MASK | (4 << 8) | 3), %eax
|
||||
cmpl $((4 << 8) | 3), %eax
|
||||
CFI_REMEMBER_STATE
|
||||
je ldt_ss # returning to user-space with LDT SS
|
||||
restore_nocheck:
|
||||
RESTORE_REGS
|
||||
addl $4, %esp
|
||||
CFI_ADJUST_CFA_OFFSET -4
|
||||
1: iret
|
||||
.section .fixup,"ax"
|
||||
iret_exc:
|
||||
|
@ -273,6 +372,7 @@ iret_exc:
|
|||
.long 1b,iret_exc
|
||||
.previous
|
||||
|
||||
CFI_RESTORE_STATE
|
||||
ldt_ss:
|
||||
larl OLDSS(%esp), %eax
|
||||
jnz restore_nocheck
|
||||
|
@ -285,11 +385,13 @@ ldt_ss:
|
|||
* CPUs, which we can try to work around to make
|
||||
* dosemu and wine happy. */
|
||||
subl $8, %esp # reserve space for switch16 pointer
|
||||
CFI_ADJUST_CFA_OFFSET 8
|
||||
cli
|
||||
movl %esp, %eax
|
||||
/* Set up the 16bit stack frame with switch32 pointer on top,
|
||||
* and a switch16 pointer on top of the current frame. */
|
||||
call setup_x86_bogus_stack
|
||||
CFI_ADJUST_CFA_OFFSET -8 # frame has moved
|
||||
RESTORE_REGS
|
||||
lss 20+4(%esp), %esp # switch to 16bit stack
|
||||
1: iret
|
||||
|
@ -297,9 +399,11 @@ ldt_ss:
|
|||
.align 4
|
||||
.long 1b,iret_exc
|
||||
.previous
|
||||
CFI_ENDPROC
|
||||
|
||||
# perform work that needs to be done immediately before resumption
|
||||
ALIGN
|
||||
RING0_PTREGS_FRAME # can't unwind into user space anyway
|
||||
work_pending:
|
||||
testb $_TIF_NEED_RESCHED, %cl
|
||||
jz work_notifysig
|
||||
|
@ -323,18 +427,20 @@ work_notifysig: # deal with pending signals and
|
|||
# vm86-space
|
||||
xorl %edx, %edx
|
||||
call do_notify_resume
|
||||
jmp resume_userspace
|
||||
jmp resume_userspace_sig
|
||||
|
||||
ALIGN
|
||||
work_notifysig_v86:
|
||||
#ifdef CONFIG_VM86
|
||||
pushl %ecx # save ti_flags for do_notify_resume
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
call save_v86_state # %eax contains pt_regs pointer
|
||||
popl %ecx
|
||||
CFI_ADJUST_CFA_OFFSET -4
|
||||
movl %eax, %esp
|
||||
xorl %edx, %edx
|
||||
call do_notify_resume
|
||||
jmp resume_userspace
|
||||
jmp resume_userspace_sig
|
||||
#endif
|
||||
|
||||
# perform syscall exit tracing
|
||||
|
@ -363,19 +469,21 @@ syscall_exit_work:
|
|||
movl $1, %edx
|
||||
call do_syscall_trace
|
||||
jmp resume_userspace
|
||||
CFI_ENDPROC
|
||||
|
||||
ALIGN
|
||||
RING0_INT_FRAME # can't unwind into user space anyway
|
||||
syscall_fault:
|
||||
pushl %eax # save orig_eax
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
SAVE_ALL
|
||||
GET_THREAD_INFO(%ebp)
|
||||
movl $-EFAULT,EAX(%esp)
|
||||
jmp resume_userspace
|
||||
|
||||
ALIGN
|
||||
syscall_badsys:
|
||||
movl $-ENOSYS,EAX(%esp)
|
||||
jmp resume_userspace
|
||||
CFI_ENDPROC
|
||||
|
||||
#define FIXUP_ESPFIX_STACK \
|
||||
movl %esp, %eax; \
|
||||
|
@ -387,16 +495,21 @@ syscall_badsys:
|
|||
movl %eax, %esp;
|
||||
#define UNWIND_ESPFIX_STACK \
|
||||
pushl %eax; \
|
||||
CFI_ADJUST_CFA_OFFSET 4; \
|
||||
movl %ss, %eax; \
|
||||
/* see if on 16bit stack */ \
|
||||
cmpw $__ESPFIX_SS, %ax; \
|
||||
jne 28f; \
|
||||
movl $__KERNEL_DS, %edx; \
|
||||
movl %edx, %ds; \
|
||||
movl %edx, %es; \
|
||||
je 28f; \
|
||||
27: popl %eax; \
|
||||
CFI_ADJUST_CFA_OFFSET -4; \
|
||||
.section .fixup,"ax"; \
|
||||
28: movl $__KERNEL_DS, %eax; \
|
||||
movl %eax, %ds; \
|
||||
movl %eax, %es; \
|
||||
/* switch to 32bit stack */ \
|
||||
FIXUP_ESPFIX_STACK \
|
||||
28: popl %eax;
|
||||
FIXUP_ESPFIX_STACK; \
|
||||
jmp 27b; \
|
||||
.previous
|
||||
|
||||
/*
|
||||
* Build the entry stubs and pointer table with
|
||||
|
@ -408,9 +521,14 @@ ENTRY(interrupt)
|
|||
|
||||
vector=0
|
||||
ENTRY(irq_entries_start)
|
||||
RING0_INT_FRAME
|
||||
.rept NR_IRQS
|
||||
ALIGN
|
||||
1: pushl $vector-256
|
||||
.if vector
|
||||
CFI_ADJUST_CFA_OFFSET -4
|
||||
.endif
|
||||
1: pushl $~(vector)
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp common_interrupt
|
||||
.data
|
||||
.long 1b
|
||||
|
@ -424,60 +542,99 @@ common_interrupt:
|
|||
movl %esp,%eax
|
||||
call do_IRQ
|
||||
jmp ret_from_intr
|
||||
CFI_ENDPROC
|
||||
|
||||
#define BUILD_INTERRUPT(name, nr) \
|
||||
ENTRY(name) \
|
||||
pushl $nr-256; \
|
||||
SAVE_ALL \
|
||||
RING0_INT_FRAME; \
|
||||
pushl $~(nr); \
|
||||
CFI_ADJUST_CFA_OFFSET 4; \
|
||||
SAVE_ALL; \
|
||||
movl %esp,%eax; \
|
||||
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 */
|
||||
#include "entry_arch.h"
|
||||
|
||||
ENTRY(divide_error)
|
||||
RING0_INT_FRAME
|
||||
pushl $0 # no error code
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
pushl $do_divide_error
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
ALIGN
|
||||
error_code:
|
||||
pushl %ds
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
/*CFI_REL_OFFSET ds, 0*/
|
||||
pushl %eax
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
CFI_REL_OFFSET eax, 0
|
||||
xorl %eax, %eax
|
||||
pushl %ebp
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
CFI_REL_OFFSET ebp, 0
|
||||
pushl %edi
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
CFI_REL_OFFSET edi, 0
|
||||
pushl %esi
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
CFI_REL_OFFSET esi, 0
|
||||
pushl %edx
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
CFI_REL_OFFSET edx, 0
|
||||
decl %eax # eax = -1
|
||||
pushl %ecx
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
CFI_REL_OFFSET ecx, 0
|
||||
pushl %ebx
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
CFI_REL_OFFSET ebx, 0
|
||||
cld
|
||||
pushl %es
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
/*CFI_REL_OFFSET es, 0*/
|
||||
UNWIND_ESPFIX_STACK
|
||||
popl %ecx
|
||||
CFI_ADJUST_CFA_OFFSET -4
|
||||
/*CFI_REGISTER es, ecx*/
|
||||
movl ES(%esp), %edi # get the function address
|
||||
movl ORIG_EAX(%esp), %edx # get the error code
|
||||
movl %eax, ORIG_EAX(%esp)
|
||||
movl %ecx, ES(%esp)
|
||||
/*CFI_REL_OFFSET es, ES*/
|
||||
movl $(__USER_DS), %ecx
|
||||
movl %ecx, %ds
|
||||
movl %ecx, %es
|
||||
movl %esp,%eax # pt_regs pointer
|
||||
call *%edi
|
||||
jmp ret_from_exception
|
||||
CFI_ENDPROC
|
||||
|
||||
ENTRY(coprocessor_error)
|
||||
RING0_INT_FRAME
|
||||
pushl $0
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
pushl $do_coprocessor_error
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
|
||||
ENTRY(simd_coprocessor_error)
|
||||
RING0_INT_FRAME
|
||||
pushl $0
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
pushl $do_simd_coprocessor_error
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
|
||||
ENTRY(device_not_available)
|
||||
RING0_INT_FRAME
|
||||
pushl $-1 # mark this as an int
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
SAVE_ALL
|
||||
movl %cr0, %eax
|
||||
testl $0x4, %eax # EM (math emulation bit)
|
||||
|
@ -487,9 +644,12 @@ ENTRY(device_not_available)
|
|||
jmp ret_from_exception
|
||||
device_not_available_emulate:
|
||||
pushl $0 # temporary storage for ORIG_EIP
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
call math_emulate
|
||||
addl $4, %esp
|
||||
CFI_ADJUST_CFA_OFFSET -4
|
||||
jmp ret_from_exception
|
||||
CFI_ENDPROC
|
||||
|
||||
/*
|
||||
* Debug traps and NMI can happen at the one SYSENTER instruction
|
||||
|
@ -514,16 +674,19 @@ label: \
|
|||
pushl $sysenter_past_esp
|
||||
|
||||
KPROBE_ENTRY(debug)
|
||||
RING0_INT_FRAME
|
||||
cmpl $sysenter_entry,(%esp)
|
||||
jne debug_stack_correct
|
||||
FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
|
||||
debug_stack_correct:
|
||||
pushl $-1 # mark this as an int
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
SAVE_ALL
|
||||
xorl %edx,%edx # error code 0
|
||||
movl %esp,%eax # pt_regs pointer
|
||||
call do_debug
|
||||
jmp ret_from_exception
|
||||
CFI_ENDPROC
|
||||
.previous .text
|
||||
/*
|
||||
* NMI is doubly nasty. It can happen _while_ we're handling
|
||||
|
@ -534,14 +697,18 @@ debug_stack_correct:
|
|||
* fault happened on the sysenter path.
|
||||
*/
|
||||
ENTRY(nmi)
|
||||
RING0_INT_FRAME
|
||||
pushl %eax
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
movl %ss, %eax
|
||||
cmpw $__ESPFIX_SS, %ax
|
||||
popl %eax
|
||||
CFI_ADJUST_CFA_OFFSET -4
|
||||
je nmi_16bit_stack
|
||||
cmpl $sysenter_entry,(%esp)
|
||||
je nmi_stack_fixup
|
||||
pushl %eax
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
movl %esp,%eax
|
||||
/* Do not access memory above the end of our stack page,
|
||||
* it might not exist.
|
||||
|
@ -549,16 +716,19 @@ ENTRY(nmi)
|
|||
andl $(THREAD_SIZE-1),%eax
|
||||
cmpl $(THREAD_SIZE-20),%eax
|
||||
popl %eax
|
||||
CFI_ADJUST_CFA_OFFSET -4
|
||||
jae nmi_stack_correct
|
||||
cmpl $sysenter_entry,12(%esp)
|
||||
je nmi_debug_stack_check
|
||||
nmi_stack_correct:
|
||||
pushl %eax
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
SAVE_ALL
|
||||
xorl %edx,%edx # zero error code
|
||||
movl %esp,%eax # pt_regs pointer
|
||||
call do_nmi
|
||||
jmp restore_all
|
||||
CFI_ENDPROC
|
||||
|
||||
nmi_stack_fixup:
|
||||
FIX_STACK(12,nmi_stack_correct, 1)
|
||||
|
@ -574,94 +744,177 @@ nmi_debug_stack_check:
|
|||
jmp nmi_stack_correct
|
||||
|
||||
nmi_16bit_stack:
|
||||
RING0_INT_FRAME
|
||||
/* create the pointer to lss back */
|
||||
pushl %ss
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
pushl %esp
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
movzwl %sp, %esp
|
||||
addw $4, (%esp)
|
||||
/* copy the iret frame of 12 bytes */
|
||||
.rept 3
|
||||
pushl 16(%esp)
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
.endr
|
||||
pushl %eax
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
SAVE_ALL
|
||||
FIXUP_ESPFIX_STACK # %eax == %esp
|
||||
CFI_ADJUST_CFA_OFFSET -20 # the frame has now moved
|
||||
xorl %edx,%edx # zero error code
|
||||
call do_nmi
|
||||
RESTORE_REGS
|
||||
lss 12+4(%esp), %esp # back to 16bit stack
|
||||
1: iret
|
||||
CFI_ENDPROC
|
||||
.section __ex_table,"a"
|
||||
.align 4
|
||||
.long 1b,iret_exc
|
||||
.previous
|
||||
|
||||
KPROBE_ENTRY(int3)
|
||||
RING0_INT_FRAME
|
||||
pushl $-1 # mark this as an int
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
SAVE_ALL
|
||||
xorl %edx,%edx # zero error code
|
||||
movl %esp,%eax # pt_regs pointer
|
||||
call do_int3
|
||||
jmp ret_from_exception
|
||||
CFI_ENDPROC
|
||||
.previous .text
|
||||
|
||||
ENTRY(overflow)
|
||||
RING0_INT_FRAME
|
||||
pushl $0
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
pushl $do_overflow
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
|
||||
ENTRY(bounds)
|
||||
RING0_INT_FRAME
|
||||
pushl $0
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
pushl $do_bounds
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
|
||||
ENTRY(invalid_op)
|
||||
RING0_INT_FRAME
|
||||
pushl $0
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
pushl $do_invalid_op
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
|
||||
ENTRY(coprocessor_segment_overrun)
|
||||
RING0_INT_FRAME
|
||||
pushl $0
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
pushl $do_coprocessor_segment_overrun
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
|
||||
ENTRY(invalid_TSS)
|
||||
RING0_EC_FRAME
|
||||
pushl $do_invalid_TSS
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
|
||||
ENTRY(segment_not_present)
|
||||
RING0_EC_FRAME
|
||||
pushl $do_segment_not_present
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
|
||||
ENTRY(stack_segment)
|
||||
RING0_EC_FRAME
|
||||
pushl $do_stack_segment
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
|
||||
KPROBE_ENTRY(general_protection)
|
||||
RING0_EC_FRAME
|
||||
pushl $do_general_protection
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
.previous .text
|
||||
|
||||
ENTRY(alignment_check)
|
||||
RING0_EC_FRAME
|
||||
pushl $do_alignment_check
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
|
||||
KPROBE_ENTRY(page_fault)
|
||||
RING0_EC_FRAME
|
||||
pushl $do_page_fault
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
.previous .text
|
||||
|
||||
#ifdef CONFIG_X86_MCE
|
||||
ENTRY(machine_check)
|
||||
RING0_INT_FRAME
|
||||
pushl $0
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
pushl machine_check_vector
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
jmp error_code
|
||||
CFI_ENDPROC
|
||||
#endif
|
||||
|
||||
ENTRY(spurious_interrupt_bug)
|
||||
RING0_INT_FRAME
|
||||
pushl $0
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
pushl $do_spurious_interrupt_bug
|
||||
CFI_ADJUST_CFA_OFFSET 4
|
||||
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"
|
||||
#include "syscall_table.S"
|
||||
|
|
|
@ -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);
|
|
@ -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
|
||||
* to overdo spurious IRQ handling - it's usually a sign
|
||||
* 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
|
||||
* usually resulting from the 8259A-1|2 PICs) occur
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <asm/desc.h>
|
||||
#include <asm/timer.h>
|
||||
#include <asm/i8259.h>
|
||||
#include <asm/nmi.h>
|
||||
|
||||
#include <mach_apic.h>
|
||||
|
||||
|
@ -50,6 +51,7 @@ atomic_t irq_mis_count;
|
|||
static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
|
||||
|
||||
static DEFINE_SPINLOCK(ioapic_lock);
|
||||
static DEFINE_SPINLOCK(vector_lock);
|
||||
|
||||
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)
|
||||
{
|
||||
static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
|
||||
unsigned long flags;
|
||||
int vector;
|
||||
|
||||
BUG_ON(irq >= NR_IRQ_VECTORS);
|
||||
if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
|
||||
BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
|
||||
|
||||
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);
|
||||
}
|
||||
next:
|
||||
current_vector += 8;
|
||||
if (current_vector == SYSCALL_VECTOR)
|
||||
|
@ -1172,16 +1181,21 @@ next:
|
|||
|
||||
if (current_vector >= FIRST_SYSTEM_VECTOR) {
|
||||
offset++;
|
||||
if (!(offset%8))
|
||||
if (!(offset%8)) {
|
||||
spin_unlock_irqrestore(&vector_lock, flags);
|
||||
return -ENOSPC;
|
||||
}
|
||||
current_vector = FIRST_DEVICE_VECTOR + offset;
|
||||
}
|
||||
|
||||
vector_irq[current_vector] = irq;
|
||||
vector = current_vector;
|
||||
vector_irq[vector] = irq;
|
||||
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;
|
||||
|
@ -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)
|
||||
{
|
||||
if (use_pci_vector() && !platform_legacy_irq(irq)) {
|
||||
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
|
||||
trigger == IOAPIC_LEVEL)
|
||||
irq_desc[vector].handler = &ioapic_level_type;
|
||||
else
|
||||
irq_desc[vector].handler = &ioapic_edge_type;
|
||||
set_intr_gate(vector, interrupt[vector]);
|
||||
} else {
|
||||
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]);
|
||||
}
|
||||
unsigned idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq;
|
||||
|
||||
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
|
||||
trigger == IOAPIC_LEVEL)
|
||||
irq_desc[idx].handler = &ioapic_level_type;
|
||||
else
|
||||
irq_desc[idx].handler = &ioapic_edge_type;
|
||||
set_intr_gate(vector, interrupt[idx]);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* high bits used in ret_from_ code */
|
||||
int irq = regs->orig_eax & 0xff;
|
||||
/* high bit used in ret_from_ code */
|
||||
int irq = ~regs->orig_eax;
|
||||
#ifdef CONFIG_4KSTACKS
|
||||
union irq_ctx *curctx, *irqctx;
|
||||
u32 *isp;
|
||||
|
@ -100,8 +100,8 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
|||
* softirq checks work in the hardirq context.
|
||||
*/
|
||||
irqctx->tinfo.preempt_count =
|
||||
irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK |
|
||||
curctx->tinfo.preempt_count & SOFTIRQ_MASK;
|
||||
(irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
|
||||
(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
|
||||
|
||||
asm volatile(
|
||||
" xchgl %%ebx,%%esp \n"
|
||||
|
@ -227,7 +227,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||
if (i == 0) {
|
||||
seq_printf(p, " ");
|
||||
for_each_online_cpu(j)
|
||||
seq_printf(p, "CPU%d ",j);
|
||||
seq_printf(p, "CPU%-8d",j);
|
||||
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.
|
||||
*/
|
||||
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:
|
||||
return 0; /* can't boost conditional jump */
|
||||
case 0x90:
|
||||
/* can't boost call and pushf */
|
||||
return opcode != 0x9a && opcode != 0x9c;
|
||||
case 0xc0:
|
||||
/* can't boost undefined opcodes and soft-interruptions */
|
||||
return (0xc1 < opcode && opcode < 0xc6) ||
|
||||
(0xc7 < opcode && opcode < 0xcc) || opcode == 0xcf;
|
||||
/* can't boost software-interruptions */
|
||||
return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf;
|
||||
case 0xd0:
|
||||
/* can boost AA* and XLAT */
|
||||
return (opcode == 0xd4 || opcode == 0xd5 || opcode == 0xd7);
|
||||
case 0xe0:
|
||||
/* can boost in/out and (may be) jmps */
|
||||
return (0xe3 < opcode && opcode != 0xe8);
|
||||
/* can boost in/out and absolute jmps */
|
||||
return ((opcode & 0x04) || opcode == 0xea);
|
||||
case 0xf0:
|
||||
if ((opcode & 0x0c) == 0 && opcode != 0xf1)
|
||||
goto retry; /* lock/rep(ne) prefix */
|
||||
/* clear and set flags can be boost */
|
||||
return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
|
||||
default:
|
||||
/* currently, can't boost 2 bytes opcodes */
|
||||
return opcode != 0x0f;
|
||||
if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e)
|
||||
goto retry; /* prefixes */
|
||||
/* can't boost CS override and call */
|
||||
return (opcode != 0x2e && opcode != 0x9a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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));
|
||||
p->opcode = *p->addr;
|
||||
if (can_boost(p->opcode)) {
|
||||
if (can_boost(p->addr)) {
|
||||
p->ainsn.boostable = 0;
|
||||
} else {
|
||||
p->ainsn.boostable = -1;
|
||||
|
@ -208,7 +259,9 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||
struct kprobe_ctlblk *kcb;
|
||||
#ifdef CONFIG_PREEMPT
|
||||
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));
|
||||
|
||||
|
@ -285,22 +338,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||
/* handler has already set things up, so skip ss setup */
|
||||
return 1;
|
||||
|
||||
if (p->ainsn.boostable == 1 &&
|
||||
#ifdef CONFIG_PREEMPT
|
||||
!(pre_preempt_count) && /*
|
||||
* This enables booster when the direct
|
||||
* execution path aren't preempted.
|
||||
*/
|
||||
#endif /* CONFIG_PREEMPT */
|
||||
!p->post_handler && !p->break_handler ) {
|
||||
ss_probe:
|
||||
if (pre_preempt_count && p->ainsn.boostable == 1 && !p->post_handler){
|
||||
/* Boost up -- we can execute copied instructions directly */
|
||||
reset_current_kprobe();
|
||||
regs->eip = (unsigned long)p->ainsn.insn;
|
||||
preempt_enable_no_resched();
|
||||
return 1;
|
||||
}
|
||||
|
||||
ss_probe:
|
||||
prepare_singlestep(p, regs);
|
||||
kcb->kprobe_status = KPROBE_HIT_SS;
|
||||
return 1;
|
||||
|
|
|
@ -133,9 +133,9 @@ typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
|
|||
unsigned long start_address,
|
||||
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);
|
||||
const extern unsigned int relocate_new_kernel_size;
|
||||
extern const unsigned int relocate_new_kernel_size;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
static struct notifier_block msr_class_cpu_notifier =
|
||||
static struct notifier_block __cpuinitdata msr_class_cpu_notifier =
|
||||
{
|
||||
.notifier_call = msr_class_cpu_callback,
|
||||
};
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче