mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 11:16:11 +00:00
Merge branch 'for-rmk' of git://linux-arm.org/linux-2.6
This commit is contained in:
commit
40d743b8c1
2683 changed files with 353759 additions and 233832 deletions
2
CREDITS
2
CREDITS
|
@ -2800,7 +2800,7 @@ D: Starter of Linux1394 effort
|
|||
S: ask per mail for current address
|
||||
|
||||
N: Nicolas Pitre
|
||||
E: nico@cam.org
|
||||
E: nico@fluxnic.net
|
||||
D: StrongARM SA1100 support integrator & hacker
|
||||
D: Xscale PXA architecture
|
||||
D: unified SMC 91C9x/91C11x ethernet driver (smc91x)
|
||||
|
|
|
@ -84,6 +84,16 @@ Description:
|
|||
from this part of the device tree.
|
||||
Depends on CONFIG_HOTPLUG.
|
||||
|
||||
What: /sys/bus/pci/devices/.../reset
|
||||
Date: July 2009
|
||||
Contact: Michael S. Tsirkin <mst@redhat.com>
|
||||
Description:
|
||||
Some devices allow an individual function to be reset
|
||||
without affecting other functions in the same device.
|
||||
For devices that have this support, a file named reset
|
||||
will be present in sysfs. Writing 1 to this file
|
||||
will perform reset.
|
||||
|
||||
What: /sys/bus/pci/devices/.../vpd
|
||||
Date: February 2008
|
||||
Contact: Ben Hutchings <bhutchings@solarflare.com>
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
<year>2006-2008</year>
|
||||
<holder>Hans-Jürgen Koch.</holder>
|
||||
</copyright>
|
||||
<copyright>
|
||||
<year>2009</year>
|
||||
<holder>Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)</holder>
|
||||
</copyright>
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
|
@ -41,6 +45,13 @@ GPL version 2.
|
|||
</abstract>
|
||||
|
||||
<revhistory>
|
||||
<revision>
|
||||
<revnumber>0.9</revnumber>
|
||||
<date>2009-07-16</date>
|
||||
<authorinitials>mst</authorinitials>
|
||||
<revremark>Added generic pci driver
|
||||
</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>0.8</revnumber>
|
||||
<date>2008-12-24</date>
|
||||
|
@ -809,6 +820,158 @@ framework to set up sysfs files for this region. Simply leave it alone.
|
|||
|
||||
</chapter>
|
||||
|
||||
<chapter id="uio_pci_generic" xreflabel="Using Generic driver for PCI cards">
|
||||
<?dbhtml filename="uio_pci_generic.html"?>
|
||||
<title>Generic PCI UIO driver</title>
|
||||
<para>
|
||||
The generic driver is a kernel module named uio_pci_generic.
|
||||
It can work with any device compliant to PCI 2.3 (circa 2002) and
|
||||
any compliant PCI Express device. Using this, you only need to
|
||||
write the userspace driver, removing the need to write
|
||||
a hardware-specific kernel module.
|
||||
</para>
|
||||
|
||||
<sect1 id="uio_pci_generic_binding">
|
||||
<title>Making the driver recognize the device</title>
|
||||
<para>
|
||||
Since the driver does not declare any device ids, it will not get loaded
|
||||
automatically and will not automatically bind to any devices, you must load it
|
||||
and allocate id to the driver yourself. For example:
|
||||
<programlisting>
|
||||
modprobe uio_pci_generic
|
||||
echo "8086 10f5" > /sys/bus/pci/drivers/uio_pci_generic/new_id
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
If there already is a hardware specific kernel driver for your device, the
|
||||
generic driver still won't bind to it, in this case if you want to use the
|
||||
generic driver (why would you?) you'll have to manually unbind the hardware
|
||||
specific driver and bind the generic driver, like this:
|
||||
<programlisting>
|
||||
echo -n 0000:00:19.0 > /sys/bus/pci/drivers/e1000e/unbind
|
||||
echo -n 0000:00:19.0 > /sys/bus/pci/drivers/uio_pci_generic/bind
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
You can verify that the device has been bound to the driver
|
||||
by looking for it in sysfs, for example like the following:
|
||||
<programlisting>
|
||||
ls -l /sys/bus/pci/devices/0000:00:19.0/driver
|
||||
</programlisting>
|
||||
Which if successful should print
|
||||
<programlisting>
|
||||
.../0000:00:19.0/driver -> ../../../bus/pci/drivers/uio_pci_generic
|
||||
</programlisting>
|
||||
Note that the generic driver will not bind to old PCI 2.2 devices.
|
||||
If binding the device failed, run the following command:
|
||||
<programlisting>
|
||||
dmesg
|
||||
</programlisting>
|
||||
and look in the output for failure reasons
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="uio_pci_generic_internals">
|
||||
<title>Things to know about uio_pci_generic</title>
|
||||
<para>
|
||||
Interrupts are handled using the Interrupt Disable bit in the PCI command
|
||||
register and Interrupt Status bit in the PCI status register. All devices
|
||||
compliant to PCI 2.3 (circa 2002) and all compliant PCI Express devices should
|
||||
support these bits. uio_pci_generic detects this support, and won't bind to
|
||||
devices which do not support the Interrupt Disable Bit in the command register.
|
||||
</para>
|
||||
<para>
|
||||
On each interrupt, uio_pci_generic sets the Interrupt Disable bit.
|
||||
This prevents the device from generating further interrupts
|
||||
until the bit is cleared. The userspace driver should clear this
|
||||
bit before blocking and waiting for more interrupts.
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="uio_pci_generic_userspace">
|
||||
<title>Writing userspace driver using uio_pci_generic</title>
|
||||
<para>
|
||||
Userspace driver can use pci sysfs interface, or the
|
||||
libpci libray that wraps it, to talk to the device and to
|
||||
re-enable interrupts by writing to the command register.
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="uio_pci_generic_example">
|
||||
<title>Example code using uio_pci_generic</title>
|
||||
<para>
|
||||
Here is some sample userspace driver code using uio_pci_generic:
|
||||
<programlisting>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int uiofd;
|
||||
int configfd;
|
||||
int err;
|
||||
int i;
|
||||
unsigned icount;
|
||||
unsigned char command_high;
|
||||
|
||||
uiofd = open("/dev/uio0", O_RDONLY);
|
||||
if (uiofd < 0) {
|
||||
perror("uio open:");
|
||||
return errno;
|
||||
}
|
||||
configfd = open("/sys/class/uio/uio0/device/config", O_RDWR);
|
||||
if (uiofd < 0) {
|
||||
perror("config open:");
|
||||
return errno;
|
||||
}
|
||||
|
||||
/* Read and cache command value */
|
||||
err = pread(configfd, &command_high, 1, 5);
|
||||
if (err != 1) {
|
||||
perror("command config read:");
|
||||
return errno;
|
||||
}
|
||||
command_high &= ~0x4;
|
||||
|
||||
for(i = 0;; ++i) {
|
||||
/* Print out a message, for debugging. */
|
||||
if (i == 0)
|
||||
fprintf(stderr, "Started uio test driver.\n");
|
||||
else
|
||||
fprintf(stderr, "Interrupts: %d\n", icount);
|
||||
|
||||
/****************************************/
|
||||
/* Here we got an interrupt from the
|
||||
device. Do something to it. */
|
||||
/****************************************/
|
||||
|
||||
/* Re-enable interrupts. */
|
||||
err = pwrite(configfd, &command_high, 1, 5);
|
||||
if (err != 1) {
|
||||
perror("config write:");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wait for next interrupt. */
|
||||
err = read(uiofd, &icount, 4);
|
||||
if (err != 4) {
|
||||
perror("uio read:");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return errno;
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
||||
|
||||
<appendix id="app1">
|
||||
<title>Further information</title>
|
||||
<itemizedlist>
|
||||
|
|
|
@ -4,15 +4,17 @@
|
|||
February 2, 2006
|
||||
|
||||
Current document maintainer:
|
||||
Linas Vepstas <linas@austin.ibm.com>
|
||||
Linas Vepstas <linasvepstas@gmail.com>
|
||||
updated by Richard Lary <rlary@us.ibm.com>
|
||||
and Mike Mason <mmlnx@us.ibm.com> on 27-Jul-2009
|
||||
|
||||
|
||||
Many PCI bus controllers are able to detect a variety of hardware
|
||||
PCI errors on the bus, such as parity errors on the data and address
|
||||
busses, as well as SERR and PERR errors. Some of the more advanced
|
||||
chipsets are able to deal with these errors; these include PCI-E chipsets,
|
||||
and the PCI-host bridges found on IBM Power4 and Power5-based pSeries
|
||||
boxes. A typical action taken is to disconnect the affected device,
|
||||
and the PCI-host bridges found on IBM Power4, Power5 and Power6-based
|
||||
pSeries boxes. A typical action taken is to disconnect the affected device,
|
||||
halting all I/O to it. The goal of a disconnection is to avoid system
|
||||
corruption; for example, to halt system memory corruption due to DMA's
|
||||
to "wild" addresses. Typically, a reconnection mechanism is also
|
||||
|
@ -37,10 +39,11 @@ is forced by the need to handle multi-function devices, that is,
|
|||
devices that have multiple device drivers associated with them.
|
||||
In the first stage, each driver is allowed to indicate what type
|
||||
of reset it desires, the choices being a simple re-enabling of I/O
|
||||
or requesting a hard reset (a full electrical #RST of the PCI card).
|
||||
If any driver requests a full reset, that is what will be done.
|
||||
or requesting a slot reset.
|
||||
|
||||
After a full reset and/or a re-enabling of I/O, all drivers are
|
||||
If any driver requests a slot reset, that is what will be done.
|
||||
|
||||
After a reset and/or a re-enabling of I/O, all drivers are
|
||||
again notified, so that they may then perform any device setup/config
|
||||
that may be required. After these have all completed, a final
|
||||
"resume normal operations" event is sent out.
|
||||
|
@ -101,7 +104,7 @@ if it implements any, it must implement error_detected(). If a callback
|
|||
is not implemented, the corresponding feature is considered unsupported.
|
||||
For example, if mmio_enabled() and resume() aren't there, then it
|
||||
is assumed that the driver is not doing any direct recovery and requires
|
||||
a reset. If link_reset() is not implemented, the card is assumed as
|
||||
a slot reset. If link_reset() is not implemented, the card is assumed to
|
||||
not care about link resets. Typically a driver will want to know about
|
||||
a slot_reset().
|
||||
|
||||
|
@ -111,7 +114,7 @@ sequence described below.
|
|||
|
||||
STEP 0: Error Event
|
||||
-------------------
|
||||
PCI bus error is detect by the PCI hardware. On powerpc, the slot
|
||||
A PCI bus error is detected by the PCI hardware. On powerpc, the slot
|
||||
is isolated, in that all I/O is blocked: all reads return 0xffffffff,
|
||||
all writes are ignored.
|
||||
|
||||
|
@ -139,7 +142,7 @@ The driver must return one of the following result codes:
|
|||
a chance to extract some diagnostic information (see
|
||||
mmio_enable, below).
|
||||
- PCI_ERS_RESULT_NEED_RESET:
|
||||
Driver returns this if it can't recover without a hard
|
||||
Driver returns this if it can't recover without a
|
||||
slot reset.
|
||||
- PCI_ERS_RESULT_DISCONNECT:
|
||||
Driver returns this if it doesn't want to recover at all.
|
||||
|
@ -169,11 +172,11 @@ is STEP 6 (Permanent Failure).
|
|||
|
||||
>>> The current powerpc implementation doesn't much care if the device
|
||||
>>> attempts I/O at this point, or not. I/O's will fail, returning
|
||||
>>> a value of 0xff on read, and writes will be dropped. If the device
|
||||
>>> driver attempts more than 10K I/O's to a frozen adapter, it will
|
||||
>>> assume that the device driver has gone into an infinite loop, and
|
||||
>>> it will panic the kernel. There doesn't seem to be any other
|
||||
>>> way of stopping a device driver that insists on spinning on I/O.
|
||||
>>> a value of 0xff on read, and writes will be dropped. If more than
|
||||
>>> EEH_MAX_FAILS I/O's are attempted to a frozen adapter, EEH
|
||||
>>> assumes that the device driver has gone into an infinite loop
|
||||
>>> and prints an error to syslog. A reboot is then required to
|
||||
>>> get the device working again.
|
||||
|
||||
STEP 2: MMIO Enabled
|
||||
-------------------
|
||||
|
@ -182,15 +185,14 @@ DMA), and then calls the mmio_enabled() callback on all affected
|
|||
device drivers.
|
||||
|
||||
This is the "early recovery" call. IOs are allowed again, but DMA is
|
||||
not (hrm... to be discussed, I prefer not), with some restrictions. This
|
||||
is NOT a callback for the driver to start operations again, only to
|
||||
peek/poke at the device, extract diagnostic information, if any, and
|
||||
eventually do things like trigger a device local reset or some such,
|
||||
but not restart operations. This is callback is made if all drivers on
|
||||
a segment agree that they can try to recover and if no automatic link reset
|
||||
was performed by the HW. If the platform can't just re-enable IOs without
|
||||
a slot reset or a link reset, it wont call this callback, and instead
|
||||
will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
|
||||
not, with some restrictions. This is NOT a callback for the driver to
|
||||
start operations again, only to peek/poke at the device, extract diagnostic
|
||||
information, if any, and eventually do things like trigger a device local
|
||||
reset or some such, but not restart operations. This callback is made if
|
||||
all drivers on a segment agree that they can try to recover and if no automatic
|
||||
link reset was performed by the HW. If the platform can't just re-enable IOs
|
||||
without a slot reset or a link reset, it will not call this callback, and
|
||||
instead will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
|
||||
|
||||
>>> The following is proposed; no platform implements this yet:
|
||||
>>> Proposal: All I/O's should be done _synchronously_ from within
|
||||
|
@ -228,9 +230,6 @@ proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations).
|
|||
If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform
|
||||
proceeds to STEP 4 (Slot Reset)
|
||||
|
||||
>>> The current powerpc implementation does not implement this callback.
|
||||
|
||||
|
||||
STEP 3: Link Reset
|
||||
------------------
|
||||
The platform resets the link, and then calls the link_reset() callback
|
||||
|
@ -253,16 +252,33 @@ The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5
|
|||
|
||||
>>> The current powerpc implementation does not implement this callback.
|
||||
|
||||
|
||||
STEP 4: Slot Reset
|
||||
------------------
|
||||
The platform performs a soft or hard reset of the device, and then
|
||||
calls the slot_reset() callback.
|
||||
|
||||
A soft reset consists of asserting the adapter #RST line and then
|
||||
In response to a return value of PCI_ERS_RESULT_NEED_RESET, the
|
||||
the platform will peform a slot reset on the requesting PCI device(s).
|
||||
The actual steps taken by a platform to perform a slot reset
|
||||
will be platform-dependent. Upon completion of slot reset, the
|
||||
platform will call the device slot_reset() callback.
|
||||
|
||||
Powerpc platforms implement two levels of slot reset:
|
||||
soft reset(default) and fundamental(optional) reset.
|
||||
|
||||
Powerpc soft reset consists of asserting the adapter #RST line and then
|
||||
restoring the PCI BAR's and PCI configuration header to a state
|
||||
that is equivalent to what it would be after a fresh system
|
||||
power-on followed by power-on BIOS/system firmware initialization.
|
||||
Soft reset is also known as hot-reset.
|
||||
|
||||
Powerpc fundamental reset is supported by PCI Express cards only
|
||||
and results in device's state machines, hardware logic, port states and
|
||||
configuration registers to initialize to their default conditions.
|
||||
|
||||
For most PCI devices, a soft reset will be sufficient for recovery.
|
||||
Optional fundamental reset is provided to support a limited number
|
||||
of PCI Express PCI devices for which a soft reset is not sufficient
|
||||
for recovery.
|
||||
|
||||
If the platform supports PCI hotplug, then the reset might be
|
||||
performed by toggling the slot electrical power off/on.
|
||||
|
||||
|
@ -274,10 +290,12 @@ may result in hung devices, kernel panics, or silent data corruption.
|
|||
|
||||
This call gives drivers the chance to re-initialize the hardware
|
||||
(re-download firmware, etc.). At this point, the driver may assume
|
||||
that he card is in a fresh state and is fully functional. In
|
||||
particular, interrupt generation should work normally.
|
||||
that the card is in a fresh state and is fully functional. The slot
|
||||
is unfrozen and the driver has full access to PCI config space,
|
||||
memory mapped I/O space and DMA. Interrupts (Legacy, MSI, or MSI-X)
|
||||
will also be available.
|
||||
|
||||
Drivers should not yet restart normal I/O processing operations
|
||||
Drivers should not restart normal I/O processing operations
|
||||
at this point. If all device drivers report success on this
|
||||
callback, the platform will call resume() to complete the sequence,
|
||||
and let the driver restart normal I/O processing.
|
||||
|
@ -302,11 +320,21 @@ driver performs device init only from PCI function 0:
|
|||
- PCI_ERS_RESULT_DISCONNECT
|
||||
Same as above.
|
||||
|
||||
Drivers for PCI Express cards that require a fundamental reset must
|
||||
set the needs_freset bit in the pci_dev structure in their probe function.
|
||||
For example, the QLogic qla2xxx driver sets the needs_freset bit for certain
|
||||
PCI card types:
|
||||
|
||||
+ /* Set EEH reset type to fundamental if required by hba */
|
||||
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha))
|
||||
+ pdev->needs_freset = 1;
|
||||
+
|
||||
|
||||
Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent
|
||||
Failure).
|
||||
|
||||
>>> The current powerpc implementation does not currently try a
|
||||
>>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
|
||||
>>> The current powerpc implementation does not try a power-cycle
|
||||
>>> reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
|
||||
>>> However, it probably should.
|
||||
|
||||
|
||||
|
@ -348,7 +376,7 @@ software errors.
|
|||
|
||||
Conclusion; General Remarks
|
||||
---------------------------
|
||||
The way those callbacks are called is platform policy. A platform with
|
||||
The way the callbacks are called is platform policy. A platform with
|
||||
no slot reset capability may want to just "ignore" drivers that can't
|
||||
recover (disconnect them) and try to let other cards on the same segment
|
||||
recover. Keep in mind that in most real life cases, though, there will
|
||||
|
@ -361,8 +389,8 @@ That is, the recovery API only requires that:
|
|||
|
||||
- There is no guarantee that interrupt delivery can proceed from any
|
||||
device on the segment starting from the error detection and until the
|
||||
resume callback is sent, at which point interrupts are expected to be
|
||||
fully operational.
|
||||
slot_reset callback is called, at which point interrupts are expected
|
||||
to be fully operational.
|
||||
|
||||
- There is no guarantee that interrupt delivery is stopped, that is,
|
||||
a driver that gets an interrupt after detecting an error, or that detects
|
||||
|
@ -381,16 +409,23 @@ anyway :)
|
|||
>>> Implementation details for the powerpc platform are discussed in
|
||||
>>> the file Documentation/powerpc/eeh-pci-error-recovery.txt
|
||||
|
||||
>>> As of this writing, there are six device drivers with patches
|
||||
>>> implementing error recovery. Not all of these patches are in
|
||||
>>> As of this writing, there is a growing list of device drivers with
|
||||
>>> patches implementing error recovery. Not all of these patches are in
|
||||
>>> mainline yet. These may be used as "examples":
|
||||
>>>
|
||||
>>> drivers/scsi/ipr.c
|
||||
>>> drivers/scsi/sym53cxx_2
|
||||
>>> drivers/scsi/ipr
|
||||
>>> drivers/scsi/sym53c8xx_2
|
||||
>>> drivers/scsi/qla2xxx
|
||||
>>> drivers/scsi/lpfc
|
||||
>>> drivers/next/bnx2.c
|
||||
>>> drivers/next/e100.c
|
||||
>>> drivers/net/e1000
|
||||
>>> drivers/net/e1000e
|
||||
>>> drivers/net/ixgb
|
||||
>>> drivers/net/ixgbe
|
||||
>>> drivers/net/cxgb3
|
||||
>>> drivers/net/s2io.c
|
||||
>>> drivers/net/qlge
|
||||
|
||||
The End
|
||||
-------
|
||||
|
|
|
@ -40,4 +40,4 @@ Notes:
|
|||
mode, the timing is off so the image is corrupted. This will be
|
||||
fixed soon.
|
||||
|
||||
Any contribution can be sent to nico@cam.org and will be greatly welcome!
|
||||
Any contribution can be sent to nico@fluxnic.net and will be greatly welcome!
|
||||
|
|
|
@ -240,7 +240,7 @@ Then, rebooting the Assabet is just a matter of waiting for the login prompt.
|
|||
|
||||
|
||||
Nicolas Pitre
|
||||
nico@cam.org
|
||||
nico@fluxnic.net
|
||||
June 12, 2001
|
||||
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ little modifications.
|
|||
|
||||
Any contribution is welcome.
|
||||
|
||||
Please send patches to nico@cam.org
|
||||
Please send patches to nico@fluxnic.net
|
||||
|
||||
Have Fun !
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ For more details, contact Applied Data Systems or see
|
|||
http://www.applieddata.net/products.html
|
||||
|
||||
The original Linux support for this product has been provided by
|
||||
Nicolas Pitre <nico@cam.org>. Continued development work by
|
||||
Nicolas Pitre <nico@fluxnic.net>. Continued development work by
|
||||
Woojung Huh <whuh@applieddata.net>
|
||||
|
||||
It's currently possible to mount a root filesystem via NFS providing a
|
||||
|
@ -94,5 +94,5 @@ Notes:
|
|||
mode, the timing is off so the image is corrupted. This will be
|
||||
fixed soon.
|
||||
|
||||
Any contribution can be sent to nico@cam.org and will be greatly welcome!
|
||||
Any contribution can be sent to nico@fluxnic.net and will be greatly welcome!
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ For more details, contact Applied Data Systems or see
|
|||
http://www.applieddata.net/products.html
|
||||
|
||||
The original Linux support for this product has been provided by
|
||||
Nicolas Pitre <nico@cam.org>. Continued development work by
|
||||
Nicolas Pitre <nico@fluxnic.net>. Continued development work by
|
||||
Woojung Huh <whuh@applieddata.net>
|
||||
|
||||
Use 'make graphicsmaster_config' before any 'make config'.
|
||||
|
@ -50,4 +50,4 @@ Notes:
|
|||
mode, the timing is off so the image is corrupted. This will be
|
||||
fixed soon.
|
||||
|
||||
Any contribution can be sent to nico@cam.org and will be greatly welcome!
|
||||
Any contribution can be sent to nico@fluxnic.net and will be greatly welcome!
|
||||
|
|
|
@ -9,7 +9,7 @@ Of course Victor is using Linux as its main operating system.
|
|||
The Victor implementation for Linux is maintained by Nicolas Pitre:
|
||||
|
||||
nico@visuaide.com
|
||||
nico@cam.org
|
||||
nico@fluxnic.net
|
||||
|
||||
For any comments, please feel free to contact me through the above
|
||||
addresses.
|
||||
|
|
|
@ -152,7 +152,6 @@ piggy.gz
|
|||
piggyback
|
||||
pnmtologo
|
||||
ppc_defs.h*
|
||||
promcon_tbl.c
|
||||
pss_boot.h
|
||||
qconf
|
||||
raid6altivec*.c
|
||||
|
|
|
@ -428,16 +428,6 @@ Who: Johannes Berg <johannes@sipsolutions.net>
|
|||
|
||||
----------------------------
|
||||
|
||||
What: CONFIG_X86_OLD_MCE
|
||||
When: 2.6.32
|
||||
Why: Remove the old legacy 32bit machine check code. This has been
|
||||
superseded by the newer machine check code from the 64bit port,
|
||||
but the old version has been kept around for easier testing. Note this
|
||||
doesn't impact the old P5 and WinChip machine check handlers.
|
||||
Who: Andi Kleen <andi@firstfloor.org>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: lock_policy_rwsem_* and unlock_policy_rwsem_* will not be
|
||||
exported interface anymore.
|
||||
When: 2.6.33
|
||||
|
|
|
@ -2,11 +2,11 @@ Kernel driver pcf8591
|
|||
=====================
|
||||
|
||||
Supported chips:
|
||||
* Philips PCF8591
|
||||
* Philips/NXP PCF8591
|
||||
Prefix: 'pcf8591'
|
||||
Addresses scanned: I2C 0x48 - 0x4f
|
||||
Datasheet: Publicly available at the Philips Semiconductor website
|
||||
http://www.semiconductors.philips.com/pip/PCF8591P.html
|
||||
Datasheet: Publicly available at the NXP website
|
||||
http://www.nxp.com/pip/PCF8591_6.html
|
||||
|
||||
Authors:
|
||||
Aurelien Jarno <aurelien@aurel32.net>
|
||||
|
@ -16,9 +16,10 @@ Authors:
|
|||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The PCF8591 is an 8-bit A/D and D/A converter (4 analog inputs and one
|
||||
analog output) for the I2C bus produced by Philips Semiconductors. It
|
||||
is designed to provide a byte I2C interface to up to 4 separate devices.
|
||||
analog output) for the I2C bus produced by Philips Semiconductors (now NXP).
|
||||
It is designed to provide a byte I2C interface to up to 4 separate devices.
|
||||
|
||||
The PCF8591 has 4 analog inputs programmable as single-ended or
|
||||
differential inputs :
|
||||
|
@ -58,8 +59,8 @@ Accessing PCF8591 via /sys interface
|
|||
-------------------------------------
|
||||
|
||||
! Be careful !
|
||||
The PCF8591 is plainly impossible to detect ! Stupid chip.
|
||||
So every chip with address in the interval [48..4f] is
|
||||
The PCF8591 is plainly impossible to detect! Stupid chip.
|
||||
So every chip with address in the interval [0x48..0x4f] is
|
||||
detected as PCF8591. If you have other chips in this address
|
||||
range, the workaround is to load this module after the one
|
||||
for your others chips.
|
||||
|
@ -67,19 +68,20 @@ for your others chips.
|
|||
On detection (i.e. insmod, modprobe et al.), directories are being
|
||||
created for each detected PCF8591:
|
||||
|
||||
/sys/bus/devices/<0>-<1>/
|
||||
/sys/bus/i2c/devices/<0>-<1>/
|
||||
where <0> is the bus the chip was detected on (e. g. i2c-0)
|
||||
and <1> the chip address ([48..4f])
|
||||
|
||||
Inside these directories, there are such files:
|
||||
in0, in1, in2, in3, out0_enable, out0_output, name
|
||||
in0_input, in1_input, in2_input, in3_input, out0_enable, out0_output, name
|
||||
|
||||
Name contains chip name.
|
||||
|
||||
The in0, in1, in2 and in3 files are RO. Reading gives the value of the
|
||||
corresponding channel. Depending on the current analog inputs configuration,
|
||||
files in2 and/or in3 do not exist. Values range are from 0 to 255 for single
|
||||
ended inputs and -128 to +127 for differential inputs (8-bit ADC).
|
||||
The in0_input, in1_input, in2_input and in3_input files are RO. Reading gives
|
||||
the value of the corresponding channel. Depending on the current analog inputs
|
||||
configuration, files in2_input and in3_input may not exist. Values range
|
||||
from 0 to 255 for single ended inputs and -128 to +127 for differential inputs
|
||||
(8-bit ADC).
|
||||
|
||||
The out0_enable file is RW. Reading gives "1" for analog output enabled and
|
||||
"0" for analog output disabled. Writing accepts "0" and "1" accordingly.
|
||||
|
|
36
Documentation/hwmon/tmp421
Normal file
36
Documentation/hwmon/tmp421
Normal file
|
@ -0,0 +1,36 @@
|
|||
Kernel driver tmp421
|
||||
====================
|
||||
|
||||
Supported chips:
|
||||
* Texas Instruments TMP421
|
||||
Prefix: 'tmp421'
|
||||
Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
|
||||
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
|
||||
* Texas Instruments TMP422
|
||||
Prefix: 'tmp422'
|
||||
Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
|
||||
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
|
||||
* Texas Instruments TMP423
|
||||
Prefix: 'tmp423'
|
||||
Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
|
||||
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
|
||||
|
||||
Authors:
|
||||
Andre Prendel <andre.prendel@gmx.de>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for Texas Instruments TMP421, TMP422
|
||||
and TMP423 temperature sensor chips. These chips implement one local
|
||||
and up to one (TMP421), up to two (TMP422) or up to three (TMP423)
|
||||
remote sensors. Temperature is measured in degrees Celsius. The chips
|
||||
are wired over I2C/SMBus and specified over a temperature range of -40
|
||||
to +125 degrees Celsius. Resolution for both the local and remote
|
||||
channels is 0.0625 degree C.
|
||||
|
||||
The chips support only temperature measurement. The driver exports
|
||||
the temperature values via the following sysfs files:
|
||||
|
||||
temp[1-4]_input
|
||||
temp[2-4]_fault
|
210
Documentation/intel_txt.txt
Normal file
210
Documentation/intel_txt.txt
Normal file
|
@ -0,0 +1,210 @@
|
|||
Intel(R) TXT Overview:
|
||||
=====================
|
||||
|
||||
Intel's technology for safer computing, Intel(R) Trusted Execution
|
||||
Technology (Intel(R) TXT), defines platform-level enhancements that
|
||||
provide the building blocks for creating trusted platforms.
|
||||
|
||||
Intel TXT was formerly known by the code name LaGrande Technology (LT).
|
||||
|
||||
Intel TXT in Brief:
|
||||
o Provides dynamic root of trust for measurement (DRTM)
|
||||
o Data protection in case of improper shutdown
|
||||
o Measurement and verification of launched environment
|
||||
|
||||
Intel TXT is part of the vPro(TM) brand and is also available some
|
||||
non-vPro systems. It is currently available on desktop systems
|
||||
based on the Q35, X38, Q45, and Q43 Express chipsets (e.g. Dell
|
||||
Optiplex 755, HP dc7800, etc.) and mobile systems based on the GM45,
|
||||
PM45, and GS45 Express chipsets.
|
||||
|
||||
For more information, see http://www.intel.com/technology/security/.
|
||||
This site also has a link to the Intel TXT MLE Developers Manual,
|
||||
which has been updated for the new released platforms.
|
||||
|
||||
Intel TXT has been presented at various events over the past few
|
||||
years, some of which are:
|
||||
LinuxTAG 2008:
|
||||
http://www.linuxtag.org/2008/en/conf/events/vp-donnerstag/
|
||||
details.html?talkid=110
|
||||
TRUST2008:
|
||||
http://www.trust2008.eu/downloads/Keynote-Speakers/
|
||||
3_David-Grawrock_The-Front-Door-of-Trusted-Computing.pdf
|
||||
IDF 2008, Shanghai:
|
||||
http://inteldeveloperforum.com.edgesuite.net/shanghai_2008/
|
||||
aep/PROS003/index.html
|
||||
IDFs 2006, 2007 (I'm not sure if/where they are online)
|
||||
|
||||
Trusted Boot Project Overview:
|
||||
=============================
|
||||
|
||||
Trusted Boot (tboot) is an open source, pre- kernel/VMM module that
|
||||
uses Intel TXT to perform a measured and verified launch of an OS
|
||||
kernel/VMM.
|
||||
|
||||
It is hosted on SourceForge at http://sourceforge.net/projects/tboot.
|
||||
The mercurial source repo is available at http://www.bughost.org/
|
||||
repos.hg/tboot.hg.
|
||||
|
||||
Tboot currently supports launching Xen (open source VMM/hypervisor
|
||||
w/ TXT support since v3.2), and now Linux kernels.
|
||||
|
||||
|
||||
Value Proposition for Linux or "Why should you care?"
|
||||
=====================================================
|
||||
|
||||
While there are many products and technologies that attempt to
|
||||
measure or protect the integrity of a running kernel, they all
|
||||
assume the kernel is "good" to begin with. The Integrity
|
||||
Measurement Architecture (IMA) and Linux Integrity Module interface
|
||||
are examples of such solutions.
|
||||
|
||||
To get trust in the initial kernel without using Intel TXT, a
|
||||
static root of trust must be used. This bases trust in BIOS
|
||||
starting at system reset and requires measurement of all code
|
||||
executed between system reset through the completion of the kernel
|
||||
boot as well as data objects used by that code. In the case of a
|
||||
Linux kernel, this means all of BIOS, any option ROMs, the
|
||||
bootloader and the boot config. In practice, this is a lot of
|
||||
code/data, much of which is subject to change from boot to boot
|
||||
(e.g. changing NICs may change option ROMs). Without reference
|
||||
hashes, these measurement changes are difficult to assess or
|
||||
confirm as benign. This process also does not provide DMA
|
||||
protection, memory configuration/alias checks and locks, crash
|
||||
protection, or policy support.
|
||||
|
||||
By using the hardware-based root of trust that Intel TXT provides,
|
||||
many of these issues can be mitigated. Specifically: many
|
||||
pre-launch components can be removed from the trust chain, DMA
|
||||
protection is provided to all launched components, a large number
|
||||
of platform configuration checks are performed and values locked,
|
||||
protection is provided for any data in the event of an improper
|
||||
shutdown, and there is support for policy-based execution/verification.
|
||||
This provides a more stable measurement and a higher assurance of
|
||||
system configuration and initial state than would be otherwise
|
||||
possible. Since the tboot project is open source, source code for
|
||||
almost all parts of the trust chain is available (excepting SMM and
|
||||
Intel-provided firmware).
|
||||
|
||||
How Does it Work?
|
||||
=================
|
||||
|
||||
o Tboot is an executable that is launched by the bootloader as
|
||||
the "kernel" (the binary the bootloader executes).
|
||||
o It performs all of the work necessary to determine if the
|
||||
platform supports Intel TXT and, if so, executes the GETSEC[SENTER]
|
||||
processor instruction that initiates the dynamic root of trust.
|
||||
- If tboot determines that the system does not support Intel TXT
|
||||
or is not configured correctly (e.g. the SINIT AC Module was
|
||||
incorrect), it will directly launch the kernel with no changes
|
||||
to any state.
|
||||
- Tboot will output various information about its progress to the
|
||||
terminal, serial port, and/or an in-memory log; the output
|
||||
locations can be configured with a command line switch.
|
||||
o The GETSEC[SENTER] instruction will return control to tboot and
|
||||
tboot then verifies certain aspects of the environment (e.g. TPM NV
|
||||
lock, e820 table does not have invalid entries, etc.).
|
||||
o It will wake the APs from the special sleep state the GETSEC[SENTER]
|
||||
instruction had put them in and place them into a wait-for-SIPI
|
||||
state.
|
||||
- Because the processors will not respond to an INIT or SIPI when
|
||||
in the TXT environment, it is necessary to create a small VT-x
|
||||
guest for the APs. When they run in this guest, they will
|
||||
simply wait for the INIT-SIPI-SIPI sequence, which will cause
|
||||
VMEXITs, and then disable VT and jump to the SIPI vector. This
|
||||
approach seemed like a better choice than having to insert
|
||||
special code into the kernel's MP wakeup sequence.
|
||||
o Tboot then applies an (optional) user-defined launch policy to
|
||||
verify the kernel and initrd.
|
||||
- This policy is rooted in TPM NV and is described in the tboot
|
||||
project. The tboot project also contains code for tools to
|
||||
create and provision the policy.
|
||||
- Policies are completely under user control and if not present
|
||||
then any kernel will be launched.
|
||||
- Policy action is flexible and can include halting on failures
|
||||
or simply logging them and continuing.
|
||||
o Tboot adjusts the e820 table provided by the bootloader to reserve
|
||||
its own location in memory as well as to reserve certain other
|
||||
TXT-related regions.
|
||||
o As part of it's launch, tboot DMA protects all of RAM (using the
|
||||
VT-d PMRs). Thus, the kernel must be booted with 'intel_iommu=on'
|
||||
in order to remove this blanket protection and use VT-d's
|
||||
page-level protection.
|
||||
o Tboot will populate a shared page with some data about itself and
|
||||
pass this to the Linux kernel as it transfers control.
|
||||
- The location of the shared page is passed via the boot_params
|
||||
struct as a physical address.
|
||||
o The kernel will look for the tboot shared page address and, if it
|
||||
exists, map it.
|
||||
o As one of the checks/protections provided by TXT, it makes a copy
|
||||
of the VT-d DMARs in a DMA-protected region of memory and verifies
|
||||
them for correctness. The VT-d code will detect if the kernel was
|
||||
launched with tboot and use this copy instead of the one in the
|
||||
ACPI table.
|
||||
o At this point, tboot and TXT are out of the picture until a
|
||||
shutdown (S<n>)
|
||||
o In order to put a system into any of the sleep states after a TXT
|
||||
launch, TXT must first be exited. This is to prevent attacks that
|
||||
attempt to crash the system to gain control on reboot and steal
|
||||
data left in memory.
|
||||
- The kernel will perform all of its sleep preparation and
|
||||
populate the shared page with the ACPI data needed to put the
|
||||
platform in the desired sleep state.
|
||||
- Then the kernel jumps into tboot via the vector specified in the
|
||||
shared page.
|
||||
- Tboot will clean up the environment and disable TXT, then use the
|
||||
kernel-provided ACPI information to actually place the platform
|
||||
into the desired sleep state.
|
||||
- In the case of S3, tboot will also register itself as the resume
|
||||
vector. This is necessary because it must re-establish the
|
||||
measured environment upon resume. Once the TXT environment
|
||||
has been restored, it will restore the TPM PCRs and then
|
||||
transfer control back to the kernel's S3 resume vector.
|
||||
In order to preserve system integrity across S3, the kernel
|
||||
provides tboot with a set of memory ranges (kernel
|
||||
code/data/bss, S3 resume code, and AP trampoline) that tboot
|
||||
will calculate a MAC (message authentication code) over and then
|
||||
seal with the TPM. On resume and once the measured environment
|
||||
has been re-established, tboot will re-calculate the MAC and
|
||||
verify it against the sealed value. Tboot's policy determines
|
||||
what happens if the verification fails.
|
||||
|
||||
That's pretty much it for TXT support.
|
||||
|
||||
|
||||
Configuring the System:
|
||||
======================
|
||||
|
||||
This code works with 32bit, 32bit PAE, and 64bit (x86_64) kernels.
|
||||
|
||||
In BIOS, the user must enable: TPM, TXT, VT-x, VT-d. Not all BIOSes
|
||||
allow these to be individually enabled/disabled and the screens in
|
||||
which to find them are BIOS-specific.
|
||||
|
||||
grub.conf needs to be modified as follows:
|
||||
title Linux 2.6.29-tip w/ tboot
|
||||
root (hd0,0)
|
||||
kernel /tboot.gz logging=serial,vga,memory
|
||||
module /vmlinuz-2.6.29-tip intel_iommu=on ro
|
||||
root=LABEL=/ rhgb console=ttyS0,115200 3
|
||||
module /initrd-2.6.29-tip.img
|
||||
module /Q35_SINIT_17.BIN
|
||||
|
||||
The kernel option for enabling Intel TXT support is found under the
|
||||
Security top-level menu and is called "Enable Intel(R) Trusted
|
||||
Execution Technology (TXT)". It is marked as EXPERIMENTAL and
|
||||
depends on the generic x86 support (to allow maximum flexibility in
|
||||
kernel build options), since the tboot code will detect whether the
|
||||
platform actually supports Intel TXT and thus whether any of the
|
||||
kernel code is executed.
|
||||
|
||||
The Q35_SINIT_17.BIN file is what Intel TXT refers to as an
|
||||
Authenticated Code Module. It is specific to the chipset in the
|
||||
system and can also be found on the Trusted Boot site. It is an
|
||||
(unencrypted) module signed by Intel that is used as part of the
|
||||
DRTM process to verify and configure the system. It is signed
|
||||
because it operates at a higher privilege level in the system than
|
||||
any other macrocode and its correct operation is critical to the
|
||||
establishment of the DRTM. The process for determining the correct
|
||||
SINIT ACM for a system is documented in the SINIT-guide.txt file
|
||||
that is on the tboot SourceForge site under the SINIT ACM downloads.
|
|
@ -1286,6 +1286,10 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||
(machvec) in a generic kernel.
|
||||
Example: machvec=hpzx1_swiotlb
|
||||
|
||||
machtype= [Loongson] Share the same kernel image file between different
|
||||
yeeloong laptop.
|
||||
Example: machtype=lemote-yeeloong-2f-7inch
|
||||
|
||||
max_addr=nn[KMG] [KNL,BOOT,ia64] All physical memory greater
|
||||
than or equal to this physical address is ignored.
|
||||
|
||||
|
@ -1971,11 +1975,12 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||
Format: { 0 | 1 }
|
||||
See arch/parisc/kernel/pdc_chassis.c
|
||||
|
||||
percpu_alloc= [X86] Select which percpu first chunk allocator to use.
|
||||
Allowed values are one of "lpage", "embed" and "4k".
|
||||
See comments in arch/x86/kernel/setup_percpu.c for
|
||||
details on each allocator. This parameter is primarily
|
||||
for debugging and performance comparison.
|
||||
percpu_alloc= Select which percpu first chunk allocator to use.
|
||||
Currently supported values are "embed" and "page".
|
||||
Archs may support subset or none of the selections.
|
||||
See comments in mm/percpu.c for details on each
|
||||
allocator. This parameter is primarily for debugging
|
||||
and performance comparison.
|
||||
|
||||
pf. [PARIDE]
|
||||
See Documentation/blockdev/paride.txt.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Event Tracing
|
||||
|
||||
Documentation written by Theodore Ts'o
|
||||
Updated by Li Zefan
|
||||
Updated by Li Zefan and Tom Zanussi
|
||||
|
||||
1. Introduction
|
||||
===============
|
||||
|
@ -22,12 +22,12 @@ tracing information should be printed.
|
|||
---------------------------------
|
||||
|
||||
The events which are available for tracing can be found in the file
|
||||
/debug/tracing/available_events.
|
||||
/sys/kernel/debug/tracing/available_events.
|
||||
|
||||
To enable a particular event, such as 'sched_wakeup', simply echo it
|
||||
to /debug/tracing/set_event. For example:
|
||||
to /sys/kernel/debug/tracing/set_event. For example:
|
||||
|
||||
# echo sched_wakeup >> /debug/tracing/set_event
|
||||
# echo sched_wakeup >> /sys/kernel/debug/tracing/set_event
|
||||
|
||||
[ Note: '>>' is necessary, otherwise it will firstly disable
|
||||
all the events. ]
|
||||
|
@ -35,15 +35,15 @@ to /debug/tracing/set_event. For example:
|
|||
To disable an event, echo the event name to the set_event file prefixed
|
||||
with an exclamation point:
|
||||
|
||||
# echo '!sched_wakeup' >> /debug/tracing/set_event
|
||||
# echo '!sched_wakeup' >> /sys/kernel/debug/tracing/set_event
|
||||
|
||||
To disable all events, echo an empty line to the set_event file:
|
||||
|
||||
# echo > /debug/tracing/set_event
|
||||
# echo > /sys/kernel/debug/tracing/set_event
|
||||
|
||||
To enable all events, echo '*:*' or '*:' to the set_event file:
|
||||
|
||||
# echo *:* > /debug/tracing/set_event
|
||||
# echo *:* > /sys/kernel/debug/tracing/set_event
|
||||
|
||||
The events are organized into subsystems, such as ext4, irq, sched,
|
||||
etc., and a full event name looks like this: <subsystem>:<event>. The
|
||||
|
@ -52,29 +52,29 @@ file. All of the events in a subsystem can be specified via the syntax
|
|||
"<subsystem>:*"; for example, to enable all irq events, you can use the
|
||||
command:
|
||||
|
||||
# echo 'irq:*' > /debug/tracing/set_event
|
||||
# echo 'irq:*' > /sys/kernel/debug/tracing/set_event
|
||||
|
||||
2.2 Via the 'enable' toggle
|
||||
---------------------------
|
||||
|
||||
The events available are also listed in /debug/tracing/events/ hierarchy
|
||||
The events available are also listed in /sys/kernel/debug/tracing/events/ hierarchy
|
||||
of directories.
|
||||
|
||||
To enable event 'sched_wakeup':
|
||||
|
||||
# echo 1 > /debug/tracing/events/sched/sched_wakeup/enable
|
||||
# echo 1 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
|
||||
|
||||
To disable it:
|
||||
|
||||
# echo 0 > /debug/tracing/events/sched/sched_wakeup/enable
|
||||
# echo 0 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
|
||||
|
||||
To enable all events in sched subsystem:
|
||||
|
||||
# echo 1 > /debug/tracing/events/sched/enable
|
||||
# echo 1 > /sys/kernel/debug/tracing/events/sched/enable
|
||||
|
||||
To eanble all events:
|
||||
|
||||
# echo 1 > /debug/tracing/events/enable
|
||||
# echo 1 > /sys/kernel/debug/tracing/events/enable
|
||||
|
||||
When reading one of these enable files, there are four results:
|
||||
|
||||
|
@ -97,3 +97,185 @@ The format of this boot option is the same as described in section 2.1.
|
|||
|
||||
See The example provided in samples/trace_events
|
||||
|
||||
4. Event formats
|
||||
================
|
||||
|
||||
Each trace event has a 'format' file associated with it that contains
|
||||
a description of each field in a logged event. This information can
|
||||
be used to parse the binary trace stream, and is also the place to
|
||||
find the field names that can be used in event filters (see section 5).
|
||||
|
||||
It also displays the format string that will be used to print the
|
||||
event in text mode, along with the event name and ID used for
|
||||
profiling.
|
||||
|
||||
Every event has a set of 'common' fields associated with it; these are
|
||||
the fields prefixed with 'common_'. The other fields vary between
|
||||
events and correspond to the fields defined in the TRACE_EVENT
|
||||
definition for that event.
|
||||
|
||||
Each field in the format has the form:
|
||||
|
||||
field:field-type field-name; offset:N; size:N;
|
||||
|
||||
where offset is the offset of the field in the trace record and size
|
||||
is the size of the data item, in bytes.
|
||||
|
||||
For example, here's the information displayed for the 'sched_wakeup'
|
||||
event:
|
||||
|
||||
# cat /debug/tracing/events/sched/sched_wakeup/format
|
||||
|
||||
name: sched_wakeup
|
||||
ID: 60
|
||||
format:
|
||||
field:unsigned short common_type; offset:0; size:2;
|
||||
field:unsigned char common_flags; offset:2; size:1;
|
||||
field:unsigned char common_preempt_count; offset:3; size:1;
|
||||
field:int common_pid; offset:4; size:4;
|
||||
field:int common_tgid; offset:8; size:4;
|
||||
|
||||
field:char comm[TASK_COMM_LEN]; offset:12; size:16;
|
||||
field:pid_t pid; offset:28; size:4;
|
||||
field:int prio; offset:32; size:4;
|
||||
field:int success; offset:36; size:4;
|
||||
field:int cpu; offset:40; size:4;
|
||||
|
||||
print fmt: "task %s:%d [%d] success=%d [%03d]", REC->comm, REC->pid,
|
||||
REC->prio, REC->success, REC->cpu
|
||||
|
||||
This event contains 10 fields, the first 5 common and the remaining 5
|
||||
event-specific. All the fields for this event are numeric, except for
|
||||
'comm' which is a string, a distinction important for event filtering.
|
||||
|
||||
5. Event filtering
|
||||
==================
|
||||
|
||||
Trace events can be filtered in the kernel by associating boolean
|
||||
'filter expressions' with them. As soon as an event is logged into
|
||||
the trace buffer, its fields are checked against the filter expression
|
||||
associated with that event type. An event with field values that
|
||||
'match' the filter will appear in the trace output, and an event whose
|
||||
values don't match will be discarded. An event with no filter
|
||||
associated with it matches everything, and is the default when no
|
||||
filter has been set for an event.
|
||||
|
||||
5.1 Expression syntax
|
||||
---------------------
|
||||
|
||||
A filter expression consists of one or more 'predicates' that can be
|
||||
combined using the logical operators '&&' and '||'. A predicate is
|
||||
simply a clause that compares the value of a field contained within a
|
||||
logged event with a constant value and returns either 0 or 1 depending
|
||||
on whether the field value matched (1) or didn't match (0):
|
||||
|
||||
field-name relational-operator value
|
||||
|
||||
Parentheses can be used to provide arbitrary logical groupings and
|
||||
double-quotes can be used to prevent the shell from interpreting
|
||||
operators as shell metacharacters.
|
||||
|
||||
The field-names available for use in filters can be found in the
|
||||
'format' files for trace events (see section 4).
|
||||
|
||||
The relational-operators depend on the type of the field being tested:
|
||||
|
||||
The operators available for numeric fields are:
|
||||
|
||||
==, !=, <, <=, >, >=
|
||||
|
||||
And for string fields they are:
|
||||
|
||||
==, !=
|
||||
|
||||
Currently, only exact string matches are supported.
|
||||
|
||||
Currently, the maximum number of predicates in a filter is 16.
|
||||
|
||||
5.2 Setting filters
|
||||
-------------------
|
||||
|
||||
A filter for an individual event is set by writing a filter expression
|
||||
to the 'filter' file for the given event.
|
||||
|
||||
For example:
|
||||
|
||||
# cd /debug/tracing/events/sched/sched_wakeup
|
||||
# echo "common_preempt_count > 4" > filter
|
||||
|
||||
A slightly more involved example:
|
||||
|
||||
# cd /debug/tracing/events/sched/sched_signal_send
|
||||
# echo "((sig >= 10 && sig < 15) || sig == 17) && comm != bash" > filter
|
||||
|
||||
If there is an error in the expression, you'll get an 'Invalid
|
||||
argument' error when setting it, and the erroneous string along with
|
||||
an error message can be seen by looking at the filter e.g.:
|
||||
|
||||
# cd /debug/tracing/events/sched/sched_signal_send
|
||||
# echo "((sig >= 10 && sig < 15) || dsig == 17) && comm != bash" > filter
|
||||
-bash: echo: write error: Invalid argument
|
||||
# cat filter
|
||||
((sig >= 10 && sig < 15) || dsig == 17) && comm != bash
|
||||
^
|
||||
parse_error: Field not found
|
||||
|
||||
Currently the caret ('^') for an error always appears at the beginning of
|
||||
the filter string; the error message should still be useful though
|
||||
even without more accurate position info.
|
||||
|
||||
5.3 Clearing filters
|
||||
--------------------
|
||||
|
||||
To clear the filter for an event, write a '0' to the event's filter
|
||||
file.
|
||||
|
||||
To clear the filters for all events in a subsystem, write a '0' to the
|
||||
subsystem's filter file.
|
||||
|
||||
5.3 Subsystem filters
|
||||
---------------------
|
||||
|
||||
For convenience, filters for every event in a subsystem can be set or
|
||||
cleared as a group by writing a filter expression into the filter file
|
||||
at the root of the subsytem. Note however, that if a filter for any
|
||||
event within the subsystem lacks a field specified in the subsystem
|
||||
filter, or if the filter can't be applied for any other reason, the
|
||||
filter for that event will retain its previous setting. This can
|
||||
result in an unintended mixture of filters which could lead to
|
||||
confusing (to the user who might think different filters are in
|
||||
effect) trace output. Only filters that reference just the common
|
||||
fields can be guaranteed to propagate successfully to all events.
|
||||
|
||||
Here are a few subsystem filter examples that also illustrate the
|
||||
above points:
|
||||
|
||||
Clear the filters on all events in the sched subsytem:
|
||||
|
||||
# cd /sys/kernel/debug/tracing/events/sched
|
||||
# echo 0 > filter
|
||||
# cat sched_switch/filter
|
||||
none
|
||||
# cat sched_wakeup/filter
|
||||
none
|
||||
|
||||
Set a filter using only common fields for all events in the sched
|
||||
subsytem (all events end up with the same filter):
|
||||
|
||||
# cd /sys/kernel/debug/tracing/events/sched
|
||||
# echo common_pid == 0 > filter
|
||||
# cat sched_switch/filter
|
||||
common_pid == 0
|
||||
# cat sched_wakeup/filter
|
||||
common_pid == 0
|
||||
|
||||
Attempt to set a filter using a non-common field for all events in the
|
||||
sched subsytem (all events but those that have a prev_pid field retain
|
||||
their old filters):
|
||||
|
||||
# cd /sys/kernel/debug/tracing/events/sched
|
||||
# echo prev_pid == 0 > filter
|
||||
# cat sched_switch/filter
|
||||
prev_pid == 0
|
||||
# cat sched_wakeup/filter
|
||||
common_pid == 0
|
||||
|
|
233
Documentation/trace/ftrace-design.txt
Normal file
233
Documentation/trace/ftrace-design.txt
Normal file
|
@ -0,0 +1,233 @@
|
|||
function tracer guts
|
||||
====================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Here we will cover the architecture pieces that the common function tracing
|
||||
code relies on for proper functioning. Things are broken down into increasing
|
||||
complexity so that you can start simple and at least get basic functionality.
|
||||
|
||||
Note that this focuses on architecture implementation details only. If you
|
||||
want more explanation of a feature in terms of common code, review the common
|
||||
ftrace.txt file.
|
||||
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
Ftrace relies on these features being implemented:
|
||||
STACKTRACE_SUPPORT - implement save_stack_trace()
|
||||
TRACE_IRQFLAGS_SUPPORT - implement include/asm/irqflags.h
|
||||
|
||||
|
||||
HAVE_FUNCTION_TRACER
|
||||
--------------------
|
||||
|
||||
You will need to implement the mcount and the ftrace_stub functions.
|
||||
|
||||
The exact mcount symbol name will depend on your toolchain. Some call it
|
||||
"mcount", "_mcount", or even "__mcount". You can probably figure it out by
|
||||
running something like:
|
||||
$ echo 'main(){}' | gcc -x c -S -o - - -pg | grep mcount
|
||||
call mcount
|
||||
We'll make the assumption below that the symbol is "mcount" just to keep things
|
||||
nice and simple in the examples.
|
||||
|
||||
Keep in mind that the ABI that is in effect inside of the mcount function is
|
||||
*highly* architecture/toolchain specific. We cannot help you in this regard,
|
||||
sorry. Dig up some old documentation and/or find someone more familiar than
|
||||
you to bang ideas off of. Typically, register usage (argument/scratch/etc...)
|
||||
is a major issue at this point, especially in relation to the location of the
|
||||
mcount call (before/after function prologue). You might also want to look at
|
||||
how glibc has implemented the mcount function for your architecture. It might
|
||||
be (semi-)relevant.
|
||||
|
||||
The mcount function should check the function pointer ftrace_trace_function
|
||||
to see if it is set to ftrace_stub. If it is, there is nothing for you to do,
|
||||
so return immediately. If it isn't, then call that function in the same way
|
||||
the mcount function normally calls __mcount_internal -- the first argument is
|
||||
the "frompc" while the second argument is the "selfpc" (adjusted to remove the
|
||||
size of the mcount call that is embedded in the function).
|
||||
|
||||
For example, if the function foo() calls bar(), when the bar() function calls
|
||||
mcount(), the arguments mcount() will pass to the tracer are:
|
||||
"frompc" - the address bar() will use to return to foo()
|
||||
"selfpc" - the address bar() (with _mcount() size adjustment)
|
||||
|
||||
Also keep in mind that this mcount function will be called *a lot*, so
|
||||
optimizing for the default case of no tracer will help the smooth running of
|
||||
your system when tracing is disabled. So the start of the mcount function is
|
||||
typically the bare min with checking things before returning. That also means
|
||||
the code flow should usually kept linear (i.e. no branching in the nop case).
|
||||
This is of course an optimization and not a hard requirement.
|
||||
|
||||
Here is some pseudo code that should help (these functions should actually be
|
||||
implemented in assembly):
|
||||
|
||||
void ftrace_stub(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void mcount(void)
|
||||
{
|
||||
/* save any bare state needed in order to do initial checking */
|
||||
|
||||
extern void (*ftrace_trace_function)(unsigned long, unsigned long);
|
||||
if (ftrace_trace_function != ftrace_stub)
|
||||
goto do_trace;
|
||||
|
||||
/* restore any bare state */
|
||||
|
||||
return;
|
||||
|
||||
do_trace:
|
||||
|
||||
/* save all state needed by the ABI (see paragraph above) */
|
||||
|
||||
unsigned long frompc = ...;
|
||||
unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE;
|
||||
ftrace_trace_function(frompc, selfpc);
|
||||
|
||||
/* restore all state needed by the ABI */
|
||||
}
|
||||
|
||||
Don't forget to export mcount for modules !
|
||||
extern void mcount(void);
|
||||
EXPORT_SYMBOL(mcount);
|
||||
|
||||
|
||||
HAVE_FUNCTION_TRACE_MCOUNT_TEST
|
||||
-------------------------------
|
||||
|
||||
This is an optional optimization for the normal case when tracing is turned off
|
||||
in the system. If you do not enable this Kconfig option, the common ftrace
|
||||
code will take care of doing the checking for you.
|
||||
|
||||
To support this feature, you only need to check the function_trace_stop
|
||||
variable in the mcount function. If it is non-zero, there is no tracing to be
|
||||
done at all, so you can return.
|
||||
|
||||
This additional pseudo code would simply be:
|
||||
void mcount(void)
|
||||
{
|
||||
/* save any bare state needed in order to do initial checking */
|
||||
|
||||
+ if (function_trace_stop)
|
||||
+ return;
|
||||
|
||||
extern void (*ftrace_trace_function)(unsigned long, unsigned long);
|
||||
if (ftrace_trace_function != ftrace_stub)
|
||||
...
|
||||
|
||||
|
||||
HAVE_FUNCTION_GRAPH_TRACER
|
||||
--------------------------
|
||||
|
||||
Deep breath ... time to do some real work. Here you will need to update the
|
||||
mcount function to check ftrace graph function pointers, as well as implement
|
||||
some functions to save (hijack) and restore the return address.
|
||||
|
||||
The mcount function should check the function pointers ftrace_graph_return
|
||||
(compare to ftrace_stub) and ftrace_graph_entry (compare to
|
||||
ftrace_graph_entry_stub). If either of those are not set to the relevant stub
|
||||
function, call the arch-specific function ftrace_graph_caller which in turn
|
||||
calls the arch-specific function prepare_ftrace_return. Neither of these
|
||||
function names are strictly required, but you should use them anyways to stay
|
||||
consistent across the architecture ports -- easier to compare & contrast
|
||||
things.
|
||||
|
||||
The arguments to prepare_ftrace_return are slightly different than what are
|
||||
passed to ftrace_trace_function. The second argument "selfpc" is the same,
|
||||
but the first argument should be a pointer to the "frompc". Typically this is
|
||||
located on the stack. This allows the function to hijack the return address
|
||||
temporarily to have it point to the arch-specific function return_to_handler.
|
||||
That function will simply call the common ftrace_return_to_handler function and
|
||||
that will return the original return address with which, you can return to the
|
||||
original call site.
|
||||
|
||||
Here is the updated mcount pseudo code:
|
||||
void mcount(void)
|
||||
{
|
||||
...
|
||||
if (ftrace_trace_function != ftrace_stub)
|
||||
goto do_trace;
|
||||
|
||||
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
+ extern void (*ftrace_graph_return)(...);
|
||||
+ extern void (*ftrace_graph_entry)(...);
|
||||
+ if (ftrace_graph_return != ftrace_stub ||
|
||||
+ ftrace_graph_entry != ftrace_graph_entry_stub)
|
||||
+ ftrace_graph_caller();
|
||||
+#endif
|
||||
|
||||
/* restore any bare state */
|
||||
...
|
||||
|
||||
Here is the pseudo code for the new ftrace_graph_caller assembly function:
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
void ftrace_graph_caller(void)
|
||||
{
|
||||
/* save all state needed by the ABI */
|
||||
|
||||
unsigned long *frompc = &...;
|
||||
unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE;
|
||||
prepare_ftrace_return(frompc, selfpc);
|
||||
|
||||
/* restore all state needed by the ABI */
|
||||
}
|
||||
#endif
|
||||
|
||||
For information on how to implement prepare_ftrace_return(), simply look at
|
||||
the x86 version. The only architecture-specific piece in it is the setup of
|
||||
the fault recovery table (the asm(...) code). The rest should be the same
|
||||
across architectures.
|
||||
|
||||
Here is the pseudo code for the new return_to_handler assembly function. Note
|
||||
that the ABI that applies here is different from what applies to the mcount
|
||||
code. Since you are returning from a function (after the epilogue), you might
|
||||
be able to skimp on things saved/restored (usually just registers used to pass
|
||||
return values).
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
void return_to_handler(void)
|
||||
{
|
||||
/* save all state needed by the ABI (see paragraph above) */
|
||||
|
||||
void (*original_return_point)(void) = ftrace_return_to_handler();
|
||||
|
||||
/* restore all state needed by the ABI */
|
||||
|
||||
/* this is usually either a return or a jump */
|
||||
original_return_point();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
HAVE_FTRACE_NMI_ENTER
|
||||
---------------------
|
||||
|
||||
If you can't trace NMI functions, then skip this option.
|
||||
|
||||
<details to be filled>
|
||||
|
||||
|
||||
HAVE_FTRACE_SYSCALLS
|
||||
---------------------
|
||||
|
||||
<details to be filled>
|
||||
|
||||
|
||||
HAVE_FTRACE_MCOUNT_RECORD
|
||||
-------------------------
|
||||
|
||||
See scripts/recordmcount.pl for more info.
|
||||
|
||||
<details to be filled>
|
||||
|
||||
|
||||
HAVE_DYNAMIC_FTRACE
|
||||
---------------------
|
||||
|
||||
<details to be filled>
|
|
@ -26,6 +26,12 @@ disabled, and more (ftrace allows for tracer plugins, which
|
|||
means that the list of tracers can always grow).
|
||||
|
||||
|
||||
Implementation Details
|
||||
----------------------
|
||||
|
||||
See ftrace-design.txt for details for arch porters and such.
|
||||
|
||||
|
||||
The File System
|
||||
---------------
|
||||
|
||||
|
|
194
Documentation/vgaarbiter.txt
Normal file
194
Documentation/vgaarbiter.txt
Normal file
|
@ -0,0 +1,194 @@
|
|||
|
||||
VGA Arbiter
|
||||
===========
|
||||
|
||||
Graphic devices are accessed through ranges in I/O or memory space. While most
|
||||
modern devices allow relocation of such ranges, some "Legacy" VGA devices
|
||||
implemented on PCI will typically have the same "hard-decoded" addresses as
|
||||
they did on ISA. For more details see "PCI Bus Binding to IEEE Std 1275-1994
|
||||
Standard for Boot (Initialization Configuration) Firmware Revision 2.1"
|
||||
Section 7, Legacy Devices.
|
||||
|
||||
The Resource Access Control (RAC) module inside the X server [0] existed for
|
||||
the legacy VGA arbitration task (besides other bus management tasks) when more
|
||||
than one legacy device co-exists on the same machine. But the problem happens
|
||||
when these devices are trying to be accessed by different userspace clients
|
||||
(e.g. two server in parallel). Their address assignments conflict. Moreover,
|
||||
ideally, being an userspace application, it is not the role of the the X
|
||||
server to control bus resources. Therefore an arbitration scheme outside of
|
||||
the X server is needed to control the sharing of these resources. This
|
||||
document introduces the operation of the VGA arbiter implemented for Linux
|
||||
kernel.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
I. Details and Theory of Operation
|
||||
I.1 vgaarb
|
||||
I.2 libpciaccess
|
||||
I.3 xf86VGAArbiter (X server implementation)
|
||||
II. Credits
|
||||
III.References
|
||||
|
||||
|
||||
I. Details and Theory of Operation
|
||||
==================================
|
||||
|
||||
I.1 vgaarb
|
||||
----------
|
||||
|
||||
The vgaarb is a module of the Linux Kernel. When it is initially loaded, it
|
||||
scans all PCI devices and adds the VGA ones inside the arbitration. The
|
||||
arbiter then enables/disables the decoding on different devices of the VGA
|
||||
legacy instructions. Device which do not want/need to use the arbiter may
|
||||
explicitly tell it by calling vga_set_legacy_decoding().
|
||||
|
||||
The kernel exports a char device interface (/dev/vga_arbiter) to the clients,
|
||||
which has the following semantics:
|
||||
|
||||
open : open user instance of the arbiter. By default, it's attached to
|
||||
the default VGA device of the system.
|
||||
|
||||
close : close user instance. Release locks made by the user
|
||||
|
||||
read : return a string indicating the status of the target like:
|
||||
|
||||
"<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)"
|
||||
|
||||
An IO state string is of the form {io,mem,io+mem,none}, mc and
|
||||
ic are respectively mem and io lock counts (for debugging/
|
||||
diagnostic only). "decodes" indicate what the card currently
|
||||
decodes, "owns" indicates what is currently enabled on it, and
|
||||
"locks" indicates what is locked by this card. If the card is
|
||||
unplugged, we get "invalid" then for card_ID and an -ENODEV
|
||||
error is returned for any command until a new card is targeted.
|
||||
|
||||
|
||||
write : write a command to the arbiter. List of commands:
|
||||
|
||||
target <card_ID> : switch target to card <card_ID> (see below)
|
||||
lock <io_state> : acquires locks on target ("none" is an invalid io_state)
|
||||
trylock <io_state> : non-blocking acquire locks on target (returns EBUSY if
|
||||
unsuccessful)
|
||||
unlock <io_state> : release locks on target
|
||||
unlock all : release all locks on target held by this user (not
|
||||
implemented yet)
|
||||
decodes <io_state> : set the legacy decoding attributes for the card
|
||||
|
||||
poll : event if something changes on any card (not just the
|
||||
target)
|
||||
|
||||
card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default"
|
||||
to go back to the system default card (TODO: not implemented yet). Currently,
|
||||
only PCI is supported as a prefix, but the userland API may support other bus
|
||||
types in the future, even if the current kernel implementation doesn't.
|
||||
|
||||
Note about locks:
|
||||
|
||||
The driver keeps track of which user has which locks on which card. It
|
||||
supports stacking, like the kernel one. This complexifies the implementation
|
||||
a bit, but makes the arbiter more tolerant to user space problems and able
|
||||
to properly cleanup in all cases when a process dies.
|
||||
Currently, a max of 16 cards can have locks simultaneously issued from
|
||||
user space for a given user (file descriptor instance) of the arbiter.
|
||||
|
||||
In the case of devices hot-{un,}plugged, there is a hook - pci_notify() - to
|
||||
notify them being added/removed in the system and automatically added/removed
|
||||
in the arbiter.
|
||||
|
||||
There's also a in-kernel API of the arbiter in the case of DRM, vgacon and
|
||||
others which may use the arbiter.
|
||||
|
||||
|
||||
I.2 libpciaccess
|
||||
----------------
|
||||
|
||||
To use the vga arbiter char device it was implemented an API inside the
|
||||
libpciaccess library. One fieldd was added to struct pci_device (each device
|
||||
on the system):
|
||||
|
||||
/* the type of resource decoded by the device */
|
||||
int vgaarb_rsrc;
|
||||
|
||||
Besides it, in pci_system were added:
|
||||
|
||||
int vgaarb_fd;
|
||||
int vga_count;
|
||||
struct pci_device *vga_target;
|
||||
struct pci_device *vga_default_dev;
|
||||
|
||||
|
||||
The vga_count is usually need to keep informed how many cards are being
|
||||
arbitrated, so for instance if there's only one then it can totally escape the
|
||||
scheme.
|
||||
|
||||
|
||||
These functions below acquire VGA resources for the given card and mark those
|
||||
resources as locked. If the resources requested are "normal" (and not legacy)
|
||||
resources, the arbiter will first check whether the card is doing legacy
|
||||
decoding for that type of resource. If yes, the lock is "converted" into a
|
||||
legacy resource lock. The arbiter will first look for all VGA cards that
|
||||
might conflict and disable their IOs and/or Memory access, including VGA
|
||||
forwarding on P2P bridges if necessary, so that the requested resources can
|
||||
be used. Then, the card is marked as locking these resources and the IO and/or
|
||||
Memory access is enabled on the card (including VGA forwarding on parent
|
||||
P2P bridges if any). In the case of vga_arb_lock(), the function will block
|
||||
if some conflicting card is already locking one of the required resources (or
|
||||
any resource on a different bus segment, since P2P bridges don't differentiate
|
||||
VGA memory and IO afaik). If the card already owns the resources, the function
|
||||
succeeds. vga_arb_trylock() will return (-EBUSY) instead of blocking. Nested
|
||||
calls are supported (a per-resource counter is maintained).
|
||||
|
||||
|
||||
Set the target device of this client.
|
||||
int pci_device_vgaarb_set_target (struct pci_device *dev);
|
||||
|
||||
|
||||
For instance, in x86 if two devices on the same bus want to lock different
|
||||
resources, both will succeed (lock). If devices are in different buses and
|
||||
trying to lock different resources, only the first who tried succeeds.
|
||||
int pci_device_vgaarb_lock (void);
|
||||
int pci_device_vgaarb_trylock (void);
|
||||
|
||||
Unlock resources of device.
|
||||
int pci_device_vgaarb_unlock (void);
|
||||
|
||||
Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA
|
||||
Memory, both, or none. All cards default to both, the card driver (fbdev for
|
||||
example) should tell the arbiter if it has disabled legacy decoding, so the
|
||||
card can be left out of the arbitration process (and can be safe to take
|
||||
interrupts at any time.
|
||||
int pci_device_vgaarb_decodes (int new_vgaarb_rsrc);
|
||||
|
||||
Connects to the arbiter device, allocates the struct
|
||||
int pci_device_vgaarb_init (void);
|
||||
|
||||
Close the connection
|
||||
void pci_device_vgaarb_fini (void);
|
||||
|
||||
|
||||
I.3 xf86VGAArbiter (X server implementation)
|
||||
--------------------------------------------
|
||||
|
||||
(TODO)
|
||||
|
||||
X server basically wraps all the functions that touch VGA registers somehow.
|
||||
|
||||
|
||||
II. Credits
|
||||
===========
|
||||
|
||||
Benjamin Herrenschmidt (IBM?) started this work when he discussed such design
|
||||
with the Xorg community in 2005 [1, 2]. In the end of 2007, Paulo Zanoni and
|
||||
Tiago Vignatti (both of C3SL/Federal University of Paraná) proceeded his work
|
||||
enhancing the kernel code to adapt as a kernel module and also did the
|
||||
implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave
|
||||
Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree.
|
||||
|
||||
|
||||
III. References
|
||||
==============
|
||||
|
||||
[0] http://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
|
||||
[1] http://lists.freedesktop.org/archives/xorg/2005-March/006663.html
|
||||
[2] http://lists.freedesktop.org/archives/xorg/2005-March/006745.html
|
||||
[3] http://lists.freedesktop.org/archives/xorg/2007-October/029507.html
|
|
@ -21,3 +21,5 @@
|
|||
20 -> Hauppauge WinTV-HVR1255 [0070:2251]
|
||||
21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295]
|
||||
22 -> Mygica X8506 DMB-TH [14f1:8651]
|
||||
23 -> Magic-Pro ProHDTV Extreme 2 [14f1:8657]
|
||||
24 -> Hauppauge WinTV-HVR1850 [0070:8541]
|
||||
|
|
|
@ -80,3 +80,4 @@
|
|||
79 -> Terratec Cinergy HT PCI MKII [153b:1177]
|
||||
80 -> Hauppauge WinTV-IR Only [0070:9290]
|
||||
81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654]
|
||||
82 -> WinFast DTV2000 H rev. J [107d:6f2b]
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
6 -> Terratec Cinergy 200 USB (em2800)
|
||||
7 -> Leadtek Winfast USB II (em2800) [0413:6023]
|
||||
8 -> Kworld USB2800 (em2800)
|
||||
9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,2304:0207,2304:021a]
|
||||
9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,1b80:e304,2304:0207,2304:021a]
|
||||
10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
|
||||
11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
|
||||
12 -> Kworld PVR TV 2800 RF (em2820/em2840)
|
||||
|
@ -33,7 +33,7 @@
|
|||
34 -> Terratec Cinergy A Hybrid XS (em2860) [0ccd:004f]
|
||||
35 -> Typhoon DVD Maker (em2860)
|
||||
36 -> NetGMBH Cam (em2860)
|
||||
37 -> Gadmei UTV330 (em2860)
|
||||
37 -> Gadmei UTV330 (em2860) [eb1a:50a6]
|
||||
38 -> Yakumo MovieMixer (em2861)
|
||||
39 -> KWorld PVRTV 300U (em2861) [eb1a:e300]
|
||||
40 -> Plextor ConvertX PX-TV100U (em2861) [093b:a005]
|
||||
|
@ -67,3 +67,4 @@
|
|||
69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313]
|
||||
70 -> Evga inDtube (em2882)
|
||||
71 -> Silvercrest Webcam 1.3mpix (em2820/em2840)
|
||||
72 -> Gadmei UTV330+ (em2861)
|
||||
|
|
|
@ -167,3 +167,7 @@
|
|||
166 -> Beholder BeholdTV 607 RDS [5ace:6073]
|
||||
167 -> Beholder BeholdTV 609 RDS [5ace:6092]
|
||||
168 -> Beholder BeholdTV 609 RDS [5ace:6093]
|
||||
169 -> Compro VideoMate S350/S300 [185b:c900]
|
||||
170 -> AverMedia AverTV Studio 505 [1461:a115]
|
||||
171 -> Beholder BeholdTV X7 [5ace:7595]
|
||||
172 -> RoverMedia TV Link Pro FM [19d1:0138]
|
||||
|
|
|
@ -78,3 +78,4 @@ tuner=77 - TCL tuner MF02GIP-5N-E
|
|||
tuner=78 - Philips FMD1216MEX MK3 Hybrid Tuner
|
||||
tuner=79 - Philips PAL/SECAM multi (FM1216 MK5)
|
||||
tuner=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough
|
||||
tuner=81 - Partsnic (Daewoo) PTI-5NF05
|
||||
|
|
|
@ -18,8 +18,8 @@ Table of Contents
|
|||
|
||||
1.0 Introduction
|
||||
|
||||
The file ../drivers/char/c-qcam.c is a device driver for the
|
||||
Logitech (nee Connectix) parallel port interface color CCD camera.
|
||||
The file ../../drivers/media/video/c-qcam.c is a device driver for
|
||||
the Logitech (nee Connectix) parallel port interface color CCD camera.
|
||||
This is a fairly inexpensive device for capturing images. Logitech
|
||||
does not currently provide information for developers, but many people
|
||||
have engineered several solutions for non-Microsoft use of the Color
|
||||
|
|
|
@ -140,6 +140,7 @@ spca500 04fc:7333 PalmPixDC85
|
|||
sunplus 04fc:ffff Pure DigitalDakota
|
||||
spca501 0506:00df 3Com HomeConnect Lite
|
||||
sunplus 052b:1513 Megapix V4
|
||||
sunplus 052b:1803 MegaImage VI
|
||||
tv8532 0545:808b Veo Stingray
|
||||
tv8532 0545:8333 Veo Stingray
|
||||
sunplus 0546:3155 Polaroid PDC3070
|
||||
|
@ -182,6 +183,7 @@ ov534 06f8:3002 Hercules Blog Webcam
|
|||
ov534 06f8:3003 Hercules Dualpix HD Weblog
|
||||
sonixj 06f8:3004 Hercules Classic Silver
|
||||
sonixj 06f8:3008 Hercules Deluxe Optical Glass
|
||||
pac7311 06f8:3009 Hercules Classic Link
|
||||
spca508 0733:0110 ViewQuest VQ110
|
||||
spca508 0130:0130 Clone Digital Webcam 11043
|
||||
spca501 0733:0401 Intel Create and Share
|
||||
|
@ -235,8 +237,10 @@ pac7311 093a:2621 PAC731x
|
|||
pac7311 093a:2622 Genius Eye 312
|
||||
pac7311 093a:2624 PAC7302
|
||||
pac7311 093a:2626 Labtec 2200
|
||||
pac7311 093a:2629 Genious iSlim 300
|
||||
pac7311 093a:262a Webcam 300k
|
||||
pac7311 093a:262c Philips SPC 230 NC
|
||||
jeilinj 0979:0280 Sakar 57379
|
||||
zc3xx 0ac8:0302 Z-star Vimicro zc0302
|
||||
vc032x 0ac8:0321 Vimicro generic vc0321
|
||||
vc032x 0ac8:0323 Vimicro Vc0323
|
||||
|
@ -247,6 +251,7 @@ zc3xx 0ac8:305b Z-star Vimicro zc0305b
|
|||
zc3xx 0ac8:307b Ldlc VC302+Ov7620
|
||||
vc032x 0ac8:c001 Sony embedded vimicro
|
||||
vc032x 0ac8:c002 Sony embedded vimicro
|
||||
vc032x 0ac8:c301 Samsung Q1 Ultra Premium
|
||||
spca508 0af9:0010 Hama USB Sightcam 100
|
||||
spca508 0af9:0011 Hama USB Sightcam 100
|
||||
sonixb 0c45:6001 Genius VideoCAM NB
|
||||
|
@ -284,6 +289,7 @@ sonixj 0c45:613a Microdia Sonix PC Camera
|
|||
sonixj 0c45:613b Surfer SN-206
|
||||
sonixj 0c45:613c Sonix Pccam168
|
||||
sonixj 0c45:6143 Sonix Pccam168
|
||||
sonixj 0c45:6148 Digitus DA-70811/ZSMC USB PC Camera ZS211/Microdia
|
||||
sn9c20x 0c45:6240 PC Camera (SN9C201 + MT9M001)
|
||||
sn9c20x 0c45:6242 PC Camera (SN9C201 + MT9M111)
|
||||
sn9c20x 0c45:6248 PC Camera (SN9C201 + OV9655)
|
||||
|
|
176
Documentation/video4linux/si4713.txt
Normal file
176
Documentation/video4linux/si4713.txt
Normal file
|
@ -0,0 +1,176 @@
|
|||
Driver for I2C radios for the Silicon Labs Si4713 FM Radio Transmitters
|
||||
|
||||
Copyright (c) 2009 Nokia Corporation
|
||||
Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
|
||||
|
||||
|
||||
Information about the Device
|
||||
============================
|
||||
This chip is a Silicon Labs product. It is a I2C device, currently on 0x63 address.
|
||||
Basically, it has transmission and signal noise level measurement features.
|
||||
|
||||
The Si4713 integrates transmit functions for FM broadcast stereo transmission.
|
||||
The chip also allows integrated receive power scanning to identify low signal
|
||||
power FM channels.
|
||||
|
||||
The chip is programmed using commands and responses. There are also several
|
||||
properties which can change the behavior of this chip.
|
||||
|
||||
Users must comply with local regulations on radio frequency (RF) transmission.
|
||||
|
||||
Device driver description
|
||||
=========================
|
||||
There are two modules to handle this device. One is a I2C device driver
|
||||
and the other is a platform driver.
|
||||
|
||||
The I2C device driver exports a v4l2-subdev interface to the kernel.
|
||||
All properties can also be accessed by v4l2 extended controls interface, by
|
||||
using the v4l2-subdev calls (g_ext_ctrls, s_ext_ctrls).
|
||||
|
||||
The platform device driver exports a v4l2 radio device interface to user land.
|
||||
So, it uses the I2C device driver as a sub device in order to send the user
|
||||
commands to the actual device. Basically it is a wrapper to the I2C device driver.
|
||||
|
||||
Applications can use v4l2 radio API to specify frequency of operation, mute state,
|
||||
etc. But mostly of its properties will be present in the extended controls.
|
||||
|
||||
When the v4l2 mute property is set to 1 (true), the driver will turn the chip off.
|
||||
|
||||
Properties description
|
||||
======================
|
||||
|
||||
The properties can be accessed using v4l2 extended controls.
|
||||
Here is an output from v4l2-ctl util:
|
||||
/ # v4l2-ctl -d /dev/radio0 --all -L
|
||||
Driver Info:
|
||||
Driver name : radio-si4713
|
||||
Card type : Silicon Labs Si4713 Modulator
|
||||
Bus info :
|
||||
Driver version: 0
|
||||
Capabilities : 0x00080800
|
||||
RDS Output
|
||||
Modulator
|
||||
Audio output: 0 (FM Modulator Audio Out)
|
||||
Frequency: 1408000 (88.000000 MHz)
|
||||
Video Standard = 0x00000000
|
||||
Modulator:
|
||||
Name : FM Modulator
|
||||
Capabilities : 62.5 Hz stereo rds
|
||||
Frequency range : 76.0 MHz - 108.0 MHz
|
||||
Subchannel modulation: stereo+rds
|
||||
|
||||
User Controls
|
||||
|
||||
mute (bool) : default=1 value=0
|
||||
|
||||
FM Radio Modulator Controls
|
||||
|
||||
rds_signal_deviation (int) : min=0 max=90000 step=10 default=200 value=200 flags=slider
|
||||
rds_program_id (int) : min=0 max=65535 step=1 default=0 value=0
|
||||
rds_program_type (int) : min=0 max=31 step=1 default=0 value=0
|
||||
rds_ps_name (str) : min=0 max=96 step=8 value='si4713 '
|
||||
rds_radio_text (str) : min=0 max=384 step=32 value=''
|
||||
audio_limiter_feature_enabled (bool) : default=1 value=1
|
||||
audio_limiter_release_time (int) : min=250 max=102390 step=50 default=5010 value=5010 flags=slider
|
||||
audio_limiter_deviation (int) : min=0 max=90000 step=10 default=66250 value=66250 flags=slider
|
||||
audio_compression_feature_enabl (bool) : default=1 value=1
|
||||
audio_compression_gain (int) : min=0 max=20 step=1 default=15 value=15 flags=slider
|
||||
audio_compression_threshold (int) : min=-40 max=0 step=1 default=-40 value=-40 flags=slider
|
||||
audio_compression_attack_time (int) : min=0 max=5000 step=500 default=0 value=0 flags=slider
|
||||
audio_compression_release_time (int) : min=100000 max=1000000 step=100000 default=1000000 value=1000000 flags=slider
|
||||
pilot_tone_feature_enabled (bool) : default=1 value=1
|
||||
pilot_tone_deviation (int) : min=0 max=90000 step=10 default=6750 value=6750 flags=slider
|
||||
pilot_tone_frequency (int) : min=0 max=19000 step=1 default=19000 value=19000 flags=slider
|
||||
pre_emphasis_settings (menu) : min=0 max=2 default=1 value=1
|
||||
tune_power_level (int) : min=0 max=120 step=1 default=88 value=88 flags=slider
|
||||
tune_antenna_capacitor (int) : min=0 max=191 step=1 default=0 value=110 flags=slider
|
||||
/ #
|
||||
|
||||
Here is a summary of them:
|
||||
|
||||
* Pilot is an audible tone sent by the device.
|
||||
|
||||
pilot_frequency - Configures the frequency of the stereo pilot tone.
|
||||
pilot_deviation - Configures pilot tone frequency deviation level.
|
||||
pilot_enabled - Enables or disables the pilot tone feature.
|
||||
|
||||
* The si4713 device is capable of applying audio compression to the transmitted signal.
|
||||
|
||||
acomp_enabled - Enables or disables the audio dynamic range control feature.
|
||||
acomp_gain - Sets the gain for audio dynamic range control.
|
||||
acomp_threshold - Sets the threshold level for audio dynamic range control.
|
||||
acomp_attack_time - Sets the attack time for audio dynamic range control.
|
||||
acomp_release_time - Sets the release time for audio dynamic range control.
|
||||
|
||||
* Limiter setups audio deviation limiter feature. Once a over deviation occurs,
|
||||
it is possible to adjust the front-end gain of the audio input and always
|
||||
prevent over deviation.
|
||||
|
||||
limiter_enabled - Enables or disables the limiter feature.
|
||||
limiter_deviation - Configures audio frequency deviation level.
|
||||
limiter_release_time - Sets the limiter release time.
|
||||
|
||||
* Tuning power
|
||||
|
||||
power_level - Sets the output power level for signal transmission.
|
||||
antenna_capacitor - This selects the value of antenna tuning capacitor manually
|
||||
or automatically if set to zero.
|
||||
|
||||
* RDS related
|
||||
|
||||
rds_ps_name - Sets the RDS ps name field for transmission.
|
||||
rds_radio_text - Sets the RDS radio text for transmission.
|
||||
rds_pi - Sets the RDS PI field for transmission.
|
||||
rds_pty - Sets the RDS PTY field for transmission.
|
||||
|
||||
* Region related
|
||||
|
||||
preemphasis - sets the preemphasis to be applied for transmission.
|
||||
|
||||
RNL
|
||||
===
|
||||
|
||||
This device also has an interface to measure received noise level. To do that, you should
|
||||
ioctl the device node. Here is an code of example:
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
struct si4713_rnl rnl;
|
||||
int fd = open("/dev/radio0", O_RDWR);
|
||||
int rval;
|
||||
|
||||
if (argc < 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
sscanf(argv[1], "%d", &rnl.frequency);
|
||||
|
||||
rval = ioctl(fd, SI4713_IOC_MEASURE_RNL, &rnl);
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
|
||||
printf("received noise level: %d\n", rnl.rnl);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
The struct si4713_rnl and SI4713_IOC_MEASURE_RNL are defined under
|
||||
include/media/si4713.h.
|
||||
|
||||
Stereo/Mono and RDS subchannels
|
||||
===============================
|
||||
|
||||
The device can also be configured using the available sub channels for
|
||||
transmission. To do that use S/G_MODULATOR ioctl and configure txsubchans properly.
|
||||
Refer to v4l2-spec for proper use of this ioctl.
|
||||
|
||||
Testing
|
||||
=======
|
||||
Testing is usually done with v4l2-ctl utility for managing FM tuner cards.
|
||||
The tool can be found in v4l-dvb repository under v4l2-apps/util directory.
|
||||
|
||||
Example for setting rds ps name:
|
||||
# v4l2-ctl -d /dev/radio0 --set-ctrl=rds_ps_name="Dummy"
|
||||
|
|
@ -12,6 +12,7 @@ Offset Proto Name Meaning
|
|||
000/040 ALL screen_info Text mode or frame buffer information
|
||||
(struct screen_info)
|
||||
040/014 ALL apm_bios_info APM BIOS information (struct apm_bios_info)
|
||||
058/008 ALL tboot_addr Physical address of tboot shared page
|
||||
060/010 ALL ist_info Intel SpeedStep (IST) BIOS support information
|
||||
(struct ist_info)
|
||||
080/010 ALL hd0_info hd0 disk parameter, OBSOLETE!!
|
||||
|
|
26
MAINTAINERS
26
MAINTAINERS
|
@ -931,6 +931,12 @@ W: http://wireless.kernel.org/en/users/Drivers/ar9170
|
|||
S: Maintained
|
||||
F: drivers/net/wireless/ath/ar9170/
|
||||
|
||||
ATK0110 HWMON DRIVER
|
||||
M: Luca Tettamanti <kronos.it@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/asus_atk0110.c
|
||||
|
||||
ATI_REMOTE2 DRIVER
|
||||
M: Ville Syrjala <syrjala@sci.fi>
|
||||
S: Maintained
|
||||
|
@ -2152,13 +2158,16 @@ F: Documentation/filesystems/caching/
|
|||
F: fs/fscache/
|
||||
F: include/linux/fscache*.h
|
||||
|
||||
FTRACE
|
||||
TRACING
|
||||
M: Steven Rostedt <rostedt@goodmis.org>
|
||||
M: Frederic Weisbecker <fweisbec@gmail.com>
|
||||
M: Ingo Molnar <mingo@redhat.com>
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git tracing/core
|
||||
S: Maintained
|
||||
F: Documentation/trace/ftrace.txt
|
||||
F: arch/*/*/*/ftrace.h
|
||||
F: arch/*/kernel/ftrace.c
|
||||
F: include/*/ftrace.h
|
||||
F: include/*/ftrace.h include/trace/ include/linux/trace*.h
|
||||
F: kernel/trace/
|
||||
|
||||
FUJITSU FR-V (FRV) PORT
|
||||
|
@ -2218,6 +2227,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git
|
|||
S: Maintained
|
||||
F: include/asm-generic
|
||||
|
||||
GENERIC UIO DRIVER FOR PCI DEVICES
|
||||
M: Michael S. Tsirkin <mst@redhat.com>
|
||||
L: kvm@vger.kernel.org
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/uio/uio_pci_generic.c
|
||||
|
||||
GFS2 FILE SYSTEM
|
||||
M: Steven Whitehouse <swhiteho@redhat.com>
|
||||
L: cluster-devel@redhat.com
|
||||
|
@ -3317,7 +3333,7 @@ S: Supported
|
|||
F: drivers/net/wireless/mwl8k.c
|
||||
|
||||
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
|
||||
M: Nicolas Pitre <nico@cam.org>
|
||||
M: Nicolas Pitre <nico@fluxnic.net>
|
||||
S: Maintained
|
||||
|
||||
MARVELL YUKON / SYSKONNECT DRIVER
|
||||
|
@ -4689,7 +4705,7 @@ F: include/linux/sl?b*.h
|
|||
F: mm/sl?b.c
|
||||
|
||||
SMC91x ETHERNET DRIVER
|
||||
M: Nicolas Pitre <nico@cam.org>
|
||||
M: Nicolas Pitre <nico@fluxnic.net>
|
||||
S: Maintained
|
||||
F: drivers/net/smc91x.*
|
||||
|
||||
|
@ -5694,7 +5710,7 @@ F: include/xen/
|
|||
|
||||
XFS FILESYSTEM
|
||||
P: Silicon Graphics Inc
|
||||
M: Felix Blyakher <felixb@sgi.com>
|
||||
M: Alex Elder <aelder@sgi.com>
|
||||
M: xfs-masters@oss.sgi.com
|
||||
L: xfs@oss.sgi.com
|
||||
W: http://oss.sgi.com/projects/xfs
|
||||
|
|
2
Makefile
2
Makefile
|
@ -325,7 +325,7 @@ CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
|
|||
MODFLAGS = -DMODULE
|
||||
CFLAGS_MODULE = $(MODFLAGS)
|
||||
AFLAGS_MODULE = $(MODFLAGS)
|
||||
LDFLAGS_MODULE =
|
||||
LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds
|
||||
CFLAGS_KERNEL =
|
||||
AFLAGS_KERNEL =
|
||||
CFLAGS_GCOV = -fprofile-arcs -ftest-coverage
|
||||
|
|
|
@ -9,6 +9,7 @@ config OPROFILE
|
|||
depends on TRACING_SUPPORT
|
||||
select TRACING
|
||||
select RING_BUFFER
|
||||
select RING_BUFFER_ALLOW_SWAP
|
||||
help
|
||||
OProfile is a profiling system capable of profiling the
|
||||
whole system, include the kernel, kernel modules, libraries,
|
||||
|
|
|
@ -9,10 +9,6 @@
|
|||
#define unmap_page_from_agp(page)
|
||||
#define flush_agp_cache() mb()
|
||||
|
||||
/* Convert a physical address to an address suitable for the GART. */
|
||||
#define phys_to_gart(x) (x)
|
||||
#define gart_to_phys(x) (x)
|
||||
|
||||
/* GATT allocation. Returns/accepts GATT kernel virtual address. */
|
||||
#define alloc_gatt_pages(order) \
|
||||
((char *)__get_free_pages(GFP_KERNEL, (order)))
|
||||
|
|
|
@ -52,7 +52,6 @@ struct pci_controller {
|
|||
bus numbers. */
|
||||
|
||||
#define pcibios_assign_all_busses() 1
|
||||
#define pcibios_scan_all_fns(a, b) 0
|
||||
|
||||
#define PCIBIOS_MIN_IO alpha_mv.min_io_address
|
||||
#define PCIBIOS_MIN_MEM alpha_mv.min_mem_address
|
||||
|
|
|
@ -1,102 +1,18 @@
|
|||
#ifndef __ALPHA_PERCPU_H
|
||||
#define __ALPHA_PERCPU_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/percpu-defs.h>
|
||||
|
||||
/*
|
||||
* Determine the real variable name from the name visible in the
|
||||
* kernel sources.
|
||||
*/
|
||||
#define per_cpu_var(var) per_cpu__##var
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/*
|
||||
* per_cpu_offset() is the offset that has to be added to a
|
||||
* percpu variable to get to the instance for a certain processor.
|
||||
*/
|
||||
extern unsigned long __per_cpu_offset[NR_CPUS];
|
||||
|
||||
#define per_cpu_offset(x) (__per_cpu_offset[x])
|
||||
|
||||
#define __my_cpu_offset per_cpu_offset(raw_smp_processor_id())
|
||||
#ifdef CONFIG_DEBUG_PREEMPT
|
||||
#define my_cpu_offset per_cpu_offset(smp_processor_id())
|
||||
#else
|
||||
#define my_cpu_offset __my_cpu_offset
|
||||
#endif
|
||||
|
||||
#ifndef MODULE
|
||||
#define SHIFT_PERCPU_PTR(var, offset) RELOC_HIDE(&per_cpu_var(var), (offset))
|
||||
#define PER_CPU_DEF_ATTRIBUTES
|
||||
#else
|
||||
/*
|
||||
* To calculate addresses of locally defined variables, GCC uses 32-bit
|
||||
* displacement from the GP. Which doesn't work for per cpu variables in
|
||||
* modules, as an offset to the kernel per cpu area is way above 4G.
|
||||
* To calculate addresses of locally defined variables, GCC uses
|
||||
* 32-bit displacement from the GP. Which doesn't work for per cpu
|
||||
* variables in modules, as an offset to the kernel per cpu area is
|
||||
* way above 4G.
|
||||
*
|
||||
* This forces allocation of a GOT entry for per cpu variable using
|
||||
* ldq instruction with a 'literal' relocation.
|
||||
* Always use weak definitions for percpu variables in modules.
|
||||
*/
|
||||
#define SHIFT_PERCPU_PTR(var, offset) ({ \
|
||||
extern int simple_identifier_##var(void); \
|
||||
unsigned long __ptr, tmp_gp; \
|
||||
asm ( "br %1, 1f \n\
|
||||
1: ldgp %1, 0(%1) \n\
|
||||
ldq %0, per_cpu__" #var"(%1)\t!literal" \
|
||||
: "=&r"(__ptr), "=&r"(tmp_gp)); \
|
||||
(typeof(&per_cpu_var(var)))(__ptr + (offset)); })
|
||||
|
||||
#define PER_CPU_DEF_ATTRIBUTES __used
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
/*
|
||||
* A percpu variable may point to a discarded regions. The following are
|
||||
* established ways to produce a usable pointer from the percpu variable
|
||||
* offset.
|
||||
*/
|
||||
#define per_cpu(var, cpu) \
|
||||
(*SHIFT_PERCPU_PTR(var, per_cpu_offset(cpu)))
|
||||
#define __get_cpu_var(var) \
|
||||
(*SHIFT_PERCPU_PTR(var, my_cpu_offset))
|
||||
#define __raw_get_cpu_var(var) \
|
||||
(*SHIFT_PERCPU_PTR(var, __my_cpu_offset))
|
||||
|
||||
#else /* ! SMP */
|
||||
|
||||
#define per_cpu(var, cpu) (*((void)(cpu), &per_cpu_var(var)))
|
||||
#define __get_cpu_var(var) per_cpu_var(var)
|
||||
#define __raw_get_cpu_var(var) per_cpu_var(var)
|
||||
|
||||
#define PER_CPU_DEF_ATTRIBUTES
|
||||
|
||||
#endif /* SMP */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define PER_CPU_BASE_SECTION ".data.percpu"
|
||||
#else
|
||||
#define PER_CPU_BASE_SECTION ".data"
|
||||
#if defined(MODULE) && defined(CONFIG_SMP)
|
||||
#define ARCH_NEEDS_WEAK_PER_CPU
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#ifdef MODULE
|
||||
#define PER_CPU_SHARED_ALIGNED_SECTION ""
|
||||
#else
|
||||
#define PER_CPU_SHARED_ALIGNED_SECTION ".shared_aligned"
|
||||
#endif
|
||||
#define PER_CPU_FIRST_SECTION ".first"
|
||||
|
||||
#else
|
||||
|
||||
#define PER_CPU_SHARED_ALIGNED_SECTION ""
|
||||
#define PER_CPU_FIRST_SECTION ""
|
||||
|
||||
#endif
|
||||
|
||||
#define PER_CPU_ATTRIBUTES
|
||||
#include <asm-generic/percpu.h>
|
||||
|
||||
#endif /* __ALPHA_PERCPU_H */
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _ALPHA_TLBFLUSH_H
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/compiler.h>
|
||||
#include <asm/pgalloc.h>
|
||||
|
||||
|
|
|
@ -134,13 +134,6 @@ SECTIONS
|
|||
__bss_stop = .;
|
||||
_end = .;
|
||||
|
||||
/* Sections to be discarded */
|
||||
/DISCARD/ : {
|
||||
EXIT_TEXT
|
||||
EXIT_DATA
|
||||
*(.exitcall.exit)
|
||||
}
|
||||
|
||||
.mdebug 0 : {
|
||||
*(.mdebug)
|
||||
}
|
||||
|
@ -150,4 +143,6 @@ SECTIONS
|
|||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
|
||||
DISCARDS
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* linux/arch/arm/boot/compressed/head-sa1100.S
|
||||
*
|
||||
* Copyright (C) 1999 Nicolas Pitre <nico@cam.org>
|
||||
* Copyright (C) 1999 Nicolas Pitre <nico@fluxnic.net>
|
||||
*
|
||||
* SA1100 specific tweaks. This is merged into head.S by the linker.
|
||||
*
|
||||
|
|
|
@ -19,31 +19,21 @@
|
|||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/*
|
||||
* On ARM, ordinary assignment (str instruction) doesn't clear the local
|
||||
* strex/ldrex monitor on some implementations. The reason we can use it for
|
||||
* atomic_set() is the clrex or dummy strex done on every exception return.
|
||||
*/
|
||||
#define atomic_read(v) ((v)->counter)
|
||||
#define atomic_set(v,i) (((v)->counter) = (i))
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 6
|
||||
|
||||
/*
|
||||
* ARMv6 UP and SMP safe atomic ops. We use load exclusive and
|
||||
* store exclusive to ensure that these are atomic. We may loop
|
||||
* to ensure that the update happens. Writing to 'v->counter'
|
||||
* without using the following operations WILL break the atomic
|
||||
* nature of these ops.
|
||||
* to ensure that the update happens.
|
||||
*/
|
||||
static inline void atomic_set(atomic_t *v, int i)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__("@ atomic_set\n"
|
||||
"1: ldrex %0, [%1]\n"
|
||||
" strex %0, %2, [%1]\n"
|
||||
" teq %0, #0\n"
|
||||
" bne 1b"
|
||||
: "=&r" (tmp)
|
||||
: "r" (&v->counter), "r" (i)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
static inline void atomic_add(int i, atomic_t *v)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
@ -163,8 +153,6 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
|
|||
#error SMP not supported on pre-ARMv6 CPUs
|
||||
#endif
|
||||
|
||||
#define atomic_set(v,i) (((v)->counter) = (i))
|
||||
|
||||
static inline int atomic_add_return(int i, atomic_t *v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#include <mach/hardware.h> /* for PCIBIOS_MIN_* */
|
||||
|
||||
#define pcibios_scan_all_fns(a, b) 0
|
||||
|
||||
#ifdef CONFIG_PCI_HOST_ITE8152
|
||||
/* ITE bridge requires setting latency timer to avoid early bus access
|
||||
termination by PIC bus mater devices
|
||||
|
|
|
@ -35,7 +35,9 @@
|
|||
|
||||
#define ARM(x...)
|
||||
#define THUMB(x...) x
|
||||
#ifdef __ASSEMBLY__
|
||||
#define W(instr) instr.w
|
||||
#endif
|
||||
#define BSYM(sym) sym + 1
|
||||
|
||||
#else /* !CONFIG_THUMB2_KERNEL */
|
||||
|
@ -45,7 +47,9 @@
|
|||
|
||||
#define ARM(x...) x
|
||||
#define THUMB(x...)
|
||||
#ifdef __ASSEMBLY__
|
||||
#define W(instr) instr
|
||||
#endif
|
||||
#define BSYM(sym) sym
|
||||
|
||||
#endif /* CONFIG_THUMB2_KERNEL */
|
||||
|
|
|
@ -272,7 +272,15 @@ __und_svc:
|
|||
@
|
||||
@ r0 - instruction
|
||||
@
|
||||
#ifndef CONFIG_THUMB2_KERNEL
|
||||
ldr r0, [r2, #-4]
|
||||
#else
|
||||
ldrh r0, [r2, #-2] @ Thumb instruction at LR - 2
|
||||
and r9, r0, #0xf800
|
||||
cmp r9, #0xe800 @ 32-bit instruction if xx >= 0
|
||||
ldrhhs r9, [r2] @ bottom 16 bits
|
||||
orrhs r0, r9, r0, lsl #16
|
||||
#endif
|
||||
adr r9, BSYM(1f)
|
||||
bl call_fpe
|
||||
|
||||
|
@ -678,7 +686,9 @@ ENTRY(fp_enter)
|
|||
.word no_fp
|
||||
.previous
|
||||
|
||||
no_fp: mov pc, lr
|
||||
ENTRY(no_fp)
|
||||
mov pc, lr
|
||||
ENDPROC(no_fp)
|
||||
|
||||
__und_usr_unknown:
|
||||
enable_irq
|
||||
|
@ -734,13 +744,6 @@ ENTRY(__switch_to)
|
|||
#ifdef CONFIG_MMU
|
||||
ldr r6, [r2, #TI_CPU_DOMAIN]
|
||||
#endif
|
||||
#if __LINUX_ARM_ARCH__ >= 6
|
||||
#ifdef CONFIG_CPU_32v6K
|
||||
clrex
|
||||
#else
|
||||
strex r5, r4, [ip] @ Clear exclusive monitor
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_HAS_TLS_REG)
|
||||
mcr p15, 0, r3, c13, c0, 3 @ set TLS register
|
||||
#elif !defined(CONFIG_TLS_REG_EMUL)
|
||||
|
|
|
@ -76,13 +76,25 @@
|
|||
#ifndef CONFIG_THUMB2_KERNEL
|
||||
.macro svc_exit, rpsr
|
||||
msr spsr_cxsf, \rpsr
|
||||
#if defined(CONFIG_CPU_32v6K)
|
||||
clrex @ clear the exclusive monitor
|
||||
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
|
||||
#elif defined (CONFIG_CPU_V6)
|
||||
ldr r0, [sp]
|
||||
strex r1, r2, [sp] @ clear the exclusive monitor
|
||||
ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro restore_user_regs, fast = 0, offset = 0
|
||||
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
|
||||
ldr lr, [sp, #\offset + S_PC]! @ get pc
|
||||
msr spsr_cxsf, r1 @ save in spsr_svc
|
||||
#if defined(CONFIG_CPU_32v6K)
|
||||
clrex @ clear the exclusive monitor
|
||||
#elif defined (CONFIG_CPU_V6)
|
||||
strex r1, r2, [sp] @ clear the exclusive monitor
|
||||
#endif
|
||||
.if \fast
|
||||
ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
|
||||
.else
|
||||
|
@ -98,6 +110,7 @@
|
|||
.endm
|
||||
#else /* CONFIG_THUMB2_KERNEL */
|
||||
.macro svc_exit, rpsr
|
||||
clrex @ clear the exclusive monitor
|
||||
ldr r0, [sp, #S_SP] @ top of the stack
|
||||
ldr r1, [sp, #S_PC] @ return address
|
||||
tst r0, #4 @ orig stack 8-byte aligned?
|
||||
|
@ -110,6 +123,7 @@
|
|||
.endm
|
||||
|
||||
.macro restore_user_regs, fast = 0, offset = 0
|
||||
clrex @ clear the exclusive monitor
|
||||
mov r2, sp
|
||||
load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr
|
||||
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
|
||||
|
|
|
@ -83,6 +83,7 @@ SECTIONS
|
|||
EXIT_TEXT
|
||||
EXIT_DATA
|
||||
*(.exitcall.exit)
|
||||
*(.discard)
|
||||
*(.ARM.exidx.exit.text)
|
||||
*(.ARM.extab.exit.text)
|
||||
#ifndef CONFIG_HOTPLUG_CPU
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
|
||||
*
|
||||
* Author: Nicolas Pitre <nico@cam.org>
|
||||
* Author: Nicolas Pitre <nico@fluxnic.net>
|
||||
* - contributed to gcc-3.4 on Sep 30, 2003
|
||||
* - adapted for the Linux kernel on Oct 2, 2003
|
||||
*/
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* SHA transform optimized for ARM
|
||||
*
|
||||
* Copyright: (C) 2005 by Nicolas Pitre <nico@cam.org>
|
||||
* Copyright: (C) 2005 by Nicolas Pitre <nico@fluxnic.net>
|
||||
* Created: September 17, 2005
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* arch/arm/mach-sa1100/include/mach/assabet.h
|
||||
*
|
||||
* Created 2000/06/05 by Nicolas Pitre <nico@cam.org>
|
||||
* Created 2000/06/05 by Nicolas Pitre <nico@fluxnic.net>
|
||||
*
|
||||
* This file contains the hardware specific definitions for Assabet
|
||||
* Only include this file from SA1100-specific files.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* arch/arm/mach-sa1100/include/mach/hardware.h
|
||||
*
|
||||
* Copyright (C) 1998 Nicolas Pitre <nico@cam.org>
|
||||
* Copyright (C) 1998 Nicolas Pitre <nico@fluxnic.net>
|
||||
*
|
||||
* This file contains the hardware definitions for SA1100 architecture
|
||||
*
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* arch/arm/mach-sa1100/include/mach/memory.h
|
||||
*
|
||||
* Copyright (C) 1999-2000 Nicolas Pitre <nico@cam.org>
|
||||
* Copyright (C) 1999-2000 Nicolas Pitre <nico@fluxnic.net>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_MEMORY_H
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* arch/arm/mach-sa1100/include/mach/neponset.h
|
||||
*
|
||||
* Created 2000/06/05 by Nicolas Pitre <nico@cam.org>
|
||||
* Created 2000/06/05 by Nicolas Pitre <nico@fluxnic.net>
|
||||
*
|
||||
* This file contains the hardware specific definitions for Assabet
|
||||
* Only include this file from SA1100-specific files.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* arch/arm/mach-sa1100/include/mach/system.h
|
||||
*
|
||||
* Copyright (c) 1999 Nicolas Pitre <nico@cam.org>
|
||||
* Copyright (c) 1999 Nicolas Pitre <nico@fluxnic.net>
|
||||
*/
|
||||
#include <mach/hardware.h>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* arch/arm/mach-sa1100/include/mach/uncompress.h
|
||||
*
|
||||
* (C) 1999 Nicolas Pitre <nico@cam.org>
|
||||
* (C) 1999 Nicolas Pitre <nico@fluxnic.net>
|
||||
*
|
||||
* Reorganised to be machine independent.
|
||||
*/
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* Save more value for the resume function! Support
|
||||
* Bitsy/Assabet/Freebird board
|
||||
*
|
||||
* 2001-08-29: Nicolas Pitre <nico@cam.org>
|
||||
* 2001-08-29: Nicolas Pitre <nico@fluxnic.net>
|
||||
* Cleaned up, pushed platform dependent stuff
|
||||
* in the platform specific files.
|
||||
*
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 1998 Deborah Wallach.
|
||||
* Twiddles (C) 1999 Hugo Fiennes <hugo@empeg.com>
|
||||
*
|
||||
* 2000/03/29 (C) Nicolas Pitre <nico@cam.org>
|
||||
* 2000/03/29 (C) Nicolas Pitre <nico@fluxnic.net>
|
||||
* Rewritten: big cleanup, much simpler, better HZ accuracy.
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*
|
||||
* 2001 Sep 08:
|
||||
* Completely revisited, many important fixes
|
||||
* Nicolas Pitre <nico@cam.org>
|
||||
* Nicolas Pitre <nico@fluxnic.net>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* arch/arm/plat-iop/setup.c
|
||||
*
|
||||
* Author: Nicolas Pitre <nico@cam.org>
|
||||
* Author: Nicolas Pitre <nico@fluxnic.net>
|
||||
* Copyright (C) 2001 MontaVista Software, Inc.
|
||||
* Copyright (C) 2004 Intel Corporation.
|
||||
*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copied from arch/arm/mach-sa1100/include/mach/system.h
|
||||
* Copyright (c) 1999 Nicolas Pitre <nico@cam.org>
|
||||
* Copyright (c) 1999 Nicolas Pitre <nico@fluxnic.net>
|
||||
*/
|
||||
#ifndef __ASM_ARCH_SYSTEM_H
|
||||
#define __ASM_ARCH_SYSTEM_H
|
||||
|
|
|
@ -124,14 +124,11 @@ SECTIONS
|
|||
_end = .;
|
||||
}
|
||||
|
||||
DWARF_DEBUG
|
||||
|
||||
/* When something in the kernel is NOT compiled as a module, the module
|
||||
* cleanup code and data are put into these segments. Both can then be
|
||||
* thrown away, as cleanup code is never called unless it's a module.
|
||||
*/
|
||||
/DISCARD/ : {
|
||||
EXIT_DATA
|
||||
*(.exitcall.exit)
|
||||
}
|
||||
|
||||
DWARF_DEBUG
|
||||
DISCARDS
|
||||
}
|
||||
|
|
|
@ -342,8 +342,9 @@ config MEM_MT48LC64M4A2FB_7E
|
|||
config MEM_MT48LC16M16A2TG_75
|
||||
bool
|
||||
depends on (BFIN533_EZKIT || BFIN561_EZKIT \
|
||||
|| BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM \
|
||||
|| H8606_HVSISTEMAS || BFIN527_BLUETECHNIX_CM)
|
||||
|| BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM_E \
|
||||
|| BFIN537_BLUETECHNIX_CM_U || H8606_HVSISTEMAS \
|
||||
|| BFIN527_BLUETECHNIX_CM)
|
||||
default y
|
||||
|
||||
config MEM_MT48LC32M8A2_75
|
||||
|
@ -459,7 +460,7 @@ config VCO_MULT
|
|||
default "45" if BFIN533_STAMP
|
||||
default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM || BFIN538_EZKIT)
|
||||
default "22" if BFIN533_BLUETECHNIX_CM
|
||||
default "20" if (BFIN537_BLUETECHNIX_CM || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM)
|
||||
default "20" if (BFIN537_BLUETECHNIX_CM_E || BFIN537_BLUETECHNIX_CM_U || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM)
|
||||
default "20" if BFIN561_EZKIT
|
||||
default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN518F_EZBRD)
|
||||
help
|
||||
|
@ -574,8 +575,8 @@ config MAX_VCO_HZ
|
|||
default 400000000 if BF514
|
||||
default 400000000 if BF516
|
||||
default 400000000 if BF518
|
||||
default 600000000 if BF522
|
||||
default 400000000 if BF523
|
||||
default 400000000 if BF522
|
||||
default 600000000 if BF523
|
||||
default 400000000 if BF524
|
||||
default 600000000 if BF525
|
||||
default 400000000 if BF526
|
||||
|
@ -647,7 +648,7 @@ config CYCLES_CLOCKSOURCE
|
|||
writing the registers will most likely crash the kernel.
|
||||
|
||||
config GPTMR0_CLOCKSOURCE
|
||||
bool "Use GPTimer0 as a clocksource (higher rating)"
|
||||
bool "Use GPTimer0 as a clocksource"
|
||||
select BFIN_GPTIMERS
|
||||
depends on GENERIC_CLOCKEVENTS
|
||||
depends on !TICKSOURCE_GPTMR0
|
||||
|
@ -917,10 +918,6 @@ comment "Cache Support"
|
|||
config BFIN_ICACHE
|
||||
bool "Enable ICACHE"
|
||||
default y
|
||||
config BFIN_ICACHE_LOCK
|
||||
bool "Enable Instruction Cache Locking"
|
||||
depends on BFIN_ICACHE
|
||||
default n
|
||||
config BFIN_EXTMEM_ICACHEABLE
|
||||
bool "Enable ICACHE for external memory"
|
||||
depends on BFIN_ICACHE
|
||||
|
@ -987,7 +984,7 @@ endchoice
|
|||
config BFIN_L2_DCACHEABLE
|
||||
bool "Enable DCACHE for L2 SRAM"
|
||||
depends on BFIN_DCACHE
|
||||
depends on BF54x || BF561
|
||||
depends on (BF54x || BF561) && !SMP
|
||||
default n
|
||||
choice
|
||||
prompt "L2 SRAM DCACHE policy"
|
||||
|
@ -995,11 +992,9 @@ choice
|
|||
default BFIN_L2_WRITEBACK
|
||||
config BFIN_L2_WRITEBACK
|
||||
bool "Write back"
|
||||
depends on !SMP
|
||||
|
||||
config BFIN_L2_WRITETHROUGH
|
||||
bool "Write through"
|
||||
depends on !SMP
|
||||
endchoice
|
||||
|
||||
|
||||
|
@ -1154,11 +1149,12 @@ source "fs/Kconfig.binfmt"
|
|||
endmenu
|
||||
|
||||
menu "Power management options"
|
||||
depends on !SMP
|
||||
|
||||
source "kernel/power/Kconfig"
|
||||
|
||||
config ARCH_SUSPEND_POSSIBLE
|
||||
def_bool y
|
||||
depends on !SMP
|
||||
|
||||
choice
|
||||
prompt "Standby Power Saving Mode"
|
||||
|
@ -1246,6 +1242,7 @@ config PM_BFIN_WAKE_GP
|
|||
endmenu
|
||||
|
||||
menu "CPU Frequency scaling"
|
||||
depends on !SMP
|
||||
|
||||
source "drivers/cpufreq/Kconfig"
|
||||
|
||||
|
|
|
@ -252,4 +252,10 @@ config ACCESS_CHECK
|
|||
|
||||
Say N here to disable that check to improve the performance.
|
||||
|
||||
config BFIN_ISRAM_SELF_TEST
|
||||
bool "isram boot self tests"
|
||||
default n
|
||||
help
|
||||
Run some self tests of the isram driver code at boot.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -358,9 +358,9 @@ CONFIG_C_AMBEN_ALL=y
|
|||
# EBIU_AMBCTL Control
|
||||
#
|
||||
CONFIG_BANK_0=0x7BB0
|
||||
CONFIG_BANK_1=0x5554
|
||||
CONFIG_BANK_1=0x7BB0
|
||||
CONFIG_BANK_2=0x7BB0
|
||||
CONFIG_BANK_3=0xFFC0
|
||||
CONFIG_BANK_3=0x99B2
|
||||
|
||||
#
|
||||
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
|
||||
|
|
|
@ -359,9 +359,9 @@ CONFIG_C_AMBEN_ALL=y
|
|||
# EBIU_AMBCTL Control
|
||||
#
|
||||
CONFIG_BANK_0=0x7BB0
|
||||
CONFIG_BANK_1=0x5554
|
||||
CONFIG_BANK_1=0x7BB0
|
||||
CONFIG_BANK_2=0x7BB0
|
||||
CONFIG_BANK_3=0xFFC0
|
||||
CONFIG_BANK_3=0x99B2
|
||||
|
||||
#
|
||||
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
|
||||
|
|
|
@ -363,9 +363,9 @@ CONFIG_C_AMBEN_ALL=y
|
|||
# EBIU_AMBCTL Control
|
||||
#
|
||||
CONFIG_BANK_0=0x7BB0
|
||||
CONFIG_BANK_1=0x5554
|
||||
CONFIG_BANK_1=0x7BB0
|
||||
CONFIG_BANK_2=0x7BB0
|
||||
CONFIG_BANK_3=0xFFC0
|
||||
CONFIG_BANK_3=0x99B2
|
||||
|
||||
#
|
||||
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
|
||||
|
|
|
@ -400,7 +400,7 @@ CONFIG_C_AMBEN_ALL=y
|
|||
# EBIU_AMBCTL Control
|
||||
#
|
||||
CONFIG_BANK_0=0x7BB0
|
||||
CONFIG_BANK_1=0x5554
|
||||
CONFIG_BANK_1=0x7BB0
|
||||
CONFIG_BANK_2=0x7BB0
|
||||
CONFIG_BANK_3=0x99B2
|
||||
CONFIG_EBIU_MBSCTLVAL=0x0
|
||||
|
|
|
@ -66,7 +66,6 @@ extern void program_IAR(void);
|
|||
|
||||
extern asmlinkage void lower_to_irq14(void);
|
||||
extern asmlinkage void bfin_return_from_exception(void);
|
||||
extern asmlinkage void evt14_softirq(void);
|
||||
extern asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs);
|
||||
extern int bfin_internal_set_wake(unsigned int irq, unsigned int state);
|
||||
|
||||
|
@ -100,11 +99,6 @@ extern unsigned long bfin_sic_iwr[];
|
|||
extern unsigned vr_wakeup;
|
||||
extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */
|
||||
|
||||
#ifdef CONFIG_BFIN_ICACHE_LOCK
|
||||
extern void cache_grab_lock(int way);
|
||||
extern void bfin_cache_lock(int way);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _BLACKFIN_H_ */
|
||||
|
|
|
@ -127,6 +127,7 @@ struct bfin5xx_spi_chip {
|
|||
u32 cs_gpio;
|
||||
/* Value to send if no TX value is supplied, usually 0x0 or 0xFFFF */
|
||||
u16 idle_tx_val;
|
||||
u8 pio_interrupt; /* Enable spi data irq */
|
||||
};
|
||||
|
||||
#endif /* _SPI_CHANNEL_H_ */
|
||||
|
|
|
@ -125,4 +125,48 @@
|
|||
#define FAULT_USERSUPV (1 << 17)
|
||||
#define FAULT_CPLBBITS 0x0000ffff
|
||||
|
||||
#endif /* _CPLB_H */
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
static inline void _disable_cplb(u32 mmr, u32 mask)
|
||||
{
|
||||
u32 ctrl = bfin_read32(mmr) & ~mask;
|
||||
/* CSYNC to ensure load store ordering */
|
||||
__builtin_bfin_csync();
|
||||
bfin_write32(mmr, ctrl);
|
||||
__builtin_bfin_ssync();
|
||||
}
|
||||
static inline void disable_cplb(u32 mmr, u32 mask)
|
||||
{
|
||||
u32 ctrl = bfin_read32(mmr) & ~mask;
|
||||
CSYNC();
|
||||
bfin_write32(mmr, ctrl);
|
||||
SSYNC();
|
||||
}
|
||||
#define _disable_dcplb() _disable_cplb(DMEM_CONTROL, ENDCPLB)
|
||||
#define disable_dcplb() disable_cplb(DMEM_CONTROL, ENDCPLB)
|
||||
#define _disable_icplb() _disable_cplb(IMEM_CONTROL, ENICPLB)
|
||||
#define disable_icplb() disable_cplb(IMEM_CONTROL, ENICPLB)
|
||||
|
||||
static inline void _enable_cplb(u32 mmr, u32 mask)
|
||||
{
|
||||
u32 ctrl = bfin_read32(mmr) | mask;
|
||||
/* CSYNC to ensure load store ordering */
|
||||
__builtin_bfin_csync();
|
||||
bfin_write32(mmr, ctrl);
|
||||
__builtin_bfin_ssync();
|
||||
}
|
||||
static inline void enable_cplb(u32 mmr, u32 mask)
|
||||
{
|
||||
u32 ctrl = bfin_read32(mmr) | mask;
|
||||
CSYNC();
|
||||
bfin_write32(mmr, ctrl);
|
||||
SSYNC();
|
||||
}
|
||||
#define _enable_dcplb() _enable_cplb(DMEM_CONTROL, ENDCPLB)
|
||||
#define enable_dcplb() enable_cplb(DMEM_CONTROL, ENDCPLB)
|
||||
#define _enable_icplb() _enable_cplb(IMEM_CONTROL, ENICPLB)
|
||||
#define enable_icplb() enable_cplb(IMEM_CONTROL, ENICPLB)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _CPLB_H */
|
||||
|
|
|
@ -21,8 +21,32 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __ASM_EARLY_PRINTK_H__
|
||||
#define __ASM_EARLY_PRINTK_H__
|
||||
|
||||
#ifdef CONFIG_EARLY_PRINTK
|
||||
/* For those that don't include it already */
|
||||
#include <linux/console.h>
|
||||
|
||||
extern int setup_early_printk(char *);
|
||||
extern void enable_shadow_console(void);
|
||||
extern int shadow_console_enabled(void);
|
||||
extern void mark_shadow_error(void);
|
||||
extern void early_shadow_reg(unsigned long reg, unsigned int n);
|
||||
extern void early_shadow_write(struct console *con, const char *s,
|
||||
unsigned int n) __attribute__((nonnull(2)));
|
||||
#define early_shadow_puts(str) early_shadow_write(NULL, str, strlen(str))
|
||||
#define early_shadow_stamp() \
|
||||
do { \
|
||||
early_shadow_puts(__FILE__ " : " __stringify(__LINE__) " ["); \
|
||||
early_shadow_puts(__func__); \
|
||||
early_shadow_puts("]\n"); \
|
||||
} while (0)
|
||||
#else
|
||||
#define setup_early_printk(fmt) do { } while (0)
|
||||
#define enable_shadow_console(fmt) do { } while (0)
|
||||
#define early_shadow_stamp() do { } while (0)
|
||||
#endif /* CONFIG_EARLY_PRINTK */
|
||||
|
||||
#endif /* __ASM_EARLY_PRINTK_H__ */
|
||||
|
|
|
@ -23,7 +23,7 @@ typedef unsigned long elf_greg_t;
|
|||
#define ELF_NGREG 40 /* (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) */
|
||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
|
||||
typedef struct user_bfinfp_struct elf_fpregset_t;
|
||||
typedef struct { } elf_fpregset_t;
|
||||
/*
|
||||
* This is used to ensure we don't load something for the wrong architecture.
|
||||
*/
|
||||
|
|
|
@ -36,6 +36,21 @@
|
|||
# define LOAD_IPIPE_IPEND
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Workaround for anomalies 05000283 and 05000315
|
||||
*/
|
||||
#if ANOMALY_05000283 || ANOMALY_05000315
|
||||
# define ANOMALY_283_315_WORKAROUND(preg, dreg) \
|
||||
cc = dreg == dreg; \
|
||||
preg.h = HI(CHIPID); \
|
||||
preg.l = LO(CHIPID); \
|
||||
if cc jump 1f; \
|
||||
dreg.l = W[preg]; \
|
||||
1:
|
||||
#else
|
||||
# define ANOMALY_283_315_WORKAROUND(preg, dreg)
|
||||
#endif /* ANOMALY_05000283 || ANOMALY_05000315 */
|
||||
|
||||
#ifndef CONFIG_EXACT_HWERR
|
||||
/* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
|
||||
* otherwise it is a waste of cycles.
|
||||
|
@ -88,17 +103,22 @@
|
|||
* As you can see by the code - we actually need to do two SSYNCS - one to
|
||||
* make sure the read/writes complete, and another to make sure the hardware
|
||||
* error is recognized by the core.
|
||||
*
|
||||
* The extra nop before the SSYNC is to make sure we work around 05000244,
|
||||
* since the 283/315 workaround includes a branch to the end
|
||||
*/
|
||||
#define INTERRUPT_ENTRY(N) \
|
||||
SSYNC; \
|
||||
SSYNC; \
|
||||
[--sp] = SYSCFG; \
|
||||
[--sp] = P0; /*orig_p0*/ \
|
||||
[--sp] = R0; /*orig_r0*/ \
|
||||
[--sp] = (R7:0,P5:0); \
|
||||
R1 = ASTAT; \
|
||||
ANOMALY_283_315_WORKAROUND(p0, r0) \
|
||||
P0.L = LO(ILAT); \
|
||||
P0.H = HI(ILAT); \
|
||||
NOP; \
|
||||
SSYNC; \
|
||||
SSYNC; \
|
||||
R0 = [P0]; \
|
||||
CC = BITTST(R0, EVT_IVHW_P); \
|
||||
IF CC JUMP 1f; \
|
||||
|
@ -118,15 +138,17 @@
|
|||
RTI;
|
||||
|
||||
#define TIMER_INTERRUPT_ENTRY(N) \
|
||||
SSYNC; \
|
||||
SSYNC; \
|
||||
[--sp] = SYSCFG; \
|
||||
[--sp] = P0; /*orig_p0*/ \
|
||||
[--sp] = R0; /*orig_r0*/ \
|
||||
[--sp] = (R7:0,P5:0); \
|
||||
R1 = ASTAT; \
|
||||
ANOMALY_283_315_WORKAROUND(p0, r0) \
|
||||
P0.L = LO(ILAT); \
|
||||
P0.H = HI(ILAT); \
|
||||
NOP; \
|
||||
SSYNC; \
|
||||
SSYNC; \
|
||||
R0 = [P0]; \
|
||||
CC = BITTST(R0, EVT_IVHW_P); \
|
||||
IF CC JUMP 1f; \
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
#ifndef __ASM_BFIN_FTRACE_H__
|
||||
#define __ASM_BFIN_FTRACE_H__
|
||||
|
||||
#define MCOUNT_INSN_SIZE 8 /* sizeof mcount call: LINK + CALL */
|
||||
#define MCOUNT_INSN_SIZE 6 /* sizeof "[++sp] = rets; call __mcount;" */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -145,10 +145,6 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs);
|
|||
|
||||
int __ipipe_get_irq_priority(unsigned irq);
|
||||
|
||||
void __ipipe_stall_root_raw(void);
|
||||
|
||||
void __ipipe_unstall_root_raw(void);
|
||||
|
||||
void __ipipe_serial_debug(const char *fmt, ...);
|
||||
|
||||
asmlinkage void __ipipe_call_irqtail(unsigned long addr);
|
||||
|
@ -234,9 +230,6 @@ int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
|
|||
#define task_hijacked(p) 0
|
||||
#define ipipe_trap_notify(t, r) 0
|
||||
|
||||
#define __ipipe_stall_root_raw() do { } while (0)
|
||||
#define __ipipe_unstall_root_raw() do { } while (0)
|
||||
|
||||
#define ipipe_init_irq_threads() do { } while (0)
|
||||
#define ipipe_start_irq_thread(irq, desc) 0
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ asmlinkage void evt_evt10(void);
|
|||
asmlinkage void evt_evt11(void);
|
||||
asmlinkage void evt_evt12(void);
|
||||
asmlinkage void evt_evt13(void);
|
||||
asmlinkage void evt_evt14(void);
|
||||
asmlinkage void evt_soft_int1(void);
|
||||
asmlinkage void evt_system_call(void);
|
||||
asmlinkage void init_exception_buff(void);
|
||||
|
|
|
@ -127,17 +127,17 @@ static inline void protect_page(struct mm_struct *mm, unsigned long addr,
|
|||
unsigned long idx = page >> 5;
|
||||
unsigned long bit = 1 << (page & 31);
|
||||
|
||||
if (flags & VM_MAYREAD)
|
||||
if (flags & VM_READ)
|
||||
mask[idx] |= bit;
|
||||
else
|
||||
mask[idx] &= ~bit;
|
||||
mask += page_mask_nelts;
|
||||
if (flags & VM_MAYWRITE)
|
||||
if (flags & VM_WRITE)
|
||||
mask[idx] |= bit;
|
||||
else
|
||||
mask[idx] &= ~bit;
|
||||
mask += page_mask_nelts;
|
||||
if (flags & VM_MAYEXEC)
|
||||
if (flags & VM_EXEC)
|
||||
mask[idx] |= bit;
|
||||
else
|
||||
mask[idx] &= ~bit;
|
||||
|
|
|
@ -50,6 +50,7 @@ struct blackfin_pda { /* Per-processor Data Area */
|
|||
unsigned long ex_optr;
|
||||
unsigned long ex_buf[4];
|
||||
unsigned long ex_imask; /* Saved imask from exception */
|
||||
unsigned long ex_ipend; /* Saved IPEND from exception */
|
||||
unsigned long *ex_stack; /* Exception stack space */
|
||||
|
||||
#ifdef ANOMALY_05000261
|
||||
|
@ -60,6 +61,12 @@ struct blackfin_pda { /* Per-processor Data Area */
|
|||
unsigned long retx;
|
||||
unsigned long seqstat;
|
||||
unsigned int __nmi_count; /* number of times NMI asserted on this CPU */
|
||||
#ifdef CONFIG_DEBUG_DOUBLEFAULT
|
||||
unsigned long dcplb_doublefault_addr;
|
||||
unsigned long icplb_doublefault_addr;
|
||||
unsigned long retx_doublefault;
|
||||
unsigned long seqstat_doublefault;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct blackfin_pda cpu_pda[];
|
||||
|
|
|
@ -26,6 +26,7 @@ obj-$(CONFIG_MODULES) += module.o
|
|||
obj-$(CONFIG_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += shadow_console.o
|
||||
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||
|
||||
# the kgdb test puts code into L2 and without linker
|
||||
|
|
|
@ -145,6 +145,7 @@ int main(void)
|
|||
DEFINE(PDA_EXBUF, offsetof(struct blackfin_pda, ex_buf));
|
||||
DEFINE(PDA_EXIMASK, offsetof(struct blackfin_pda, ex_imask));
|
||||
DEFINE(PDA_EXSTACK, offsetof(struct blackfin_pda, ex_stack));
|
||||
DEFINE(PDA_EXIPEND, offsetof(struct blackfin_pda, ex_ipend));
|
||||
#ifdef ANOMALY_05000261
|
||||
DEFINE(PDA_LFRETX, offsetof(struct blackfin_pda, last_cplb_fault_retx));
|
||||
#endif
|
||||
|
@ -152,6 +153,12 @@ int main(void)
|
|||
DEFINE(PDA_ICPLB, offsetof(struct blackfin_pda, icplb_fault_addr));
|
||||
DEFINE(PDA_RETX, offsetof(struct blackfin_pda, retx));
|
||||
DEFINE(PDA_SEQSTAT, offsetof(struct blackfin_pda, seqstat));
|
||||
#ifdef CONFIG_DEBUG_DOUBLEFAULT
|
||||
DEFINE(PDA_DF_DCPLB, offsetof(struct blackfin_pda, dcplb_doublefault_addr));
|
||||
DEFINE(PDA_DF_ICPLB, offsetof(struct blackfin_pda, icplb_doublefault_addr));
|
||||
DEFINE(PDA_DF_SEQSTAT, offsetof(struct blackfin_pda, seqstat_doublefault));
|
||||
DEFINE(PDA_DF_RETX, offsetof(struct blackfin_pda, retx_doublefault));
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
/* Inter-core lock (in L2 SRAM) */
|
||||
DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot));
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <asm/cacheflush.h>
|
||||
#include <asm/dma.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/early_printk.h>
|
||||
|
||||
/*
|
||||
* To make sure we work around 05000119 - we always check DMA_DONE bit,
|
||||
|
@ -146,8 +147,8 @@ EXPORT_SYMBOL(request_dma);
|
|||
|
||||
int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data)
|
||||
{
|
||||
BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
|
||||
&& channel < MAX_DMA_CHANNELS));
|
||||
BUG_ON(channel >= MAX_DMA_CHANNELS ||
|
||||
dma_ch[channel].chan_status == DMA_CHANNEL_FREE);
|
||||
|
||||
if (callback != NULL) {
|
||||
int ret;
|
||||
|
@ -181,8 +182,8 @@ static void clear_dma_buffer(unsigned int channel)
|
|||
void free_dma(unsigned int channel)
|
||||
{
|
||||
pr_debug("freedma() : BEGIN \n");
|
||||
BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
|
||||
&& channel < MAX_DMA_CHANNELS));
|
||||
BUG_ON(channel >= MAX_DMA_CHANNELS ||
|
||||
dma_ch[channel].chan_status == DMA_CHANNEL_FREE);
|
||||
|
||||
/* Halt the DMA */
|
||||
disable_dma(channel);
|
||||
|
@ -236,6 +237,7 @@ void blackfin_dma_resume(void)
|
|||
*/
|
||||
void __init blackfin_dma_early_init(void)
|
||||
{
|
||||
early_shadow_stamp();
|
||||
bfin_write_MDMA_S0_CONFIG(0);
|
||||
bfin_write_MDMA_S1_CONFIG(0);
|
||||
}
|
||||
|
@ -246,6 +248,8 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size)
|
|||
unsigned long src = (unsigned long)psrc;
|
||||
struct dma_register *dst_ch, *src_ch;
|
||||
|
||||
early_shadow_stamp();
|
||||
|
||||
/* We assume that everything is 4 byte aligned, so include
|
||||
* a basic sanity check
|
||||
*/
|
||||
|
@ -300,6 +304,8 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size)
|
|||
|
||||
void __init early_dma_memcpy_done(void)
|
||||
{
|
||||
early_shadow_stamp();
|
||||
|
||||
while ((bfin_read_MDMA_S0_CONFIG() && !(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) ||
|
||||
(bfin_read_MDMA_S1_CONFIG() && !(bfin_read_MDMA_D1_IRQ_STATUS() & DMA_DONE)))
|
||||
continue;
|
||||
|
|
|
@ -722,7 +722,6 @@ void bfin_gpio_pm_hibernate_suspend(void)
|
|||
gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
|
||||
gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
|
||||
gpio_bank_saved[bank].data = gpio_array[bank]->data;
|
||||
gpio_bank_saved[bank].data = gpio_array[bank]->data;
|
||||
gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
|
||||
gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# arch/blackfin/kernel/cplb-nompu/Makefile
|
||||
#
|
||||
|
||||
obj-y := cplbinit.o cacheinit.o cplbmgr.o
|
||||
obj-y := cplbinit.o cplbmgr.o
|
||||
|
||||
CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \
|
||||
-ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2007 Analog Devices Inc.
|
||||
*
|
||||
* 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, see the file COPYING, or write
|
||||
* to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/blackfin.h>
|
||||
#include <asm/cplb.h>
|
||||
#include <asm/cplbinit.h>
|
||||
|
||||
#if defined(CONFIG_BFIN_ICACHE)
|
||||
void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl)
|
||||
{
|
||||
unsigned long ctrl;
|
||||
int i;
|
||||
|
||||
SSYNC();
|
||||
for (i = 0; i < MAX_CPLBS; i++) {
|
||||
bfin_write32(ICPLB_ADDR0 + i * 4, icplb_tbl[i].addr);
|
||||
bfin_write32(ICPLB_DATA0 + i * 4, icplb_tbl[i].data);
|
||||
}
|
||||
ctrl = bfin_read_IMEM_CONTROL();
|
||||
ctrl |= IMC | ENICPLB;
|
||||
bfin_write_IMEM_CONTROL(ctrl);
|
||||
SSYNC();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BFIN_DCACHE)
|
||||
void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl)
|
||||
{
|
||||
unsigned long ctrl;
|
||||
int i;
|
||||
|
||||
SSYNC();
|
||||
for (i = 0; i < MAX_CPLBS; i++) {
|
||||
bfin_write32(DCPLB_ADDR0 + i * 4, dcplb_tbl[i].addr);
|
||||
bfin_write32(DCPLB_DATA0 + i * 4, dcplb_tbl[i].data);
|
||||
}
|
||||
|
||||
ctrl = bfin_read_DMEM_CONTROL();
|
||||
|
||||
/*
|
||||
* Anomaly notes:
|
||||
* 05000287 - We implement workaround #2 - Change the DMEM_CONTROL
|
||||
* register, so that the port preferences for DAG0 and DAG1 are set
|
||||
* to port B
|
||||
*/
|
||||
ctrl |= DMEM_CNTR | PORT_PREF0 | (ANOMALY_05000287 ? PORT_PREF1 : 0);
|
||||
bfin_write_DMEM_CONTROL(ctrl);
|
||||
SSYNC();
|
||||
}
|
||||
#endif
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <asm/blackfin.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cplb.h>
|
||||
#include <asm/cplbinit.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
||||
|
@ -41,46 +42,6 @@ int nr_dcplb_miss[NR_CPUS], nr_icplb_miss[NR_CPUS];
|
|||
int nr_icplb_supv_miss[NR_CPUS], nr_dcplb_prot[NR_CPUS];
|
||||
int nr_cplb_flush[NR_CPUS];
|
||||
|
||||
static inline void disable_dcplb(void)
|
||||
{
|
||||
unsigned long ctrl;
|
||||
SSYNC();
|
||||
ctrl = bfin_read_DMEM_CONTROL();
|
||||
ctrl &= ~ENDCPLB;
|
||||
bfin_write_DMEM_CONTROL(ctrl);
|
||||
SSYNC();
|
||||
}
|
||||
|
||||
static inline void enable_dcplb(void)
|
||||
{
|
||||
unsigned long ctrl;
|
||||
SSYNC();
|
||||
ctrl = bfin_read_DMEM_CONTROL();
|
||||
ctrl |= ENDCPLB;
|
||||
bfin_write_DMEM_CONTROL(ctrl);
|
||||
SSYNC();
|
||||
}
|
||||
|
||||
static inline void disable_icplb(void)
|
||||
{
|
||||
unsigned long ctrl;
|
||||
SSYNC();
|
||||
ctrl = bfin_read_IMEM_CONTROL();
|
||||
ctrl &= ~ENICPLB;
|
||||
bfin_write_IMEM_CONTROL(ctrl);
|
||||
SSYNC();
|
||||
}
|
||||
|
||||
static inline void enable_icplb(void)
|
||||
{
|
||||
unsigned long ctrl;
|
||||
SSYNC();
|
||||
ctrl = bfin_read_IMEM_CONTROL();
|
||||
ctrl |= ENICPLB;
|
||||
bfin_write_IMEM_CONTROL(ctrl);
|
||||
SSYNC();
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the contents of the status register, return the index of the
|
||||
* CPLB that caused the fault.
|
||||
|
@ -198,10 +159,10 @@ static noinline int dcplb_miss(unsigned int cpu)
|
|||
dcplb_tbl[cpu][idx].addr = addr;
|
||||
dcplb_tbl[cpu][idx].data = d_data;
|
||||
|
||||
disable_dcplb();
|
||||
_disable_dcplb();
|
||||
bfin_write32(DCPLB_DATA0 + idx * 4, d_data);
|
||||
bfin_write32(DCPLB_ADDR0 + idx * 4, addr);
|
||||
enable_dcplb();
|
||||
_enable_dcplb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -288,10 +249,10 @@ static noinline int icplb_miss(unsigned int cpu)
|
|||
icplb_tbl[cpu][idx].addr = addr;
|
||||
icplb_tbl[cpu][idx].data = i_data;
|
||||
|
||||
disable_icplb();
|
||||
_disable_icplb();
|
||||
bfin_write32(ICPLB_DATA0 + idx * 4, i_data);
|
||||
bfin_write32(ICPLB_ADDR0 + idx * 4, addr);
|
||||
enable_icplb();
|
||||
_enable_icplb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -319,7 +280,7 @@ static noinline int dcplb_protection_fault(unsigned int cpu)
|
|||
int cplb_hdr(int seqstat, struct pt_regs *regs)
|
||||
{
|
||||
int cause = seqstat & 0x3f;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
unsigned int cpu = raw_smp_processor_id();
|
||||
switch (cause) {
|
||||
case 0x23:
|
||||
return dcplb_protection_fault(cpu);
|
||||
|
@ -340,19 +301,19 @@ void flush_switched_cplbs(unsigned int cpu)
|
|||
nr_cplb_flush[cpu]++;
|
||||
|
||||
local_irq_save_hw(flags);
|
||||
disable_icplb();
|
||||
_disable_icplb();
|
||||
for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
|
||||
icplb_tbl[cpu][i].data = 0;
|
||||
bfin_write32(ICPLB_DATA0 + i * 4, 0);
|
||||
}
|
||||
enable_icplb();
|
||||
_enable_icplb();
|
||||
|
||||
disable_dcplb();
|
||||
_disable_dcplb();
|
||||
for (i = first_switched_dcplb; i < MAX_CPLBS; i++) {
|
||||
dcplb_tbl[cpu][i].data = 0;
|
||||
bfin_write32(DCPLB_DATA0 + i * 4, 0);
|
||||
}
|
||||
enable_dcplb();
|
||||
_enable_dcplb();
|
||||
local_irq_restore_hw(flags);
|
||||
|
||||
}
|
||||
|
@ -385,7 +346,7 @@ void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
|
|||
#endif
|
||||
}
|
||||
|
||||
disable_dcplb();
|
||||
_disable_dcplb();
|
||||
for (i = first_mask_dcplb; i < first_switched_dcplb; i++) {
|
||||
dcplb_tbl[cpu][i].addr = addr;
|
||||
dcplb_tbl[cpu][i].data = d_data;
|
||||
|
@ -393,6 +354,6 @@ void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
|
|||
bfin_write32(DCPLB_ADDR0 + i * 4, addr);
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
enable_dcplb();
|
||||
_enable_dcplb();
|
||||
local_irq_restore_hw(flags);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# arch/blackfin/kernel/cplb-nompu/Makefile
|
||||
#
|
||||
|
||||
obj-y := cplbinit.o cacheinit.o cplbmgr.o
|
||||
obj-y := cplbinit.o cplbmgr.o
|
||||
|
||||
CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \
|
||||
-ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004-2007 Analog Devices Inc.
|
||||
*
|
||||
* 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, see the file COPYING, or write
|
||||
* to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/blackfin.h>
|
||||
#include <asm/cplb.h>
|
||||
#include <asm/cplbinit.h>
|
||||
|
||||
#if defined(CONFIG_BFIN_ICACHE)
|
||||
void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl)
|
||||
{
|
||||
unsigned long ctrl;
|
||||
int i;
|
||||
|
||||
SSYNC();
|
||||
for (i = 0; i < MAX_CPLBS; i++) {
|
||||
bfin_write32(ICPLB_ADDR0 + i * 4, icplb_tbl[i].addr);
|
||||
bfin_write32(ICPLB_DATA0 + i * 4, icplb_tbl[i].data);
|
||||
}
|
||||
ctrl = bfin_read_IMEM_CONTROL();
|
||||
ctrl |= IMC | ENICPLB;
|
||||
bfin_write_IMEM_CONTROL(ctrl);
|
||||
SSYNC();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BFIN_DCACHE)
|
||||
void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl)
|
||||
{
|
||||
unsigned long ctrl;
|
||||
int i;
|
||||
|
||||
SSYNC();
|
||||
for (i = 0; i < MAX_CPLBS; i++) {
|
||||
bfin_write32(DCPLB_ADDR0 + i * 4, dcplb_tbl[i].addr);
|
||||
bfin_write32(DCPLB_DATA0 + i * 4, dcplb_tbl[i].data);
|
||||
}
|
||||
|
||||
ctrl = bfin_read_DMEM_CONTROL();
|
||||
|
||||
/*
|
||||
* Anomaly notes:
|
||||
* 05000287 - We implement workaround #2 - Change the DMEM_CONTROL
|
||||
* register, so that the port preferences for DAG0 and DAG1 are set
|
||||
* to port B
|
||||
*/
|
||||
ctrl |= DMEM_CNTR | PORT_PREF0 | (ANOMALY_05000287 ? PORT_PREF1 : 0);
|
||||
bfin_write_DMEM_CONTROL(ctrl);
|
||||
SSYNC();
|
||||
}
|
||||
#endif
|
|
@ -36,7 +36,7 @@ int first_switched_icplb PDT_ATTR;
|
|||
int first_switched_dcplb PDT_ATTR;
|
||||
|
||||
struct cplb_boundary dcplb_bounds[9] PDT_ATTR;
|
||||
struct cplb_boundary icplb_bounds[7] PDT_ATTR;
|
||||
struct cplb_boundary icplb_bounds[9] PDT_ATTR;
|
||||
|
||||
int icplb_nr_bounds PDT_ATTR;
|
||||
int dcplb_nr_bounds PDT_ATTR;
|
||||
|
@ -167,14 +167,21 @@ void __init generate_cplb_tables_all(void)
|
|||
icplb_bounds[i_i++].data = (reserved_mem_icache_on ?
|
||||
SDRAM_IGENERIC : SDRAM_INON_CHBL);
|
||||
}
|
||||
/* Addressing hole up to the async bank. */
|
||||
icplb_bounds[i_i].eaddr = ASYNC_BANK0_BASE;
|
||||
icplb_bounds[i_i++].data = 0;
|
||||
/* ASYNC banks. */
|
||||
icplb_bounds[i_i].eaddr = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE;
|
||||
icplb_bounds[i_i++].data = SDRAM_EBIU;
|
||||
/* Addressing hole up to BootROM. */
|
||||
icplb_bounds[i_i].eaddr = BOOT_ROM_START;
|
||||
icplb_bounds[i_i++].data = 0;
|
||||
/* BootROM -- largest one should be less than 1 meg. */
|
||||
icplb_bounds[i_i].eaddr = BOOT_ROM_START + (1 * 1024 * 1024);
|
||||
icplb_bounds[i_i++].data = SDRAM_IGENERIC;
|
||||
|
||||
if (L2_LENGTH) {
|
||||
/* Addressing hole up to L2 SRAM, including the async bank. */
|
||||
/* Addressing hole up to L2 SRAM. */
|
||||
icplb_bounds[i_i].eaddr = L2_START;
|
||||
icplb_bounds[i_i++].data = 0;
|
||||
/* L2 SRAM. */
|
||||
|
|
|
@ -48,36 +48,13 @@ int nr_cplb_flush[NR_CPUS], nr_dcplb_prot[NR_CPUS];
|
|||
#define MGR_ATTR
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We're in an exception handler. The normal cli nop nop workaround
|
||||
* isn't going to do very much, as the only thing that can interrupt
|
||||
* us is an NMI, and the cli isn't going to stop that.
|
||||
*/
|
||||
#define NOWA_SSYNC __asm__ __volatile__ ("ssync;")
|
||||
|
||||
/* Anomaly handlers provide SSYNCs, so avoid extra if anomaly is present */
|
||||
#if ANOMALY_05000125
|
||||
|
||||
#define bfin_write_DMEM_CONTROL_SSYNC(v) bfin_write_DMEM_CONTROL(v)
|
||||
#define bfin_write_IMEM_CONTROL_SSYNC(v) bfin_write_IMEM_CONTROL(v)
|
||||
|
||||
#else
|
||||
|
||||
#define bfin_write_DMEM_CONTROL_SSYNC(v) \
|
||||
do { NOWA_SSYNC; bfin_write_DMEM_CONTROL(v); NOWA_SSYNC; } while (0)
|
||||
#define bfin_write_IMEM_CONTROL_SSYNC(v) \
|
||||
do { NOWA_SSYNC; bfin_write_IMEM_CONTROL(v); NOWA_SSYNC; } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
static inline void write_dcplb_data(int cpu, int idx, unsigned long data,
|
||||
unsigned long addr)
|
||||
{
|
||||
unsigned long ctrl = bfin_read_DMEM_CONTROL();
|
||||
bfin_write_DMEM_CONTROL_SSYNC(ctrl & ~ENDCPLB);
|
||||
_disable_dcplb();
|
||||
bfin_write32(DCPLB_DATA0 + idx * 4, data);
|
||||
bfin_write32(DCPLB_ADDR0 + idx * 4, addr);
|
||||
bfin_write_DMEM_CONTROL_SSYNC(ctrl);
|
||||
_enable_dcplb();
|
||||
|
||||
#ifdef CONFIG_CPLB_INFO
|
||||
dcplb_tbl[cpu][idx].addr = addr;
|
||||
|
@ -88,12 +65,10 @@ static inline void write_dcplb_data(int cpu, int idx, unsigned long data,
|
|||
static inline void write_icplb_data(int cpu, int idx, unsigned long data,
|
||||
unsigned long addr)
|
||||
{
|
||||
unsigned long ctrl = bfin_read_IMEM_CONTROL();
|
||||
|
||||
bfin_write_IMEM_CONTROL_SSYNC(ctrl & ~ENICPLB);
|
||||
_disable_icplb();
|
||||
bfin_write32(ICPLB_DATA0 + idx * 4, data);
|
||||
bfin_write32(ICPLB_ADDR0 + idx * 4, addr);
|
||||
bfin_write_IMEM_CONTROL_SSYNC(ctrl);
|
||||
_enable_icplb();
|
||||
|
||||
#ifdef CONFIG_CPLB_INFO
|
||||
icplb_tbl[cpu][idx].addr = addr;
|
||||
|
@ -227,7 +202,7 @@ MGR_ATTR static int dcplb_miss(int cpu)
|
|||
MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs)
|
||||
{
|
||||
int cause = seqstat & 0x3f;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
unsigned int cpu = raw_smp_processor_id();
|
||||
switch (cause) {
|
||||
case VEC_CPLB_I_M:
|
||||
return icplb_miss(cpu);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/serial_core.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <asm/blackfin.h>
|
||||
#include <asm/irq_handler.h>
|
||||
#include <asm/early_printk.h>
|
||||
|
@ -181,6 +182,22 @@ asmlinkage void __init init_early_exception_vectors(void)
|
|||
u32 evt;
|
||||
SSYNC();
|
||||
|
||||
/*
|
||||
* This starts up the shadow buffer, incase anything crashes before
|
||||
* setup arch
|
||||
*/
|
||||
mark_shadow_error();
|
||||
early_shadow_puts(linux_banner);
|
||||
early_shadow_stamp();
|
||||
|
||||
if (CPUID != bfin_cpuid()) {
|
||||
early_shadow_puts("Running on wrong machine type, expected");
|
||||
early_shadow_reg(CPUID, 16);
|
||||
early_shadow_puts(", but running on");
|
||||
early_shadow_reg(bfin_cpuid(), 16);
|
||||
early_shadow_puts("\n");
|
||||
}
|
||||
|
||||
/* cannot program in software:
|
||||
* evt0 - emulation (jtag)
|
||||
* evt1 - reset
|
||||
|
@ -199,6 +216,7 @@ asmlinkage void __init init_early_exception_vectors(void)
|
|||
|
||||
}
|
||||
|
||||
__attribute__((__noreturn__))
|
||||
asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)
|
||||
{
|
||||
/* This can happen before the uart is initialized, so initialize
|
||||
|
@ -210,10 +228,58 @@ asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)
|
|||
if (likely(early_console == NULL) && CPUID == bfin_cpuid())
|
||||
setup_early_printk(DEFAULT_EARLY_PORT);
|
||||
|
||||
printk(KERN_EMERG "Early panic\n");
|
||||
dump_bfin_mem(fp);
|
||||
show_regs(fp);
|
||||
dump_bfin_trace_buffer();
|
||||
if (!shadow_console_enabled()) {
|
||||
/* crap - we crashed before setup_arch() */
|
||||
early_shadow_puts("panic before setup_arch\n");
|
||||
early_shadow_puts("IPEND:");
|
||||
early_shadow_reg(fp->ipend, 16);
|
||||
if (fp->seqstat & SEQSTAT_EXCAUSE) {
|
||||
early_shadow_puts("\nEXCAUSE:");
|
||||
early_shadow_reg(fp->seqstat & SEQSTAT_EXCAUSE, 8);
|
||||
}
|
||||
if (fp->seqstat & SEQSTAT_HWERRCAUSE) {
|
||||
early_shadow_puts("\nHWERRCAUSE:");
|
||||
early_shadow_reg(
|
||||
(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14, 8);
|
||||
}
|
||||
early_shadow_puts("\nErr @");
|
||||
if (fp->ipend & EVT_EVX)
|
||||
early_shadow_reg(fp->retx, 32);
|
||||
else
|
||||
early_shadow_reg(fp->pc, 32);
|
||||
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
|
||||
early_shadow_puts("\nTrace:");
|
||||
if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
|
||||
while (bfin_read_TBUFSTAT() & TBUFCNT) {
|
||||
early_shadow_puts("\nT :");
|
||||
early_shadow_reg(bfin_read_TBUF(), 32);
|
||||
early_shadow_puts("\n S :");
|
||||
early_shadow_reg(bfin_read_TBUF(), 32);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
early_shadow_puts("\nUse bfin-elf-addr2line to determine "
|
||||
"function names\n");
|
||||
/*
|
||||
* We should panic(), but we can't - since panic calls printk,
|
||||
* and printk uses memcpy.
|
||||
* we want to reboot, but if the machine type is different,
|
||||
* can't due to machine specific reboot sequences
|
||||
*/
|
||||
if (CPUID == bfin_cpuid()) {
|
||||
early_shadow_puts("Trying to restart\n");
|
||||
machine_restart("");
|
||||
}
|
||||
|
||||
early_shadow_puts("Halting, since it is not safe to restart\n");
|
||||
while (1)
|
||||
asm volatile ("EMUEXCPT; IDLE;\n");
|
||||
|
||||
} else {
|
||||
printk(KERN_EMERG "Early panic\n");
|
||||
show_regs(fp);
|
||||
dump_bfin_trace_buffer();
|
||||
}
|
||||
|
||||
panic("Died early");
|
||||
}
|
||||
|
|
|
@ -43,8 +43,28 @@
|
|||
|
||||
ENTRY(_ret_from_fork)
|
||||
#ifdef CONFIG_IPIPE
|
||||
[--sp] = reti; /* IRQs on. */
|
||||
SP += 4;
|
||||
/*
|
||||
* Hw IRQs are off on entry, and we don't want the scheduling tail
|
||||
* code to starve high priority domains from interrupts while it
|
||||
* runs. Therefore we first stall the root stage to have the
|
||||
* virtual interrupt state reflect IMASK.
|
||||
*/
|
||||
p0.l = ___ipipe_root_status;
|
||||
p0.h = ___ipipe_root_status;
|
||||
r4 = [p0];
|
||||
bitset(r4, 0);
|
||||
[p0] = r4;
|
||||
/*
|
||||
* Then we may enable hw IRQs, allowing preemption from high
|
||||
* priority domains. schedule_tail() will do local_irq_enable()
|
||||
* since Blackfin does not define __ARCH_WANT_UNLOCKED_CTXSW, so
|
||||
* there is no need to unstall the root domain by ourselves
|
||||
* afterwards.
|
||||
*/
|
||||
p0.l = _bfin_irq_flags;
|
||||
p0.h = _bfin_irq_flags;
|
||||
r4 = [p0];
|
||||
sti r4;
|
||||
#endif /* CONFIG_IPIPE */
|
||||
SP += -12;
|
||||
call _schedule_tail;
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
* only one we can blow away. With pointer registers, we have P0-P2.
|
||||
*
|
||||
* Upon entry, the RETS will point to the top of the current profiled
|
||||
* function. And since GCC setup the frame for us, the previous function
|
||||
* will be waiting there. mmmm pie.
|
||||
* function. And since GCC pushed the previous RETS for us, the previous
|
||||
* function will be waiting there. mmmm pie.
|
||||
*/
|
||||
ENTRY(__mcount)
|
||||
/* save third function arg early so we can do testing below */
|
||||
|
@ -70,14 +70,14 @@ ENTRY(__mcount)
|
|||
/* setup the tracer function */
|
||||
p0 = r3;
|
||||
|
||||
/* tracer(ulong frompc, ulong selfpc):
|
||||
* frompc: the pc that did the call to ...
|
||||
* selfpc: ... this location
|
||||
* the selfpc itself will need adjusting for the mcount call
|
||||
/* function_trace_call(unsigned long ip, unsigned long parent_ip):
|
||||
* ip: this point was called by ...
|
||||
* parent_ip: ... this function
|
||||
* the ip itself will need adjusting for the mcount call
|
||||
*/
|
||||
r1 = rets;
|
||||
r0 = [fp + 4];
|
||||
r1 += -MCOUNT_INSN_SIZE;
|
||||
r0 = rets;
|
||||
r1 = [sp + 16]; /* skip the 4 local regs on stack */
|
||||
r0 += -MCOUNT_INSN_SIZE;
|
||||
|
||||
/* call the tracer */
|
||||
call (p0);
|
||||
|
@ -106,9 +106,10 @@ ENTRY(_ftrace_graph_caller)
|
|||
[--sp] = r1;
|
||||
[--sp] = rets;
|
||||
|
||||
r0 = fp;
|
||||
/* prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) */
|
||||
r0 = sp;
|
||||
r1 = rets;
|
||||
r0 += 4;
|
||||
r0 += 16; /* skip the 4 local regs on stack */
|
||||
r1 += -MCOUNT_INSN_SIZE;
|
||||
call _prepare_ftrace_return;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
|
|||
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
||||
return;
|
||||
|
||||
if (ftrace_push_return_trace(*parent, self_addr, &trace.depth) == -EBUSY)
|
||||
if (ftrace_push_return_trace(*parent, self_addr, &trace.depth, 0) == -EBUSY)
|
||||
return;
|
||||
|
||||
trace.func = self_addr;
|
||||
|
|
|
@ -30,10 +30,10 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
|
||||
|
||||
|
@ -90,6 +90,7 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
|
|||
struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr();
|
||||
struct ipipe_domain *this_domain, *next_domain;
|
||||
struct list_head *head, *pos;
|
||||
struct ipipe_irqdesc *idesc;
|
||||
int m_ack, s = -1;
|
||||
|
||||
/*
|
||||
|
@ -100,17 +101,20 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
|
|||
*/
|
||||
m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR);
|
||||
this_domain = __ipipe_current_domain;
|
||||
idesc = &this_domain->irqs[irq];
|
||||
|
||||
if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control)))
|
||||
if (unlikely(test_bit(IPIPE_STICKY_FLAG, &idesc->control)))
|
||||
head = &this_domain->p_link;
|
||||
else {
|
||||
head = __ipipe_pipeline.next;
|
||||
next_domain = list_entry(head, struct ipipe_domain, p_link);
|
||||
if (likely(test_bit(IPIPE_WIRED_FLAG, &next_domain->irqs[irq].control))) {
|
||||
if (!m_ack && next_domain->irqs[irq].acknowledge != NULL)
|
||||
next_domain->irqs[irq].acknowledge(irq, irq_to_desc(irq));
|
||||
idesc = &next_domain->irqs[irq];
|
||||
if (likely(test_bit(IPIPE_WIRED_FLAG, &idesc->control))) {
|
||||
if (!m_ack && idesc->acknowledge != NULL)
|
||||
idesc->acknowledge(irq, irq_to_desc(irq));
|
||||
if (test_bit(IPIPE_SYNCDEFER_FLAG, &p->status))
|
||||
s = __test_and_set_bit(IPIPE_STALL_FLAG, &p->status);
|
||||
s = __test_and_set_bit(IPIPE_STALL_FLAG,
|
||||
&p->status);
|
||||
__ipipe_dispatch_wired(next_domain, irq);
|
||||
goto out;
|
||||
}
|
||||
|
@ -121,14 +125,15 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
|
|||
pos = head;
|
||||
while (pos != &__ipipe_pipeline) {
|
||||
next_domain = list_entry(pos, struct ipipe_domain, p_link);
|
||||
if (test_bit(IPIPE_HANDLE_FLAG, &next_domain->irqs[irq].control)) {
|
||||
idesc = &next_domain->irqs[irq];
|
||||
if (test_bit(IPIPE_HANDLE_FLAG, &idesc->control)) {
|
||||
__ipipe_set_irq_pending(next_domain, irq);
|
||||
if (!m_ack && next_domain->irqs[irq].acknowledge != NULL) {
|
||||
next_domain->irqs[irq].acknowledge(irq, irq_to_desc(irq));
|
||||
if (!m_ack && idesc->acknowledge != NULL) {
|
||||
idesc->acknowledge(irq, irq_to_desc(irq));
|
||||
m_ack = 1;
|
||||
}
|
||||
}
|
||||
if (!test_bit(IPIPE_PASS_FLAG, &next_domain->irqs[irq].control))
|
||||
if (!test_bit(IPIPE_PASS_FLAG, &idesc->control))
|
||||
break;
|
||||
pos = next_domain->p_link.next;
|
||||
}
|
||||
|
@ -159,11 +164,6 @@ out:
|
|||
__clear_bit(IPIPE_STALL_FLAG, &p->status);
|
||||
}
|
||||
|
||||
int __ipipe_check_root(void)
|
||||
{
|
||||
return ipipe_root_domain_p;
|
||||
}
|
||||
|
||||
void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
|
@ -186,30 +186,6 @@ void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
|
|||
}
|
||||
EXPORT_SYMBOL(__ipipe_disable_irqdesc);
|
||||
|
||||
void __ipipe_stall_root_raw(void)
|
||||
{
|
||||
/*
|
||||
* This code is called by the ins{bwl} routines (see
|
||||
* arch/blackfin/lib/ins.S), which are heavily used by the
|
||||
* network stack. It masks all interrupts but those handled by
|
||||
* non-root domains, so that we keep decent network transfer
|
||||
* rates for Linux without inducing pathological jitter for
|
||||
* the real-time domain.
|
||||
*/
|
||||
__asm__ __volatile__ ("sti %0;" : : "d"(__ipipe_irq_lvmask));
|
||||
|
||||
__set_bit(IPIPE_STALL_FLAG,
|
||||
&ipipe_root_cpudom_var(status));
|
||||
}
|
||||
|
||||
void __ipipe_unstall_root_raw(void)
|
||||
{
|
||||
__clear_bit(IPIPE_STALL_FLAG,
|
||||
&ipipe_root_cpudom_var(status));
|
||||
|
||||
__asm__ __volatile__ ("sti %0;" : : "d"(bfin_irq_flags));
|
||||
}
|
||||
|
||||
int __ipipe_syscall_root(struct pt_regs *regs)
|
||||
{
|
||||
struct ipipe_percpu_domain_data *p;
|
||||
|
@ -333,12 +309,29 @@ asmlinkage void __ipipe_sync_root(void)
|
|||
|
||||
void ___ipipe_sync_pipeline(unsigned long syncmask)
|
||||
{
|
||||
if (__ipipe_root_domain_p) {
|
||||
if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
|
||||
return;
|
||||
}
|
||||
if (__ipipe_root_domain_p &&
|
||||
test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
|
||||
return;
|
||||
|
||||
__ipipe_sync_stage(syncmask);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(show_stack);
|
||||
void __ipipe_disable_root_irqs_hw(void)
|
||||
{
|
||||
/*
|
||||
* This code is called by the ins{bwl} routines (see
|
||||
* arch/blackfin/lib/ins.S), which are heavily used by the
|
||||
* network stack. It masks all interrupts but those handled by
|
||||
* non-root domains, so that we keep decent network transfer
|
||||
* rates for Linux without inducing pathological jitter for
|
||||
* the real-time domain.
|
||||
*/
|
||||
bfin_sti(__ipipe_irq_lvmask);
|
||||
__set_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status));
|
||||
}
|
||||
|
||||
void __ipipe_enable_root_irqs_hw(void)
|
||||
{
|
||||
__clear_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status));
|
||||
bfin_sti(bfin_irq_flags);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ void kgdb_l2_test(void)
|
|||
|
||||
int kgdb_test(char *name, int len, int count, int z)
|
||||
{
|
||||
printk(KERN_DEBUG "kgdb name(%d): %s, %d, %d\n", len, name, count, z);
|
||||
printk(KERN_ALERT "kgdb name(%d): %s, %d, %d\n", len, name, count, z);
|
||||
count = z;
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "module %s: " fmt
|
||||
|
||||
#include <linux/moduleloader.h>
|
||||
#include <linux/elf.h>
|
||||
|
@ -36,6 +37,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <asm/dma.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
void *module_alloc(unsigned long size)
|
||||
{
|
||||
|
@ -52,7 +54,7 @@ void module_free(struct module *mod, void *module_region)
|
|||
|
||||
/* Transfer the section to the L1 memory */
|
||||
int
|
||||
module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
|
||||
module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
|
||||
char *secstrings, struct module *mod)
|
||||
{
|
||||
/*
|
||||
|
@ -63,126 +65,119 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
|
|||
* NOTE: this breaks the semantic of mod->arch structure.
|
||||
*/
|
||||
Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
|
||||
void *dest = NULL;
|
||||
void *dest;
|
||||
|
||||
for (s = sechdrs; s < sechdrs_end; ++s) {
|
||||
if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) ||
|
||||
((strcmp(".text", secstrings + s->sh_name) == 0) &&
|
||||
(hdr->e_flags & EF_BFIN_CODE_IN_L1) && (s->sh_size > 0))) {
|
||||
const char *shname = secstrings + s->sh_name;
|
||||
|
||||
if (s->sh_size == 0)
|
||||
continue;
|
||||
|
||||
if (!strcmp(".l1.text", shname) ||
|
||||
(!strcmp(".text", shname) &&
|
||||
(hdr->e_flags & EF_BFIN_CODE_IN_L1))) {
|
||||
|
||||
dest = l1_inst_sram_alloc(s->sh_size);
|
||||
mod->arch.text_l1 = dest;
|
||||
if (dest == NULL) {
|
||||
printk(KERN_ERR
|
||||
"module %s: L1 instruction memory allocation failed\n",
|
||||
mod->name);
|
||||
pr_err("L1 inst memory allocation failed\n",
|
||||
mod->name);
|
||||
return -1;
|
||||
}
|
||||
dma_memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
||||
s->sh_flags &= ~SHF_ALLOC;
|
||||
s->sh_addr = (unsigned long)dest;
|
||||
}
|
||||
if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) ||
|
||||
((strcmp(".data", secstrings + s->sh_name) == 0) &&
|
||||
(hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) {
|
||||
|
||||
} else if (!strcmp(".l1.data", shname) ||
|
||||
(!strcmp(".data", shname) &&
|
||||
(hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
|
||||
|
||||
dest = l1_data_sram_alloc(s->sh_size);
|
||||
mod->arch.data_a_l1 = dest;
|
||||
if (dest == NULL) {
|
||||
printk(KERN_ERR
|
||||
"module %s: L1 data memory allocation failed\n",
|
||||
pr_err("L1 data memory allocation failed\n",
|
||||
mod->name);
|
||||
return -1;
|
||||
}
|
||||
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
||||
s->sh_flags &= ~SHF_ALLOC;
|
||||
s->sh_addr = (unsigned long)dest;
|
||||
}
|
||||
if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 ||
|
||||
((strcmp(".bss", secstrings + s->sh_name) == 0) &&
|
||||
(hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) {
|
||||
dest = l1_data_sram_alloc(s->sh_size);
|
||||
|
||||
} else if (!strcmp(".l1.bss", shname) ||
|
||||
(!strcmp(".bss", shname) &&
|
||||
(hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
|
||||
|
||||
dest = l1_data_sram_zalloc(s->sh_size);
|
||||
mod->arch.bss_a_l1 = dest;
|
||||
if (dest == NULL) {
|
||||
printk(KERN_ERR
|
||||
"module %s: L1 data memory allocation failed\n",
|
||||
pr_err("L1 data memory allocation failed\n",
|
||||
mod->name);
|
||||
return -1;
|
||||
}
|
||||
memset(dest, 0, s->sh_size);
|
||||
s->sh_flags &= ~SHF_ALLOC;
|
||||
s->sh_addr = (unsigned long)dest;
|
||||
}
|
||||
if (strcmp(".l1.data.B", secstrings + s->sh_name) == 0) {
|
||||
|
||||
} else if (!strcmp(".l1.data.B", shname)) {
|
||||
|
||||
dest = l1_data_B_sram_alloc(s->sh_size);
|
||||
mod->arch.data_b_l1 = dest;
|
||||
if (dest == NULL) {
|
||||
printk(KERN_ERR
|
||||
"module %s: L1 data memory allocation failed\n",
|
||||
pr_err("L1 data memory allocation failed\n",
|
||||
mod->name);
|
||||
return -1;
|
||||
}
|
||||
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
||||
s->sh_flags &= ~SHF_ALLOC;
|
||||
s->sh_addr = (unsigned long)dest;
|
||||
}
|
||||
if (strcmp(".l1.bss.B", secstrings + s->sh_name) == 0) {
|
||||
|
||||
} else if (!strcmp(".l1.bss.B", shname)) {
|
||||
|
||||
dest = l1_data_B_sram_alloc(s->sh_size);
|
||||
mod->arch.bss_b_l1 = dest;
|
||||
if (dest == NULL) {
|
||||
printk(KERN_ERR
|
||||
"module %s: L1 data memory allocation failed\n",
|
||||
pr_err("L1 data memory allocation failed\n",
|
||||
mod->name);
|
||||
return -1;
|
||||
}
|
||||
memset(dest, 0, s->sh_size);
|
||||
s->sh_flags &= ~SHF_ALLOC;
|
||||
s->sh_addr = (unsigned long)dest;
|
||||
}
|
||||
if ((strcmp(".l2.text", secstrings + s->sh_name) == 0) ||
|
||||
((strcmp(".text", secstrings + s->sh_name) == 0) &&
|
||||
(hdr->e_flags & EF_BFIN_CODE_IN_L2) && (s->sh_size > 0))) {
|
||||
|
||||
} else if (!strcmp(".l2.text", shname) ||
|
||||
(!strcmp(".text", shname) &&
|
||||
(hdr->e_flags & EF_BFIN_CODE_IN_L2))) {
|
||||
|
||||
dest = l2_sram_alloc(s->sh_size);
|
||||
mod->arch.text_l2 = dest;
|
||||
if (dest == NULL) {
|
||||
printk(KERN_ERR
|
||||
"module %s: L2 SRAM allocation failed\n",
|
||||
mod->name);
|
||||
pr_err("L2 SRAM allocation failed\n",
|
||||
mod->name);
|
||||
return -1;
|
||||
}
|
||||
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
||||
s->sh_flags &= ~SHF_ALLOC;
|
||||
s->sh_addr = (unsigned long)dest;
|
||||
}
|
||||
if ((strcmp(".l2.data", secstrings + s->sh_name) == 0) ||
|
||||
((strcmp(".data", secstrings + s->sh_name) == 0) &&
|
||||
(hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
|
||||
|
||||
} else if (!strcmp(".l2.data", shname) ||
|
||||
(!strcmp(".data", shname) &&
|
||||
(hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
|
||||
|
||||
dest = l2_sram_alloc(s->sh_size);
|
||||
mod->arch.data_l2 = dest;
|
||||
if (dest == NULL) {
|
||||
printk(KERN_ERR
|
||||
"module %s: L2 SRAM allocation failed\n",
|
||||
pr_err("L2 SRAM allocation failed\n",
|
||||
mod->name);
|
||||
return -1;
|
||||
}
|
||||
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
||||
s->sh_flags &= ~SHF_ALLOC;
|
||||
s->sh_addr = (unsigned long)dest;
|
||||
}
|
||||
if (strcmp(".l2.bss", secstrings + s->sh_name) == 0 ||
|
||||
((strcmp(".bss", secstrings + s->sh_name) == 0) &&
|
||||
(hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
|
||||
dest = l2_sram_alloc(s->sh_size);
|
||||
|
||||
} else if (!strcmp(".l2.bss", shname) ||
|
||||
(!strcmp(".bss", shname) &&
|
||||
(hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
|
||||
|
||||
dest = l2_sram_zalloc(s->sh_size);
|
||||
mod->arch.bss_l2 = dest;
|
||||
if (dest == NULL) {
|
||||
printk(KERN_ERR
|
||||
"module %s: L2 SRAM allocation failed\n",
|
||||
pr_err("L2 SRAM allocation failed\n",
|
||||
mod->name);
|
||||
return -1;
|
||||
}
|
||||
memset(dest, 0, s->sh_size);
|
||||
s->sh_flags &= ~SHF_ALLOC;
|
||||
s->sh_addr = (unsigned long)dest;
|
||||
}
|
||||
|
||||
} else
|
||||
continue;
|
||||
|
||||
s->sh_flags &= ~SHF_ALLOC;
|
||||
s->sh_addr = (unsigned long)dest;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -190,7 +185,7 @@ int
|
|||
apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
|
||||
unsigned int symindex, unsigned int relsec, struct module *me)
|
||||
{
|
||||
printk(KERN_ERR "module %s: .rel unsupported\n", me->name);
|
||||
pr_err(".rel unsupported\n", me->name);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
|
@ -205,109 +200,86 @@ apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
|
|||
/* gas does not generate it. */
|
||||
/*************************************************************************/
|
||||
int
|
||||
apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
|
||||
apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
|
||||
unsigned int symindex, unsigned int relsec,
|
||||
struct module *mod)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned short tmp;
|
||||
Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
|
||||
Elf32_Sym *sym;
|
||||
uint32_t *location32;
|
||||
uint16_t *location16;
|
||||
uint32_t value;
|
||||
unsigned long location, value, size;
|
||||
|
||||
pr_debug("applying relocate section %u to %u\n", mod->name,
|
||||
relsec, sechdrs[relsec].sh_info);
|
||||
|
||||
pr_debug("Applying relocate section %u to %u\n", relsec,
|
||||
sechdrs[relsec].sh_info);
|
||||
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
|
||||
/* This is where to make the change */
|
||||
location16 =
|
||||
(uint16_t *) (sechdrs[sechdrs[relsec].sh_info].sh_addr +
|
||||
rel[i].r_offset);
|
||||
location32 = (uint32_t *) location16;
|
||||
location = sechdrs[sechdrs[relsec].sh_info].sh_addr +
|
||||
rel[i].r_offset;
|
||||
|
||||
/* This is the symbol it is referring to. Note that all
|
||||
undefined symbols have been resolved. */
|
||||
sym = (Elf32_Sym *) sechdrs[symindex].sh_addr
|
||||
+ ELF32_R_SYM(rel[i].r_info);
|
||||
value = sym->st_value;
|
||||
value += rel[i].r_addend;
|
||||
pr_debug("location is %x, value is %x type is %d \n",
|
||||
(unsigned int) location32, value,
|
||||
ELF32_R_TYPE(rel[i].r_info));
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if ((unsigned long)location16 >= COREB_L1_DATA_A_START) {
|
||||
printk(KERN_ERR "module %s: cannot relocate in L1: %u (SMP kernel)",
|
||||
mod->name, ELF32_R_TYPE(rel[i].r_info));
|
||||
if (location >= COREB_L1_DATA_A_START) {
|
||||
pr_err("cannot relocate in L1: %u (SMP kernel)",
|
||||
mod->name, ELF32_R_TYPE(rel[i].r_info));
|
||||
return -ENOEXEC;
|
||||
}
|
||||
#endif
|
||||
|
||||
pr_debug("location is %lx, value is %lx type is %d\n",
|
||||
mod->name, location, value, ELF32_R_TYPE(rel[i].r_info));
|
||||
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
|
||||
case R_BFIN_HUIMM16:
|
||||
value >>= 16;
|
||||
case R_BFIN_LUIMM16:
|
||||
case R_BFIN_RIMM16:
|
||||
size = 2;
|
||||
break;
|
||||
case R_BFIN_BYTE4_DATA:
|
||||
size = 4;
|
||||
break;
|
||||
|
||||
case R_BFIN_PCREL24:
|
||||
case R_BFIN_PCREL24_JUMP_L:
|
||||
/* Add the value, subtract its postition */
|
||||
location16 =
|
||||
(uint16_t *) (sechdrs[sechdrs[relsec].sh_info].
|
||||
sh_addr + rel[i].r_offset - 2);
|
||||
location32 = (uint32_t *) location16;
|
||||
value -= (uint32_t) location32;
|
||||
value >>= 1;
|
||||
if ((value & 0xFF000000) != 0 &&
|
||||
(value & 0xFF000000) != 0xFF000000) {
|
||||
printk(KERN_ERR "module %s: relocation overflow\n",
|
||||
mod->name);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
pr_debug("value is %x, before %x-%x after %x-%x\n", value,
|
||||
*location16, *(location16 + 1),
|
||||
(*location16 & 0xff00) | (value >> 16 & 0x00ff),
|
||||
value & 0xffff);
|
||||
*location16 =
|
||||
(*location16 & 0xff00) | (value >> 16 & 0x00ff);
|
||||
*(location16 + 1) = value & 0xffff;
|
||||
break;
|
||||
case R_BFIN_PCREL12_JUMP:
|
||||
case R_BFIN_PCREL12_JUMP_S:
|
||||
value -= (uint32_t) location32;
|
||||
value >>= 1;
|
||||
*location16 = (value & 0xfff);
|
||||
break;
|
||||
case R_BFIN_PCREL10:
|
||||
value -= (uint32_t) location32;
|
||||
value >>= 1;
|
||||
*location16 = (value & 0x3ff);
|
||||
pr_err("unsupported relocation: %u (no -mlong-calls?)\n",
|
||||
mod->name, ELF32_R_TYPE(rel[i].r_info));
|
||||
return -ENOEXEC;
|
||||
|
||||
default:
|
||||
pr_err("unknown relocation: %u\n", mod->name,
|
||||
ELF32_R_TYPE(rel[i].r_info));
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
switch (bfin_mem_access_type(location, size)) {
|
||||
case BFIN_MEM_ACCESS_CORE:
|
||||
case BFIN_MEM_ACCESS_CORE_ONLY:
|
||||
memcpy((void *)location, &value, size);
|
||||
break;
|
||||
case R_BFIN_LUIMM16:
|
||||
pr_debug("before %x after %x\n", *location16,
|
||||
(value & 0xffff));
|
||||
tmp = (value & 0xffff);
|
||||
if ((unsigned long)location16 >= L1_CODE_START) {
|
||||
dma_memcpy(location16, &tmp, 2);
|
||||
} else
|
||||
*location16 = tmp;
|
||||
case BFIN_MEM_ACCESS_DMA:
|
||||
dma_memcpy((void *)location, &value, size);
|
||||
break;
|
||||
case R_BFIN_HUIMM16:
|
||||
pr_debug("before %x after %x\n", *location16,
|
||||
((value >> 16) & 0xffff));
|
||||
tmp = ((value >> 16) & 0xffff);
|
||||
if ((unsigned long)location16 >= L1_CODE_START) {
|
||||
dma_memcpy(location16, &tmp, 2);
|
||||
} else
|
||||
*location16 = tmp;
|
||||
break;
|
||||
case R_BFIN_RIMM16:
|
||||
*location16 = (value & 0xffff);
|
||||
break;
|
||||
case R_BFIN_BYTE4_DATA:
|
||||
pr_debug("before %x after %x\n", *location32, value);
|
||||
*location32 = value;
|
||||
case BFIN_MEM_ACCESS_ITEST:
|
||||
isram_memcpy((void *)location, &value, size);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
|
||||
mod->name, ELF32_R_TYPE(rel[i].r_info));
|
||||
pr_err("invalid relocation for %#lx\n",
|
||||
mod->name, location);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -332,22 +304,28 @@ module_finalize(const Elf_Ehdr * hdr,
|
|||
for (i = 1; i < hdr->e_shnum; i++) {
|
||||
const char *strtab = (char *)sechdrs[strindex].sh_addr;
|
||||
unsigned int info = sechdrs[i].sh_info;
|
||||
const char *shname = secstrings + sechdrs[i].sh_name;
|
||||
|
||||
/* Not a valid relocation section? */
|
||||
if (info >= hdr->e_shnum)
|
||||
continue;
|
||||
|
||||
if ((sechdrs[i].sh_type == SHT_RELA) &&
|
||||
((strcmp(".rela.l2.text", secstrings + sechdrs[i].sh_name) == 0) ||
|
||||
(strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
|
||||
((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
|
||||
(hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) {
|
||||
/* Only support RELA relocation types */
|
||||
if (sechdrs[i].sh_type != SHT_RELA)
|
||||
continue;
|
||||
|
||||
if (!strcmp(".rela.l2.text", shname) ||
|
||||
!strcmp(".rela.l1.text", shname) ||
|
||||
(!strcmp(".rela.text", shname) &&
|
||||
(hdr->e_flags & (EF_BFIN_CODE_IN_L1 | EF_BFIN_CODE_IN_L2)))) {
|
||||
|
||||
err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
|
||||
symindex, i, mod);
|
||||
if (err < 0)
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -282,25 +282,19 @@ void finish_atomic_sections (struct pt_regs *regs)
|
|||
{
|
||||
int __user *up0 = (int __user *)regs->p0;
|
||||
|
||||
if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END)
|
||||
return;
|
||||
|
||||
switch (regs->pc) {
|
||||
case ATOMIC_XCHG32 + 2:
|
||||
put_user(regs->r1, up0);
|
||||
regs->pc += 2;
|
||||
regs->pc = ATOMIC_XCHG32 + 4;
|
||||
break;
|
||||
|
||||
case ATOMIC_CAS32 + 2:
|
||||
case ATOMIC_CAS32 + 4:
|
||||
if (regs->r0 == regs->r1)
|
||||
case ATOMIC_CAS32 + 6:
|
||||
put_user(regs->r2, up0);
|
||||
regs->pc = ATOMIC_CAS32 + 8;
|
||||
break;
|
||||
case ATOMIC_CAS32 + 6:
|
||||
put_user(regs->r2, up0);
|
||||
regs->pc += 2;
|
||||
break;
|
||||
|
||||
case ATOMIC_ADD32 + 2:
|
||||
regs->r0 = regs->r1 + regs->r0;
|
||||
|
|
|
@ -206,6 +206,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||
{
|
||||
int ret;
|
||||
unsigned long __user *datap = (unsigned long __user *)data;
|
||||
void *paddr = (void *)addr;
|
||||
|
||||
switch (request) {
|
||||
/* when I and D space are separate, these will need to be fixed. */
|
||||
|
@ -215,42 +216,49 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||
case PTRACE_PEEKTEXT: /* read word at location addr. */
|
||||
{
|
||||
unsigned long tmp = 0;
|
||||
int copied;
|
||||
int copied = 0, to_copy = sizeof(tmp);
|
||||
|
||||
ret = -EIO;
|
||||
pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %ld\n", addr, sizeof(data));
|
||||
if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
|
||||
pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %i\n", addr, to_copy);
|
||||
if (is_user_addr_valid(child, addr, to_copy) < 0)
|
||||
break;
|
||||
pr_debug("ptrace: user address is valid\n");
|
||||
|
||||
if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
|
||||
&& addr + sizeof(tmp) <= get_l1_code_start() + L1_CODE_LENGTH) {
|
||||
safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp));
|
||||
copied = sizeof(tmp);
|
||||
|
||||
} else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START
|
||||
&& addr + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
|
||||
memcpy(&tmp, (const void *)(addr), sizeof(tmp));
|
||||
copied = sizeof(tmp);
|
||||
|
||||
} else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START
|
||||
&& addr + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
|
||||
memcpy(&tmp, (const void *)(addr), sizeof(tmp));
|
||||
copied = sizeof(tmp);
|
||||
|
||||
} else if (addr >= FIXED_CODE_START
|
||||
&& addr + sizeof(tmp) <= FIXED_CODE_END) {
|
||||
copy_from_user_page(0, 0, 0, &tmp, (const void *)(addr), sizeof(tmp));
|
||||
copied = sizeof(tmp);
|
||||
|
||||
} else
|
||||
switch (bfin_mem_access_type(addr, to_copy)) {
|
||||
case BFIN_MEM_ACCESS_CORE:
|
||||
case BFIN_MEM_ACCESS_CORE_ONLY:
|
||||
copied = access_process_vm(child, addr, &tmp,
|
||||
sizeof(tmp), 0);
|
||||
to_copy, 0);
|
||||
if (copied)
|
||||
break;
|
||||
|
||||
/* hrm, why didn't that work ... maybe no mapping */
|
||||
if (addr >= FIXED_CODE_START &&
|
||||
addr + to_copy <= FIXED_CODE_END) {
|
||||
copy_from_user_page(0, 0, 0, &tmp, paddr, to_copy);
|
||||
copied = to_copy;
|
||||
} else if (addr >= BOOT_ROM_START) {
|
||||
memcpy(&tmp, paddr, to_copy);
|
||||
copied = to_copy;
|
||||
}
|
||||
|
||||
break;
|
||||
case BFIN_MEM_ACCESS_DMA:
|
||||
if (safe_dma_memcpy(&tmp, paddr, to_copy))
|
||||
copied = to_copy;
|
||||
break;
|
||||
case BFIN_MEM_ACCESS_ITEST:
|
||||
if (isram_memcpy(&tmp, paddr, to_copy))
|
||||
copied = to_copy;
|
||||
break;
|
||||
default:
|
||||
copied = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp);
|
||||
if (copied != sizeof(tmp))
|
||||
break;
|
||||
ret = put_user(tmp, datap);
|
||||
if (copied == to_copy)
|
||||
ret = put_user(tmp, datap);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -277,9 +285,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||
tmp = child->mm->start_data;
|
||||
#ifdef CONFIG_BINFMT_ELF_FDPIC
|
||||
} else if (addr == (sizeof(struct pt_regs) + 12)) {
|
||||
tmp = child->mm->context.exec_fdpic_loadmap;
|
||||
goto case_PTRACE_GETFDPIC_EXEC;
|
||||
} else if (addr == (sizeof(struct pt_regs) + 16)) {
|
||||
tmp = child->mm->context.interp_fdpic_loadmap;
|
||||
goto case_PTRACE_GETFDPIC_INTERP;
|
||||
#endif
|
||||
} else {
|
||||
tmp = get_reg(child, addr);
|
||||
|
@ -288,49 +296,78 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BINFMT_ELF_FDPIC
|
||||
case PTRACE_GETFDPIC: {
|
||||
unsigned long tmp = 0;
|
||||
|
||||
switch (addr) {
|
||||
case_PTRACE_GETFDPIC_EXEC:
|
||||
case PTRACE_GETFDPIC_EXEC:
|
||||
tmp = child->mm->context.exec_fdpic_loadmap;
|
||||
break;
|
||||
case_PTRACE_GETFDPIC_INTERP:
|
||||
case PTRACE_GETFDPIC_INTERP:
|
||||
tmp = child->mm->context.interp_fdpic_loadmap;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = put_user(tmp, datap);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* when I and D space are separate, this will have to be fixed. */
|
||||
case PTRACE_POKEDATA:
|
||||
pr_debug("ptrace: PTRACE_PEEKDATA\n");
|
||||
/* fall through */
|
||||
case PTRACE_POKETEXT: /* write the word at location addr. */
|
||||
{
|
||||
int copied;
|
||||
int copied = 0, to_copy = sizeof(data);
|
||||
|
||||
ret = -EIO;
|
||||
pr_debug("ptrace: POKETEXT at addr 0x%08lx + %ld bytes %lx\n",
|
||||
addr, sizeof(data), data);
|
||||
if (is_user_addr_valid(child, addr, sizeof(data)) < 0)
|
||||
pr_debug("ptrace: POKETEXT at addr 0x%08lx + %i bytes %lx\n",
|
||||
addr, to_copy, data);
|
||||
if (is_user_addr_valid(child, addr, to_copy) < 0)
|
||||
break;
|
||||
pr_debug("ptrace: user address is valid\n");
|
||||
|
||||
if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
|
||||
&& addr + sizeof(data) <= get_l1_code_start() + L1_CODE_LENGTH) {
|
||||
safe_dma_memcpy ((void *)(addr), &data, sizeof(data));
|
||||
copied = sizeof(data);
|
||||
|
||||
} else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START
|
||||
&& addr + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
|
||||
memcpy((void *)(addr), &data, sizeof(data));
|
||||
copied = sizeof(data);
|
||||
|
||||
} else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START
|
||||
&& addr + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
|
||||
memcpy((void *)(addr), &data, sizeof(data));
|
||||
copied = sizeof(data);
|
||||
|
||||
} else if (addr >= FIXED_CODE_START
|
||||
&& addr + sizeof(data) <= FIXED_CODE_END) {
|
||||
copy_to_user_page(0, 0, 0, (void *)(addr), &data, sizeof(data));
|
||||
copied = sizeof(data);
|
||||
|
||||
} else
|
||||
switch (bfin_mem_access_type(addr, to_copy)) {
|
||||
case BFIN_MEM_ACCESS_CORE:
|
||||
case BFIN_MEM_ACCESS_CORE_ONLY:
|
||||
copied = access_process_vm(child, addr, &data,
|
||||
sizeof(data), 1);
|
||||
to_copy, 0);
|
||||
if (copied)
|
||||
break;
|
||||
|
||||
/* hrm, why didn't that work ... maybe no mapping */
|
||||
if (addr >= FIXED_CODE_START &&
|
||||
addr + to_copy <= FIXED_CODE_END) {
|
||||
copy_to_user_page(0, 0, 0, paddr, &data, to_copy);
|
||||
copied = to_copy;
|
||||
} else if (addr >= BOOT_ROM_START) {
|
||||
memcpy(paddr, &data, to_copy);
|
||||
copied = to_copy;
|
||||
}
|
||||
|
||||
break;
|
||||
case BFIN_MEM_ACCESS_DMA:
|
||||
if (safe_dma_memcpy(paddr, &data, to_copy))
|
||||
copied = to_copy;
|
||||
break;
|
||||
case BFIN_MEM_ACCESS_ITEST:
|
||||
if (isram_memcpy(paddr, &data, to_copy))
|
||||
copied = to_copy;
|
||||
break;
|
||||
default:
|
||||
copied = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pr_debug("ptrace: copied size %d\n", copied);
|
||||
if (copied != sizeof(data))
|
||||
break;
|
||||
ret = 0;
|
||||
if (copied == to_copy)
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ void __cpuinit bfin_setup_caches(unsigned int cpu)
|
|||
/*
|
||||
* In cache coherence emulation mode, we need to have the
|
||||
* D-cache enabled before running any atomic operation which
|
||||
* might invove cache invalidation (i.e. spinlock, rwlock).
|
||||
* might involve cache invalidation (i.e. spinlock, rwlock).
|
||||
* So printk's are deferred until then.
|
||||
*/
|
||||
#ifdef CONFIG_BFIN_ICACHE
|
||||
|
@ -187,6 +187,8 @@ void __init bfin_relocate_l1_mem(void)
|
|||
unsigned long l1_data_b_length;
|
||||
unsigned long l2_length;
|
||||
|
||||
early_shadow_stamp();
|
||||
|
||||
/*
|
||||
* due to the ALIGN(4) in the arch/blackfin/kernel/vmlinux.lds.S
|
||||
* we know that everything about l1 text/data is nice and aligned,
|
||||
|
@ -511,6 +513,7 @@ static __init void memory_setup(void)
|
|||
#ifdef CONFIG_MTD_UCLINUX
|
||||
unsigned long mtd_phys = 0;
|
||||
#endif
|
||||
unsigned long max_mem;
|
||||
|
||||
_rambase = (unsigned long)_stext;
|
||||
_ramstart = (unsigned long)_end;
|
||||
|
@ -520,7 +523,22 @@ static __init void memory_setup(void)
|
|||
panic("DMA region exceeds memory limit: %lu.",
|
||||
_ramend - _ramstart);
|
||||
}
|
||||
memory_end = _ramend - DMA_UNCACHED_REGION;
|
||||
max_mem = memory_end = _ramend - DMA_UNCACHED_REGION;
|
||||
|
||||
#if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
|
||||
/* Due to a Hardware Anomaly we need to limit the size of usable
|
||||
* instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
|
||||
* 05000263 - Hardware loop corrupted when taking an ICPLB exception
|
||||
*/
|
||||
# if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
|
||||
if (max_mem >= 56 * 1024 * 1024)
|
||||
max_mem = 56 * 1024 * 1024;
|
||||
# else
|
||||
if (max_mem >= 60 * 1024 * 1024)
|
||||
max_mem = 60 * 1024 * 1024;
|
||||
# endif /* CONFIG_DEBUG_HUNT_FOR_ZERO */
|
||||
#endif /* ANOMALY_05000263 */
|
||||
|
||||
|
||||
#ifdef CONFIG_MPU
|
||||
/* Round up to multiple of 4MB */
|
||||
|
@ -549,22 +567,16 @@ static __init void memory_setup(void)
|
|||
|
||||
# if defined(CONFIG_ROMFS_FS)
|
||||
if (((unsigned long *)mtd_phys)[0] == ROMSB_WORD0
|
||||
&& ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1)
|
||||
&& ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1) {
|
||||
mtd_size =
|
||||
PAGE_ALIGN(be32_to_cpu(((unsigned long *)mtd_phys)[2]));
|
||||
# if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
|
||||
/* Due to a Hardware Anomaly we need to limit the size of usable
|
||||
* instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
|
||||
* 05000263 - Hardware loop corrupted when taking an ICPLB exception
|
||||
*/
|
||||
# if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
|
||||
if (memory_end >= 56 * 1024 * 1024)
|
||||
memory_end = 56 * 1024 * 1024;
|
||||
# else
|
||||
if (memory_end >= 60 * 1024 * 1024)
|
||||
memory_end = 60 * 1024 * 1024;
|
||||
# endif /* CONFIG_DEBUG_HUNT_FOR_ZERO */
|
||||
# endif /* ANOMALY_05000263 */
|
||||
|
||||
/* ROM_FS is XIP, so if we found it, we need to limit memory */
|
||||
if (memory_end > max_mem) {
|
||||
pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20);
|
||||
memory_end = max_mem;
|
||||
}
|
||||
}
|
||||
# endif /* CONFIG_ROMFS_FS */
|
||||
|
||||
/* Since the default MTD_UCLINUX has no magic number, we just blindly
|
||||
|
@ -586,20 +598,14 @@ static __init void memory_setup(void)
|
|||
}
|
||||
#endif /* CONFIG_MTD_UCLINUX */
|
||||
|
||||
#if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
|
||||
/* Due to a Hardware Anomaly we need to limit the size of usable
|
||||
* instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
|
||||
* 05000263 - Hardware loop corrupted when taking an ICPLB exception
|
||||
/* We need lo limit memory, since everything could have a text section
|
||||
* of userspace in it, and expose anomaly 05000263. If the anomaly
|
||||
* doesn't exist, or we don't need to - then dont.
|
||||
*/
|
||||
#if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
|
||||
if (memory_end >= 56 * 1024 * 1024)
|
||||
memory_end = 56 * 1024 * 1024;
|
||||
#else
|
||||
if (memory_end >= 60 * 1024 * 1024)
|
||||
memory_end = 60 * 1024 * 1024;
|
||||
#endif /* CONFIG_DEBUG_HUNT_FOR_ZERO */
|
||||
printk(KERN_NOTICE "Warning: limiting memory to %liMB due to hardware anomaly 05000263\n", memory_end >> 20);
|
||||
#endif /* ANOMALY_05000263 */
|
||||
if (memory_end > max_mem) {
|
||||
pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20);
|
||||
memory_end = max_mem;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MPU
|
||||
page_mask_nelts = ((_ramend >> PAGE_SHIFT) + 31) / 32;
|
||||
|
@ -693,7 +699,7 @@ static __init void setup_bootmem_allocator(void)
|
|||
sanitize_memmap(bfin_memmap.map, &bfin_memmap.nr_map);
|
||||
print_memory_map("boot memmap");
|
||||
|
||||
/* intialize globals in linux/bootmem.h */
|
||||
/* initialize globals in linux/bootmem.h */
|
||||
find_min_max_pfn();
|
||||
/* pfn of the last usable page frame */
|
||||
if (max_pfn > memory_end >> PAGE_SHIFT)
|
||||
|
@ -806,6 +812,8 @@ void __init setup_arch(char **cmdline_p)
|
|||
{
|
||||
unsigned long sclk, cclk;
|
||||
|
||||
enable_shadow_console();
|
||||
|
||||
/* Check to make sure we are running on the right processor */
|
||||
if (unlikely(CPUID != bfin_cpuid()))
|
||||
printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n",
|
||||
|
@ -1230,57 +1238,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
#ifdef __ARCH_SYNC_CORE_ICACHE
|
||||
seq_printf(m, "SMP Icache Flushes\t: %lu\n\n", cpudata->icache_invld_count);
|
||||
#endif
|
||||
#ifdef CONFIG_BFIN_ICACHE_LOCK
|
||||
switch ((cpudata->imemctl >> 3) & WAYALL_L) {
|
||||
case WAY0_L:
|
||||
seq_printf(m, "Way0 Locked-Down\n");
|
||||
break;
|
||||
case WAY1_L:
|
||||
seq_printf(m, "Way1 Locked-Down\n");
|
||||
break;
|
||||
case WAY01_L:
|
||||
seq_printf(m, "Way0,Way1 Locked-Down\n");
|
||||
break;
|
||||
case WAY2_L:
|
||||
seq_printf(m, "Way2 Locked-Down\n");
|
||||
break;
|
||||
case WAY02_L:
|
||||
seq_printf(m, "Way0,Way2 Locked-Down\n");
|
||||
break;
|
||||
case WAY12_L:
|
||||
seq_printf(m, "Way1,Way2 Locked-Down\n");
|
||||
break;
|
||||
case WAY012_L:
|
||||
seq_printf(m, "Way0,Way1 & Way2 Locked-Down\n");
|
||||
break;
|
||||
case WAY3_L:
|
||||
seq_printf(m, "Way3 Locked-Down\n");
|
||||
break;
|
||||
case WAY03_L:
|
||||
seq_printf(m, "Way0,Way3 Locked-Down\n");
|
||||
break;
|
||||
case WAY13_L:
|
||||
seq_printf(m, "Way1,Way3 Locked-Down\n");
|
||||
break;
|
||||
case WAY013_L:
|
||||
seq_printf(m, "Way 0,Way1,Way3 Locked-Down\n");
|
||||
break;
|
||||
case WAY32_L:
|
||||
seq_printf(m, "Way3,Way2 Locked-Down\n");
|
||||
break;
|
||||
case WAY320_L:
|
||||
seq_printf(m, "Way3,Way2,Way0 Locked-Down\n");
|
||||
break;
|
||||
case WAY321_L:
|
||||
seq_printf(m, "Way3,Way2,Way1 Locked-Down\n");
|
||||
break;
|
||||
case WAYALL_L:
|
||||
seq_printf(m, "All Ways are locked\n");
|
||||
break;
|
||||
default:
|
||||
seq_printf(m, "No Ways are locked\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cpu_num != num_possible_cpus() - 1)
|
||||
return 0;
|
||||
|
@ -1346,6 +1303,7 @@ const struct seq_operations cpuinfo_op = {
|
|||
|
||||
void __init cmdline_init(const char *r0)
|
||||
{
|
||||
early_shadow_stamp();
|
||||
if (r0)
|
||||
strncpy(command_line, r0, COMMAND_LINE_SIZE);
|
||||
}
|
||||
|
|
113
arch/blackfin/kernel/shadow_console.c
Normal file
113
arch/blackfin/kernel/shadow_console.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* manage a small early shadow of the log buffer which we can pass between the
|
||||
* bootloader so early crash messages are communicated properly and easily
|
||||
*
|
||||
* Copyright 2009 Analog Devices Inc.
|
||||
*
|
||||
* Enter bugs at http://blackfin.uclinux.org/
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/blackfin.h>
|
||||
#include <asm/irq_handler.h>
|
||||
#include <asm/early_printk.h>
|
||||
|
||||
#define SHADOW_CONSOLE_START (0x500)
|
||||
#define SHADOW_CONSOLE_END (0x1000)
|
||||
#define SHADOW_CONSOLE_MAGIC_LOC (0x4F0)
|
||||
#define SHADOW_CONSOLE_MAGIC (0xDEADBEEF)
|
||||
|
||||
static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START;
|
||||
|
||||
__init void early_shadow_write(struct console *con, const char *s,
|
||||
unsigned int n)
|
||||
{
|
||||
unsigned int i;
|
||||
/*
|
||||
* save 2 bytes for the double null at the end
|
||||
* once we fail on a long line, make sure we don't write a short line afterwards
|
||||
*/
|
||||
if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) {
|
||||
/* can't use memcpy - it may not be relocated yet */
|
||||
for (i = 0; i <= n; i++)
|
||||
shadow_console_buffer[i] = s[i];
|
||||
shadow_console_buffer += n;
|
||||
shadow_console_buffer[0] = 0;
|
||||
shadow_console_buffer[1] = 0;
|
||||
} else
|
||||
shadow_console_buffer = (char *)SHADOW_CONSOLE_END;
|
||||
}
|
||||
|
||||
static __initdata struct console early_shadow_console = {
|
||||
.name = "early_shadow",
|
||||
.write = early_shadow_write,
|
||||
.flags = CON_BOOT | CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.device = 0,
|
||||
};
|
||||
|
||||
__init int shadow_console_enabled(void)
|
||||
{
|
||||
return early_shadow_console.flags & CON_ENABLED;
|
||||
}
|
||||
|
||||
__init void mark_shadow_error(void)
|
||||
{
|
||||
int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
|
||||
loc[0] = SHADOW_CONSOLE_MAGIC;
|
||||
loc[1] = SHADOW_CONSOLE_START;
|
||||
}
|
||||
|
||||
__init void enable_shadow_console(void)
|
||||
{
|
||||
if (!shadow_console_enabled()) {
|
||||
register_console(&early_shadow_console);
|
||||
/* for now, assume things are going to fail */
|
||||
mark_shadow_error();
|
||||
}
|
||||
}
|
||||
|
||||
static __init int disable_shadow_console(void)
|
||||
{
|
||||
/*
|
||||
* by the time pure_initcall runs, the standard console is enabled,
|
||||
* and the early_console is off, so unset the magic numbers
|
||||
* unregistering the console is taken care of in common code (See
|
||||
* ./kernel/printk:disable_boot_consoles() )
|
||||
*/
|
||||
int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
|
||||
|
||||
loc[0] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
pure_initcall(disable_shadow_console);
|
||||
|
||||
/*
|
||||
* since we can't use printk, dump numbers (as hex), n = # bits
|
||||
*/
|
||||
__init void early_shadow_reg(unsigned long reg, unsigned int n)
|
||||
{
|
||||
/*
|
||||
* can't use any "normal" kernel features, since thay
|
||||
* may not be relocated to their execute address yet
|
||||
*/
|
||||
int i;
|
||||
char ascii[11] = " 0x";
|
||||
|
||||
n = n / 4;
|
||||
reg = reg << ((8 - n) * 4);
|
||||
n += 3;
|
||||
|
||||
for (i = 3; i <= n ; i++) {
|
||||
ascii[i] = hex_asc_lo(reg >> 28);
|
||||
reg <<= 4;
|
||||
}
|
||||
early_shadow_write(NULL, ascii, n);
|
||||
|
||||
}
|
|
@ -66,7 +66,7 @@ static cycle_t bfin_read_cycles(struct clocksource *cs)
|
|||
|
||||
static struct clocksource bfin_cs_cycles = {
|
||||
.name = "bfin_cs_cycles",
|
||||
.rating = 350,
|
||||
.rating = 400,
|
||||
.read = bfin_read_cycles,
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.shift = 22,
|
||||
|
@ -115,7 +115,7 @@ static cycle_t bfin_read_gptimer0(void)
|
|||
|
||||
static struct clocksource bfin_cs_gptimer0 = {
|
||||
.name = "bfin_cs_gptimer0",
|
||||
.rating = 400,
|
||||
.rating = 350,
|
||||
.read = bfin_read_gptimer0,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.shift = 22,
|
||||
|
|
|
@ -100,7 +100,11 @@ static void decode_address(char *buf, unsigned long address)
|
|||
char *modname;
|
||||
char *delim = ":";
|
||||
char namebuf[128];
|
||||
#endif
|
||||
|
||||
buf += sprintf(buf, "<0x%08lx> ", address);
|
||||
|
||||
#ifdef CONFIG_KALLSYMS
|
||||
/* look up the address and see if we are in kernel space */
|
||||
symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
|
||||
|
||||
|
@ -108,23 +112,33 @@ static void decode_address(char *buf, unsigned long address)
|
|||
/* yeah! kernel space! */
|
||||
if (!modname)
|
||||
modname = delim = "";
|
||||
sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }",
|
||||
(void *)address, delim, modname, delim, symname,
|
||||
(unsigned long)offset);
|
||||
sprintf(buf, "{ %s%s%s%s + 0x%lx }",
|
||||
delim, modname, delim, symname,
|
||||
(unsigned long)offset);
|
||||
return;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Problem in fixed code section? */
|
||||
if (address >= FIXED_CODE_START && address < FIXED_CODE_END) {
|
||||
sprintf(buf, "<0x%p> /* Maybe fixed code section */", (void *)address);
|
||||
/* Problem in fixed code section? */
|
||||
strcat(buf, "/* Maybe fixed code section */");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Problem somewhere before the kernel start address */
|
||||
if (address < CONFIG_BOOT_LOAD) {
|
||||
sprintf(buf, "<0x%p> /* Maybe null pointer? */", (void *)address);
|
||||
} else if (address < CONFIG_BOOT_LOAD) {
|
||||
/* Problem somewhere before the kernel start address */
|
||||
strcat(buf, "/* Maybe null pointer? */");
|
||||
return;
|
||||
|
||||
} else if (address >= COREMMR_BASE) {
|
||||
strcat(buf, "/* core mmrs */");
|
||||
return;
|
||||
|
||||
} else if (address >= SYSMMR_BASE) {
|
||||
strcat(buf, "/* system mmrs */");
|
||||
return;
|
||||
|
||||
} else if (address >= L1_ROM_START && address < L1_ROM_START + L1_ROM_LENGTH) {
|
||||
strcat(buf, "/* on-chip L1 ROM */");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -172,18 +186,16 @@ static void decode_address(char *buf, unsigned long address)
|
|||
offset = (address - vma->vm_start) +
|
||||
(vma->vm_pgoff << PAGE_SHIFT);
|
||||
|
||||
sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
|
||||
(void *)address, name, offset);
|
||||
sprintf(buf, "[ %s + 0x%lx ]", name, offset);
|
||||
} else
|
||||
sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]",
|
||||
(void *)address, name,
|
||||
vma->vm_start, vma->vm_end);
|
||||
sprintf(buf, "[ %s vma:0x%lx-0x%lx]",
|
||||
name, vma->vm_start, vma->vm_end);
|
||||
|
||||
if (!in_atomic)
|
||||
mmput(mm);
|
||||
|
||||
if (!strlen(buf))
|
||||
sprintf(buf, "<0x%p> [ %s ] dynamic memory", (void *)address, name);
|
||||
if (buf[0] == '\0')
|
||||
sprintf(buf, "[ %s ] dynamic memory", name);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
@ -193,7 +205,7 @@ static void decode_address(char *buf, unsigned long address)
|
|||
}
|
||||
|
||||
/* we were unable to find this address anywhere */
|
||||
sprintf(buf, "<0x%p> /* kernel dynamic memory */", (void *)address);
|
||||
sprintf(buf, "/* kernel dynamic memory */");
|
||||
|
||||
done:
|
||||
write_unlock_irqrestore(&tasklist_lock, flags);
|
||||
|
@ -215,14 +227,14 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
|
|||
printk(KERN_EMERG "Double Fault\n");
|
||||
#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
|
||||
if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) {
|
||||
unsigned int cpu = smp_processor_id();
|
||||
unsigned int cpu = raw_smp_processor_id();
|
||||
char buf[150];
|
||||
decode_address(buf, cpu_pda[cpu].retx);
|
||||
decode_address(buf, cpu_pda[cpu].retx_doublefault);
|
||||
printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
|
||||
(unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf);
|
||||
decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
|
||||
(unsigned int)cpu_pda[cpu].seqstat_doublefault & SEQSTAT_EXCAUSE, buf);
|
||||
decode_address(buf, cpu_pda[cpu].dcplb_doublefault_addr);
|
||||
printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf);
|
||||
decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
|
||||
decode_address(buf, cpu_pda[cpu].icplb_doublefault_addr);
|
||||
printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf);
|
||||
|
||||
decode_address(buf, fp->retx);
|
||||
|
@ -245,13 +257,13 @@ static int kernel_mode_regs(struct pt_regs *regs)
|
|||
return regs->ipend & 0xffc0;
|
||||
}
|
||||
|
||||
asmlinkage void trap_c(struct pt_regs *fp)
|
||||
asmlinkage notrace void trap_c(struct pt_regs *fp)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
|
||||
int j;
|
||||
#endif
|
||||
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
||||
unsigned int cpu = smp_processor_id();
|
||||
unsigned int cpu = raw_smp_processor_id();
|
||||
#endif
|
||||
const char *strerror = NULL;
|
||||
int sig = 0;
|
||||
|
@ -267,11 +279,6 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||
* double faults if the stack has become corrupt
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_KGDB
|
||||
/* IPEND is skipped if KGDB isn't enabled (see entry code) */
|
||||
fp->ipend = bfin_read_IPEND();
|
||||
#endif
|
||||
|
||||
/* trap_c() will be called for exceptions. During exceptions
|
||||
* processing, the pc value should be set with retx value.
|
||||
* With this change we can cleanup some code in signal.c- TODO
|
||||
|
@ -404,7 +411,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||
/* 0x23 - Data CPLB protection violation, handled here */
|
||||
case VEC_CPLB_VL:
|
||||
info.si_code = ILL_CPLB_VI;
|
||||
sig = SIGBUS;
|
||||
sig = SIGSEGV;
|
||||
strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
|
@ -904,7 +911,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
|
|||
frame_no = 0;
|
||||
|
||||
for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
|
||||
addr <= endstack; addr++, i++) {
|
||||
addr < endstack; addr++, i++) {
|
||||
|
||||
ret_addr = 0;
|
||||
if (!j && i % 8 == 0)
|
||||
|
@ -949,6 +956,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(show_stack);
|
||||
|
||||
void dump_stack(void)
|
||||
{
|
||||
|
@ -1090,7 +1098,7 @@ void show_regs(struct pt_regs *fp)
|
|||
struct irqaction *action;
|
||||
unsigned int i;
|
||||
unsigned long flags = 0;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
unsigned int cpu = raw_smp_processor_id();
|
||||
unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
|
||||
|
||||
verbose_printk(KERN_NOTICE "\n");
|
||||
|
@ -1116,10 +1124,16 @@ void show_regs(struct pt_regs *fp)
|
|||
|
||||
verbose_printk(KERN_NOTICE "%s", linux_banner);
|
||||
|
||||
verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n",
|
||||
print_tainted());
|
||||
verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
|
||||
(long)fp->seqstat, fp->ipend, fp->syscfg);
|
||||
verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", print_tainted());
|
||||
verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx IMASK: %04lx SYSCFG: %04lx\n",
|
||||
(long)fp->seqstat, fp->ipend, cpu_pda[raw_smp_processor_id()].ex_imask, fp->syscfg);
|
||||
if (fp->ipend & EVT_IRPTEN)
|
||||
verbose_printk(KERN_NOTICE " Global Interrupts Disabled (IPEND[4])\n");
|
||||
if (!(cpu_pda[raw_smp_processor_id()].ex_imask & (EVT_IVG13 | EVT_IVG12 | EVT_IVG11 |
|
||||
EVT_IVG10 | EVT_IVG9 | EVT_IVG8 | EVT_IVG7 | EVT_IVTMR)))
|
||||
verbose_printk(KERN_NOTICE " Peripheral interrupts masked off\n");
|
||||
if (!(cpu_pda[raw_smp_processor_id()].ex_imask & (EVT_IVG15 | EVT_IVG14)))
|
||||
verbose_printk(KERN_NOTICE " Kernel interrupts masked off\n");
|
||||
if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
|
||||
verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n",
|
||||
(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
|
||||
|
|
|
@ -221,7 +221,7 @@ SECTIONS
|
|||
. = ALIGN(4);
|
||||
__ebss_l1 = .;
|
||||
}
|
||||
ASSERT (SIZEOF(.data_a_l1) <= L1_DATA_A_LENGTH, "L1 data A overflow!")
|
||||
ASSERT (SIZEOF(.data_l1) <= L1_DATA_A_LENGTH, "L1 data A overflow!")
|
||||
|
||||
.data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1))
|
||||
{
|
||||
|
@ -262,7 +262,7 @@ SECTIONS
|
|||
. = ALIGN(4);
|
||||
__ebss_l2 = .;
|
||||
}
|
||||
ASSERT (SIZEOF(.text_data_l1) <= L2_LENGTH, "L2 overflow!")
|
||||
ASSERT (SIZEOF(.text_data_l2) <= L2_LENGTH, "L2 overflow!")
|
||||
|
||||
/* Force trailing alignment of our init section so that when we
|
||||
* free our init memory, we don't leave behind a partial page.
|
||||
|
@ -277,8 +277,5 @@ SECTIONS
|
|||
|
||||
DWARF_DEBUG
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.exitcall.exit)
|
||||
}
|
||||
DISCARDS
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue