mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-04-13 22:17:32 +07:00
Merge branch 'for-rmk' of git://linux-arm.org/linux-2.6
This commit is contained in:
commit
40d743b8c1
2
CREDITS
2
CREDITS
@ -2800,7 +2800,7 @@ D: Starter of Linux1394 effort
|
|||||||
S: ask per mail for current address
|
S: ask per mail for current address
|
||||||
|
|
||||||
N: Nicolas Pitre
|
N: Nicolas Pitre
|
||||||
E: nico@cam.org
|
E: nico@fluxnic.net
|
||||||
D: StrongARM SA1100 support integrator & hacker
|
D: StrongARM SA1100 support integrator & hacker
|
||||||
D: Xscale PXA architecture
|
D: Xscale PXA architecture
|
||||||
D: unified SMC 91C9x/91C11x ethernet driver (smc91x)
|
D: unified SMC 91C9x/91C11x ethernet driver (smc91x)
|
||||||
|
@ -84,6 +84,16 @@ Description:
|
|||||||
from this part of the device tree.
|
from this part of the device tree.
|
||||||
Depends on CONFIG_HOTPLUG.
|
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
|
What: /sys/bus/pci/devices/.../vpd
|
||||||
Date: February 2008
|
Date: February 2008
|
||||||
Contact: Ben Hutchings <bhutchings@solarflare.com>
|
Contact: Ben Hutchings <bhutchings@solarflare.com>
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
<year>2006-2008</year>
|
<year>2006-2008</year>
|
||||||
<holder>Hans-Jürgen Koch.</holder>
|
<holder>Hans-Jürgen Koch.</holder>
|
||||||
</copyright>
|
</copyright>
|
||||||
|
<copyright>
|
||||||
|
<year>2009</year>
|
||||||
|
<holder>Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)</holder>
|
||||||
|
</copyright>
|
||||||
|
|
||||||
<legalnotice>
|
<legalnotice>
|
||||||
<para>
|
<para>
|
||||||
@ -41,6 +45,13 @@ GPL version 2.
|
|||||||
</abstract>
|
</abstract>
|
||||||
|
|
||||||
<revhistory>
|
<revhistory>
|
||||||
|
<revision>
|
||||||
|
<revnumber>0.9</revnumber>
|
||||||
|
<date>2009-07-16</date>
|
||||||
|
<authorinitials>mst</authorinitials>
|
||||||
|
<revremark>Added generic pci driver
|
||||||
|
</revremark>
|
||||||
|
</revision>
|
||||||
<revision>
|
<revision>
|
||||||
<revnumber>0.8</revnumber>
|
<revnumber>0.8</revnumber>
|
||||||
<date>2008-12-24</date>
|
<date>2008-12-24</date>
|
||||||
@ -809,6 +820,158 @@ framework to set up sysfs files for this region. Simply leave it alone.
|
|||||||
|
|
||||||
</chapter>
|
</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">
|
<appendix id="app1">
|
||||||
<title>Further information</title>
|
<title>Further information</title>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
|
@ -4,15 +4,17 @@
|
|||||||
February 2, 2006
|
February 2, 2006
|
||||||
|
|
||||||
Current document maintainer:
|
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
|
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
|
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
|
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,
|
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
|
and the PCI-host bridges found on IBM Power4, Power5 and Power6-based
|
||||||
boxes. A typical action taken is to disconnect the affected device,
|
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
|
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
|
corruption; for example, to halt system memory corruption due to DMA's
|
||||||
to "wild" addresses. Typically, a reconnection mechanism is also
|
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.
|
devices that have multiple device drivers associated with them.
|
||||||
In the first stage, each driver is allowed to indicate what type
|
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
|
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).
|
or requesting a slot reset.
|
||||||
If any driver requests a full reset, that is what will be done.
|
|
||||||
|
|
||||||
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
|
again notified, so that they may then perform any device setup/config
|
||||||
that may be required. After these have all completed, a final
|
that may be required. After these have all completed, a final
|
||||||
"resume normal operations" event is sent out.
|
"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.
|
is not implemented, the corresponding feature is considered unsupported.
|
||||||
For example, if mmio_enabled() and resume() aren't there, then it
|
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
|
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
|
not care about link resets. Typically a driver will want to know about
|
||||||
a slot_reset().
|
a slot_reset().
|
||||||
|
|
||||||
@ -111,7 +114,7 @@ sequence described below.
|
|||||||
|
|
||||||
STEP 0: Error Event
|
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,
|
is isolated, in that all I/O is blocked: all reads return 0xffffffff,
|
||||||
all writes are ignored.
|
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
|
a chance to extract some diagnostic information (see
|
||||||
mmio_enable, below).
|
mmio_enable, below).
|
||||||
- PCI_ERS_RESULT_NEED_RESET:
|
- 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.
|
slot reset.
|
||||||
- PCI_ERS_RESULT_DISCONNECT:
|
- PCI_ERS_RESULT_DISCONNECT:
|
||||||
Driver returns this if it doesn't want to recover at all.
|
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
|
>>> 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
|
>>> 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
|
>>> a value of 0xff on read, and writes will be dropped. If more than
|
||||||
>>> driver attempts more than 10K I/O's to a frozen adapter, it will
|
>>> EEH_MAX_FAILS I/O's are attempted to a frozen adapter, EEH
|
||||||
>>> assume that the device driver has gone into an infinite loop, and
|
>>> assumes that the device driver has gone into an infinite loop
|
||||||
>>> it will panic the kernel. There doesn't seem to be any other
|
>>> and prints an error to syslog. A reboot is then required to
|
||||||
>>> way of stopping a device driver that insists on spinning on I/O.
|
>>> get the device working again.
|
||||||
|
|
||||||
STEP 2: MMIO Enabled
|
STEP 2: MMIO Enabled
|
||||||
-------------------
|
-------------------
|
||||||
@ -182,15 +185,14 @@ DMA), and then calls the mmio_enabled() callback on all affected
|
|||||||
device drivers.
|
device drivers.
|
||||||
|
|
||||||
This is the "early recovery" call. IOs are allowed again, but DMA is
|
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
|
not, with some restrictions. This is NOT a callback for the driver to
|
||||||
is NOT a callback for the driver to start operations again, only to
|
start operations again, only to peek/poke at the device, extract diagnostic
|
||||||
peek/poke at the device, extract diagnostic information, if any, and
|
information, if any, and eventually do things like trigger a device local
|
||||||
eventually do things like trigger a device local reset or some such,
|
reset or some such, but not restart operations. This callback is made if
|
||||||
but not restart operations. This is callback is made if all drivers on
|
all drivers on a segment agree that they can try to recover and if no automatic
|
||||||
a segment agree that they can try to recover and if no automatic link reset
|
link reset was performed by the HW. If the platform can't just re-enable IOs
|
||||||
was performed by the HW. If the platform can't just re-enable IOs without
|
without a slot reset or a link reset, it will not call this callback, and
|
||||||
a slot reset or a link reset, it wont call this callback, and instead
|
instead will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
|
||||||
will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
|
|
||||||
|
|
||||||
>>> The following is proposed; no platform implements this yet:
|
>>> The following is proposed; no platform implements this yet:
|
||||||
>>> Proposal: All I/O's should be done _synchronously_ from within
|
>>> 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
|
If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform
|
||||||
proceeds to STEP 4 (Slot Reset)
|
proceeds to STEP 4 (Slot Reset)
|
||||||
|
|
||||||
>>> The current powerpc implementation does not implement this callback.
|
|
||||||
|
|
||||||
|
|
||||||
STEP 3: Link Reset
|
STEP 3: Link Reset
|
||||||
------------------
|
------------------
|
||||||
The platform resets the link, and then calls the link_reset() callback
|
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.
|
>>> The current powerpc implementation does not implement this callback.
|
||||||
|
|
||||||
|
|
||||||
STEP 4: Slot Reset
|
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
|
restoring the PCI BAR's and PCI configuration header to a state
|
||||||
that is equivalent to what it would be after a fresh system
|
that is equivalent to what it would be after a fresh system
|
||||||
power-on followed by power-on BIOS/system firmware initialization.
|
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
|
If the platform supports PCI hotplug, then the reset might be
|
||||||
performed by toggling the slot electrical power off/on.
|
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
|
This call gives drivers the chance to re-initialize the hardware
|
||||||
(re-download firmware, etc.). At this point, the driver may assume
|
(re-download firmware, etc.). At this point, the driver may assume
|
||||||
that he card is in a fresh state and is fully functional. In
|
that the card is in a fresh state and is fully functional. The slot
|
||||||
particular, interrupt generation should work normally.
|
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
|
at this point. If all device drivers report success on this
|
||||||
callback, the platform will call resume() to complete the sequence,
|
callback, the platform will call resume() to complete the sequence,
|
||||||
and let the driver restart normal I/O processing.
|
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
|
- PCI_ERS_RESULT_DISCONNECT
|
||||||
Same as above.
|
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
|
Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent
|
||||||
Failure).
|
Failure).
|
||||||
|
|
||||||
>>> The current powerpc implementation does not currently try a
|
>>> The current powerpc implementation does not try a power-cycle
|
||||||
>>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
|
>>> reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
|
||||||
>>> However, it probably should.
|
>>> However, it probably should.
|
||||||
|
|
||||||
|
|
||||||
@ -348,7 +376,7 @@ software errors.
|
|||||||
|
|
||||||
Conclusion; General Remarks
|
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
|
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 (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
|
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
|
- There is no guarantee that interrupt delivery can proceed from any
|
||||||
device on the segment starting from the error detection and until the
|
device on the segment starting from the error detection and until the
|
||||||
resume callback is sent, at which point interrupts are expected to be
|
slot_reset callback is called, at which point interrupts are expected
|
||||||
fully operational.
|
to be fully operational.
|
||||||
|
|
||||||
- There is no guarantee that interrupt delivery is stopped, that is,
|
- There is no guarantee that interrupt delivery is stopped, that is,
|
||||||
a driver that gets an interrupt after detecting an error, or that detects
|
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
|
>>> Implementation details for the powerpc platform are discussed in
|
||||||
>>> the file Documentation/powerpc/eeh-pci-error-recovery.txt
|
>>> the file Documentation/powerpc/eeh-pci-error-recovery.txt
|
||||||
|
|
||||||
>>> As of this writing, there are six device drivers with patches
|
>>> As of this writing, there is a growing list of device drivers with
|
||||||
>>> implementing error recovery. Not all of these patches are in
|
>>> patches implementing error recovery. Not all of these patches are in
|
||||||
>>> mainline yet. These may be used as "examples":
|
>>> mainline yet. These may be used as "examples":
|
||||||
>>>
|
>>>
|
||||||
>>> drivers/scsi/ipr.c
|
>>> drivers/scsi/ipr
|
||||||
>>> drivers/scsi/sym53cxx_2
|
>>> drivers/scsi/sym53c8xx_2
|
||||||
|
>>> drivers/scsi/qla2xxx
|
||||||
|
>>> drivers/scsi/lpfc
|
||||||
|
>>> drivers/next/bnx2.c
|
||||||
>>> drivers/next/e100.c
|
>>> drivers/next/e100.c
|
||||||
>>> drivers/net/e1000
|
>>> drivers/net/e1000
|
||||||
|
>>> drivers/net/e1000e
|
||||||
>>> drivers/net/ixgb
|
>>> drivers/net/ixgb
|
||||||
|
>>> drivers/net/ixgbe
|
||||||
|
>>> drivers/net/cxgb3
|
||||||
>>> drivers/net/s2io.c
|
>>> drivers/net/s2io.c
|
||||||
|
>>> drivers/net/qlge
|
||||||
|
|
||||||
The End
|
The End
|
||||||
-------
|
-------
|
||||||
|
@ -40,4 +40,4 @@ Notes:
|
|||||||
mode, the timing is off so the image is corrupted. This will be
|
mode, the timing is off so the image is corrupted. This will be
|
||||||
fixed soon.
|
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
|
Nicolas Pitre
|
||||||
nico@cam.org
|
nico@fluxnic.net
|
||||||
June 12, 2001
|
June 12, 2001
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ little modifications.
|
|||||||
|
|
||||||
Any contribution is welcome.
|
Any contribution is welcome.
|
||||||
|
|
||||||
Please send patches to nico@cam.org
|
Please send patches to nico@fluxnic.net
|
||||||
|
|
||||||
Have Fun !
|
Have Fun !
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ For more details, contact Applied Data Systems or see
|
|||||||
http://www.applieddata.net/products.html
|
http://www.applieddata.net/products.html
|
||||||
|
|
||||||
The original Linux support for this product has been provided by
|
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>
|
Woojung Huh <whuh@applieddata.net>
|
||||||
|
|
||||||
It's currently possible to mount a root filesystem via NFS providing a
|
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
|
mode, the timing is off so the image is corrupted. This will be
|
||||||
fixed soon.
|
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
|
http://www.applieddata.net/products.html
|
||||||
|
|
||||||
The original Linux support for this product has been provided by
|
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>
|
Woojung Huh <whuh@applieddata.net>
|
||||||
|
|
||||||
Use 'make graphicsmaster_config' before any 'make config'.
|
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
|
mode, the timing is off so the image is corrupted. This will be
|
||||||
fixed soon.
|
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:
|
The Victor implementation for Linux is maintained by Nicolas Pitre:
|
||||||
|
|
||||||
nico@visuaide.com
|
nico@visuaide.com
|
||||||
nico@cam.org
|
nico@fluxnic.net
|
||||||
|
|
||||||
For any comments, please feel free to contact me through the above
|
For any comments, please feel free to contact me through the above
|
||||||
addresses.
|
addresses.
|
||||||
|
@ -152,7 +152,6 @@ piggy.gz
|
|||||||
piggyback
|
piggyback
|
||||||
pnmtologo
|
pnmtologo
|
||||||
ppc_defs.h*
|
ppc_defs.h*
|
||||||
promcon_tbl.c
|
|
||||||
pss_boot.h
|
pss_boot.h
|
||||||
qconf
|
qconf
|
||||||
raid6altivec*.c
|
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
|
What: lock_policy_rwsem_* and unlock_policy_rwsem_* will not be
|
||||||
exported interface anymore.
|
exported interface anymore.
|
||||||
When: 2.6.33
|
When: 2.6.33
|
||||||
|
@ -2,11 +2,11 @@ Kernel driver pcf8591
|
|||||||
=====================
|
=====================
|
||||||
|
|
||||||
Supported chips:
|
Supported chips:
|
||||||
* Philips PCF8591
|
* Philips/NXP PCF8591
|
||||||
Prefix: 'pcf8591'
|
Prefix: 'pcf8591'
|
||||||
Addresses scanned: I2C 0x48 - 0x4f
|
Addresses scanned: I2C 0x48 - 0x4f
|
||||||
Datasheet: Publicly available at the Philips Semiconductor website
|
Datasheet: Publicly available at the NXP website
|
||||||
http://www.semiconductors.philips.com/pip/PCF8591P.html
|
http://www.nxp.com/pip/PCF8591_6.html
|
||||||
|
|
||||||
Authors:
|
Authors:
|
||||||
Aurelien Jarno <aurelien@aurel32.net>
|
Aurelien Jarno <aurelien@aurel32.net>
|
||||||
@ -16,9 +16,10 @@ Authors:
|
|||||||
|
|
||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
The PCF8591 is an 8-bit A/D and D/A converter (4 analog inputs and one
|
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
|
analog output) for the I2C bus produced by Philips Semiconductors (now NXP).
|
||||||
is designed to provide a byte I2C interface to up to 4 separate devices.
|
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
|
The PCF8591 has 4 analog inputs programmable as single-ended or
|
||||||
differential inputs :
|
differential inputs :
|
||||||
@ -59,7 +60,7 @@ Accessing PCF8591 via /sys interface
|
|||||||
|
|
||||||
! Be careful !
|
! Be careful !
|
||||||
The PCF8591 is plainly impossible to detect! Stupid chip.
|
The PCF8591 is plainly impossible to detect! Stupid chip.
|
||||||
So every chip with address in the interval [48..4f] is
|
So every chip with address in the interval [0x48..0x4f] is
|
||||||
detected as PCF8591. If you have other chips in this address
|
detected as PCF8591. If you have other chips in this address
|
||||||
range, the workaround is to load this module after the one
|
range, the workaround is to load this module after the one
|
||||||
for your others chips.
|
for your others chips.
|
||||||
@ -67,19 +68,20 @@ for your others chips.
|
|||||||
On detection (i.e. insmod, modprobe et al.), directories are being
|
On detection (i.e. insmod, modprobe et al.), directories are being
|
||||||
created for each detected PCF8591:
|
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)
|
where <0> is the bus the chip was detected on (e. g. i2c-0)
|
||||||
and <1> the chip address ([48..4f])
|
and <1> the chip address ([48..4f])
|
||||||
|
|
||||||
Inside these directories, there are such files:
|
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.
|
Name contains chip name.
|
||||||
|
|
||||||
The in0, in1, in2 and in3 files are RO. Reading gives the value of the
|
The in0_input, in1_input, in2_input and in3_input files are RO. Reading gives
|
||||||
corresponding channel. Depending on the current analog inputs configuration,
|
the value of the corresponding channel. Depending on the current analog inputs
|
||||||
files in2 and/or in3 do not exist. Values range are from 0 to 255 for single
|
configuration, files in2_input and in3_input may not exist. Values range
|
||||||
ended inputs and -128 to +127 for differential inputs (8-bit ADC).
|
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
|
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.
|
"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.
|
(machvec) in a generic kernel.
|
||||||
Example: machvec=hpzx1_swiotlb
|
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
|
max_addr=nn[KMG] [KNL,BOOT,ia64] All physical memory greater
|
||||||
than or equal to this physical address is ignored.
|
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 }
|
Format: { 0 | 1 }
|
||||||
See arch/parisc/kernel/pdc_chassis.c
|
See arch/parisc/kernel/pdc_chassis.c
|
||||||
|
|
||||||
percpu_alloc= [X86] Select which percpu first chunk allocator to use.
|
percpu_alloc= Select which percpu first chunk allocator to use.
|
||||||
Allowed values are one of "lpage", "embed" and "4k".
|
Currently supported values are "embed" and "page".
|
||||||
See comments in arch/x86/kernel/setup_percpu.c for
|
Archs may support subset or none of the selections.
|
||||||
details on each allocator. This parameter is primarily
|
See comments in mm/percpu.c for details on each
|
||||||
for debugging and performance comparison.
|
allocator. This parameter is primarily for debugging
|
||||||
|
and performance comparison.
|
||||||
|
|
||||||
pf. [PARIDE]
|
pf. [PARIDE]
|
||||||
See Documentation/blockdev/paride.txt.
|
See Documentation/blockdev/paride.txt.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
Event Tracing
|
Event Tracing
|
||||||
|
|
||||||
Documentation written by Theodore Ts'o
|
Documentation written by Theodore Ts'o
|
||||||
Updated by Li Zefan
|
Updated by Li Zefan and Tom Zanussi
|
||||||
|
|
||||||
1. Introduction
|
1. Introduction
|
||||||
===============
|
===============
|
||||||
@ -22,12 +22,12 @@ tracing information should be printed.
|
|||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
The events which are available for tracing can be found in the file
|
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 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
|
[ Note: '>>' is necessary, otherwise it will firstly disable
|
||||||
all the events. ]
|
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
|
To disable an event, echo the event name to the set_event file prefixed
|
||||||
with an exclamation point:
|
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:
|
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:
|
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,
|
The events are organized into subsystems, such as ext4, irq, sched,
|
||||||
etc., and a full event name looks like this: <subsystem>:<event>. The
|
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
|
"<subsystem>:*"; for example, to enable all irq events, you can use the
|
||||||
command:
|
command:
|
||||||
|
|
||||||
# echo 'irq:*' > /debug/tracing/set_event
|
# echo 'irq:*' > /sys/kernel/debug/tracing/set_event
|
||||||
|
|
||||||
2.2 Via the 'enable' toggle
|
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.
|
of directories.
|
||||||
|
|
||||||
To enable event 'sched_wakeup':
|
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:
|
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:
|
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:
|
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:
|
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
|
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).
|
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
|
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]
|
20 -> Hauppauge WinTV-HVR1255 [0070:2251]
|
||||||
21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295]
|
21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295]
|
||||||
22 -> Mygica X8506 DMB-TH [14f1:8651]
|
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]
|
79 -> Terratec Cinergy HT PCI MKII [153b:1177]
|
||||||
80 -> Hauppauge WinTV-IR Only [0070:9290]
|
80 -> Hauppauge WinTV-IR Only [0070:9290]
|
||||||
81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654]
|
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)
|
6 -> Terratec Cinergy 200 USB (em2800)
|
||||||
7 -> Leadtek Winfast USB II (em2800) [0413:6023]
|
7 -> Leadtek Winfast USB II (em2800) [0413:6023]
|
||||||
8 -> Kworld USB2800 (em2800)
|
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]
|
10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
|
||||||
11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
|
11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
|
||||||
12 -> Kworld PVR TV 2800 RF (em2820/em2840)
|
12 -> Kworld PVR TV 2800 RF (em2820/em2840)
|
||||||
@ -33,7 +33,7 @@
|
|||||||
34 -> Terratec Cinergy A Hybrid XS (em2860) [0ccd:004f]
|
34 -> Terratec Cinergy A Hybrid XS (em2860) [0ccd:004f]
|
||||||
35 -> Typhoon DVD Maker (em2860)
|
35 -> Typhoon DVD Maker (em2860)
|
||||||
36 -> NetGMBH Cam (em2860)
|
36 -> NetGMBH Cam (em2860)
|
||||||
37 -> Gadmei UTV330 (em2860)
|
37 -> Gadmei UTV330 (em2860) [eb1a:50a6]
|
||||||
38 -> Yakumo MovieMixer (em2861)
|
38 -> Yakumo MovieMixer (em2861)
|
||||||
39 -> KWorld PVRTV 300U (em2861) [eb1a:e300]
|
39 -> KWorld PVRTV 300U (em2861) [eb1a:e300]
|
||||||
40 -> Plextor ConvertX PX-TV100U (em2861) [093b:a005]
|
40 -> Plextor ConvertX PX-TV100U (em2861) [093b:a005]
|
||||||
@ -67,3 +67,4 @@
|
|||||||
69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313]
|
69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313]
|
||||||
70 -> Evga inDtube (em2882)
|
70 -> Evga inDtube (em2882)
|
||||||
71 -> Silvercrest Webcam 1.3mpix (em2820/em2840)
|
71 -> Silvercrest Webcam 1.3mpix (em2820/em2840)
|
||||||
|
72 -> Gadmei UTV330+ (em2861)
|
||||||
|
@ -167,3 +167,7 @@
|
|||||||
166 -> Beholder BeholdTV 607 RDS [5ace:6073]
|
166 -> Beholder BeholdTV 607 RDS [5ace:6073]
|
||||||
167 -> Beholder BeholdTV 609 RDS [5ace:6092]
|
167 -> Beholder BeholdTV 609 RDS [5ace:6092]
|
||||||
168 -> Beholder BeholdTV 609 RDS [5ace:6093]
|
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=78 - Philips FMD1216MEX MK3 Hybrid Tuner
|
||||||
tuner=79 - Philips PAL/SECAM multi (FM1216 MK5)
|
tuner=79 - Philips PAL/SECAM multi (FM1216 MK5)
|
||||||
tuner=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough
|
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
|
1.0 Introduction
|
||||||
|
|
||||||
The file ../drivers/char/c-qcam.c is a device driver for the
|
The file ../../drivers/media/video/c-qcam.c is a device driver for
|
||||||
Logitech (nee Connectix) parallel port interface color CCD camera.
|
the Logitech (nee Connectix) parallel port interface color CCD camera.
|
||||||
This is a fairly inexpensive device for capturing images. Logitech
|
This is a fairly inexpensive device for capturing images. Logitech
|
||||||
does not currently provide information for developers, but many people
|
does not currently provide information for developers, but many people
|
||||||
have engineered several solutions for non-Microsoft use of the Color
|
have engineered several solutions for non-Microsoft use of the Color
|
||||||
|
@ -140,6 +140,7 @@ spca500 04fc:7333 PalmPixDC85
|
|||||||
sunplus 04fc:ffff Pure DigitalDakota
|
sunplus 04fc:ffff Pure DigitalDakota
|
||||||
spca501 0506:00df 3Com HomeConnect Lite
|
spca501 0506:00df 3Com HomeConnect Lite
|
||||||
sunplus 052b:1513 Megapix V4
|
sunplus 052b:1513 Megapix V4
|
||||||
|
sunplus 052b:1803 MegaImage VI
|
||||||
tv8532 0545:808b Veo Stingray
|
tv8532 0545:808b Veo Stingray
|
||||||
tv8532 0545:8333 Veo Stingray
|
tv8532 0545:8333 Veo Stingray
|
||||||
sunplus 0546:3155 Polaroid PDC3070
|
sunplus 0546:3155 Polaroid PDC3070
|
||||||
@ -182,6 +183,7 @@ ov534 06f8:3002 Hercules Blog Webcam
|
|||||||
ov534 06f8:3003 Hercules Dualpix HD Weblog
|
ov534 06f8:3003 Hercules Dualpix HD Weblog
|
||||||
sonixj 06f8:3004 Hercules Classic Silver
|
sonixj 06f8:3004 Hercules Classic Silver
|
||||||
sonixj 06f8:3008 Hercules Deluxe Optical Glass
|
sonixj 06f8:3008 Hercules Deluxe Optical Glass
|
||||||
|
pac7311 06f8:3009 Hercules Classic Link
|
||||||
spca508 0733:0110 ViewQuest VQ110
|
spca508 0733:0110 ViewQuest VQ110
|
||||||
spca508 0130:0130 Clone Digital Webcam 11043
|
spca508 0130:0130 Clone Digital Webcam 11043
|
||||||
spca501 0733:0401 Intel Create and Share
|
spca501 0733:0401 Intel Create and Share
|
||||||
@ -235,8 +237,10 @@ pac7311 093a:2621 PAC731x
|
|||||||
pac7311 093a:2622 Genius Eye 312
|
pac7311 093a:2622 Genius Eye 312
|
||||||
pac7311 093a:2624 PAC7302
|
pac7311 093a:2624 PAC7302
|
||||||
pac7311 093a:2626 Labtec 2200
|
pac7311 093a:2626 Labtec 2200
|
||||||
|
pac7311 093a:2629 Genious iSlim 300
|
||||||
pac7311 093a:262a Webcam 300k
|
pac7311 093a:262a Webcam 300k
|
||||||
pac7311 093a:262c Philips SPC 230 NC
|
pac7311 093a:262c Philips SPC 230 NC
|
||||||
|
jeilinj 0979:0280 Sakar 57379
|
||||||
zc3xx 0ac8:0302 Z-star Vimicro zc0302
|
zc3xx 0ac8:0302 Z-star Vimicro zc0302
|
||||||
vc032x 0ac8:0321 Vimicro generic vc0321
|
vc032x 0ac8:0321 Vimicro generic vc0321
|
||||||
vc032x 0ac8:0323 Vimicro Vc0323
|
vc032x 0ac8:0323 Vimicro Vc0323
|
||||||
@ -247,6 +251,7 @@ zc3xx 0ac8:305b Z-star Vimicro zc0305b
|
|||||||
zc3xx 0ac8:307b Ldlc VC302+Ov7620
|
zc3xx 0ac8:307b Ldlc VC302+Ov7620
|
||||||
vc032x 0ac8:c001 Sony embedded vimicro
|
vc032x 0ac8:c001 Sony embedded vimicro
|
||||||
vc032x 0ac8:c002 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:0010 Hama USB Sightcam 100
|
||||||
spca508 0af9:0011 Hama USB Sightcam 100
|
spca508 0af9:0011 Hama USB Sightcam 100
|
||||||
sonixb 0c45:6001 Genius VideoCAM NB
|
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:613b Surfer SN-206
|
||||||
sonixj 0c45:613c Sonix Pccam168
|
sonixj 0c45:613c Sonix Pccam168
|
||||||
sonixj 0c45:6143 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:6240 PC Camera (SN9C201 + MT9M001)
|
||||||
sn9c20x 0c45:6242 PC Camera (SN9C201 + MT9M111)
|
sn9c20x 0c45:6242 PC Camera (SN9C201 + MT9M111)
|
||||||
sn9c20x 0c45:6248 PC Camera (SN9C201 + OV9655)
|
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
|
000/040 ALL screen_info Text mode or frame buffer information
|
||||||
(struct screen_info)
|
(struct screen_info)
|
||||||
040/014 ALL apm_bios_info APM BIOS information (struct apm_bios_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
|
060/010 ALL ist_info Intel SpeedStep (IST) BIOS support information
|
||||||
(struct ist_info)
|
(struct ist_info)
|
||||||
080/010 ALL hd0_info hd0 disk parameter, OBSOLETE!!
|
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
|
S: Maintained
|
||||||
F: drivers/net/wireless/ath/ar9170/
|
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
|
ATI_REMOTE2 DRIVER
|
||||||
M: Ville Syrjala <syrjala@sci.fi>
|
M: Ville Syrjala <syrjala@sci.fi>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
@ -2152,13 +2158,16 @@ F: Documentation/filesystems/caching/
|
|||||||
F: fs/fscache/
|
F: fs/fscache/
|
||||||
F: include/linux/fscache*.h
|
F: include/linux/fscache*.h
|
||||||
|
|
||||||
FTRACE
|
TRACING
|
||||||
M: Steven Rostedt <rostedt@goodmis.org>
|
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
|
S: Maintained
|
||||||
F: Documentation/trace/ftrace.txt
|
F: Documentation/trace/ftrace.txt
|
||||||
F: arch/*/*/*/ftrace.h
|
F: arch/*/*/*/ftrace.h
|
||||||
F: arch/*/kernel/ftrace.c
|
F: arch/*/kernel/ftrace.c
|
||||||
F: include/*/ftrace.h
|
F: include/*/ftrace.h include/trace/ include/linux/trace*.h
|
||||||
F: kernel/trace/
|
F: kernel/trace/
|
||||||
|
|
||||||
FUJITSU FR-V (FRV) PORT
|
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
|
S: Maintained
|
||||||
F: include/asm-generic
|
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
|
GFS2 FILE SYSTEM
|
||||||
M: Steven Whitehouse <swhiteho@redhat.com>
|
M: Steven Whitehouse <swhiteho@redhat.com>
|
||||||
L: cluster-devel@redhat.com
|
L: cluster-devel@redhat.com
|
||||||
@ -3317,7 +3333,7 @@ S: Supported
|
|||||||
F: drivers/net/wireless/mwl8k.c
|
F: drivers/net/wireless/mwl8k.c
|
||||||
|
|
||||||
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
|
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
|
||||||
M: Nicolas Pitre <nico@cam.org>
|
M: Nicolas Pitre <nico@fluxnic.net>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
MARVELL YUKON / SYSKONNECT DRIVER
|
MARVELL YUKON / SYSKONNECT DRIVER
|
||||||
@ -4689,7 +4705,7 @@ F: include/linux/sl?b*.h
|
|||||||
F: mm/sl?b.c
|
F: mm/sl?b.c
|
||||||
|
|
||||||
SMC91x ETHERNET DRIVER
|
SMC91x ETHERNET DRIVER
|
||||||
M: Nicolas Pitre <nico@cam.org>
|
M: Nicolas Pitre <nico@fluxnic.net>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/net/smc91x.*
|
F: drivers/net/smc91x.*
|
||||||
|
|
||||||
@ -5694,7 +5710,7 @@ F: include/xen/
|
|||||||
|
|
||||||
XFS FILESYSTEM
|
XFS FILESYSTEM
|
||||||
P: Silicon Graphics Inc
|
P: Silicon Graphics Inc
|
||||||
M: Felix Blyakher <felixb@sgi.com>
|
M: Alex Elder <aelder@sgi.com>
|
||||||
M: xfs-masters@oss.sgi.com
|
M: xfs-masters@oss.sgi.com
|
||||||
L: xfs@oss.sgi.com
|
L: xfs@oss.sgi.com
|
||||||
W: http://oss.sgi.com/projects/xfs
|
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
|
MODFLAGS = -DMODULE
|
||||||
CFLAGS_MODULE = $(MODFLAGS)
|
CFLAGS_MODULE = $(MODFLAGS)
|
||||||
AFLAGS_MODULE = $(MODFLAGS)
|
AFLAGS_MODULE = $(MODFLAGS)
|
||||||
LDFLAGS_MODULE =
|
LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds
|
||||||
CFLAGS_KERNEL =
|
CFLAGS_KERNEL =
|
||||||
AFLAGS_KERNEL =
|
AFLAGS_KERNEL =
|
||||||
CFLAGS_GCOV = -fprofile-arcs -ftest-coverage
|
CFLAGS_GCOV = -fprofile-arcs -ftest-coverage
|
||||||
|
@ -9,6 +9,7 @@ config OPROFILE
|
|||||||
depends on TRACING_SUPPORT
|
depends on TRACING_SUPPORT
|
||||||
select TRACING
|
select TRACING
|
||||||
select RING_BUFFER
|
select RING_BUFFER
|
||||||
|
select RING_BUFFER_ALLOW_SWAP
|
||||||
help
|
help
|
||||||
OProfile is a profiling system capable of profiling the
|
OProfile is a profiling system capable of profiling the
|
||||||
whole system, include the kernel, kernel modules, libraries,
|
whole system, include the kernel, kernel modules, libraries,
|
||||||
|
@ -9,10 +9,6 @@
|
|||||||
#define unmap_page_from_agp(page)
|
#define unmap_page_from_agp(page)
|
||||||
#define flush_agp_cache() mb()
|
#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. */
|
/* GATT allocation. Returns/accepts GATT kernel virtual address. */
|
||||||
#define alloc_gatt_pages(order) \
|
#define alloc_gatt_pages(order) \
|
||||||
((char *)__get_free_pages(GFP_KERNEL, (order)))
|
((char *)__get_free_pages(GFP_KERNEL, (order)))
|
||||||
|
@ -52,7 +52,6 @@ struct pci_controller {
|
|||||||
bus numbers. */
|
bus numbers. */
|
||||||
|
|
||||||
#define pcibios_assign_all_busses() 1
|
#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_IO alpha_mv.min_io_address
|
||||||
#define PCIBIOS_MIN_MEM alpha_mv.min_mem_address
|
#define PCIBIOS_MIN_MEM alpha_mv.min_mem_address
|
||||||
|
@ -1,102 +1,18 @@
|
|||||||
#ifndef __ALPHA_PERCPU_H
|
#ifndef __ALPHA_PERCPU_H
|
||||||
#define __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
|
* To calculate addresses of locally defined variables, GCC uses
|
||||||
* kernel sources.
|
* 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
|
||||||
#define per_cpu_var(var) per_cpu__##var
|
* way above 4G.
|
||||||
|
|
||||||
#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.
|
|
||||||
*
|
*
|
||||||
* This forces allocation of a GOT entry for per cpu variable using
|
* Always use weak definitions for percpu variables in modules.
|
||||||
* ldq instruction with a 'literal' relocation.
|
|
||||||
*/
|
*/
|
||||||
#define SHIFT_PERCPU_PTR(var, offset) ({ \
|
#if defined(MODULE) && defined(CONFIG_SMP)
|
||||||
extern int simple_identifier_##var(void); \
|
#define ARCH_NEEDS_WEAK_PER_CPU
|
||||||
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"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#include <asm-generic/percpu.h>
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
#endif /* __ALPHA_PERCPU_H */
|
#endif /* __ALPHA_PERCPU_H */
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define _ALPHA_TLBFLUSH_H
|
#define _ALPHA_TLBFLUSH_H
|
||||||
|
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
#include <asm/compiler.h>
|
#include <asm/compiler.h>
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
|
|
||||||
|
@ -134,13 +134,6 @@ SECTIONS
|
|||||||
__bss_stop = .;
|
__bss_stop = .;
|
||||||
_end = .;
|
_end = .;
|
||||||
|
|
||||||
/* Sections to be discarded */
|
|
||||||
/DISCARD/ : {
|
|
||||||
EXIT_TEXT
|
|
||||||
EXIT_DATA
|
|
||||||
*(.exitcall.exit)
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdebug 0 : {
|
.mdebug 0 : {
|
||||||
*(.mdebug)
|
*(.mdebug)
|
||||||
}
|
}
|
||||||
@ -150,4 +143,6 @@ SECTIONS
|
|||||||
|
|
||||||
STABS_DEBUG
|
STABS_DEBUG
|
||||||
DWARF_DEBUG
|
DWARF_DEBUG
|
||||||
|
|
||||||
|
DISCARDS
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* linux/arch/arm/boot/compressed/head-sa1100.S
|
* 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.
|
* SA1100 specific tweaks. This is merged into head.S by the linker.
|
||||||
*
|
*
|
||||||
|
@ -19,31 +19,21 @@
|
|||||||
|
|
||||||
#ifdef __KERNEL__
|
#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_read(v) ((v)->counter)
|
||||||
|
#define atomic_set(v,i) (((v)->counter) = (i))
|
||||||
|
|
||||||
#if __LINUX_ARM_ARCH__ >= 6
|
#if __LINUX_ARM_ARCH__ >= 6
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ARMv6 UP and SMP safe atomic ops. We use load exclusive and
|
* ARMv6 UP and SMP safe atomic ops. We use load exclusive and
|
||||||
* store exclusive to ensure that these are atomic. We may loop
|
* store exclusive to ensure that these are atomic. We may loop
|
||||||
* to ensure that the update happens. Writing to 'v->counter'
|
* to ensure that the update happens.
|
||||||
* without using the following operations WILL break the atomic
|
|
||||||
* nature of these ops.
|
|
||||||
*/
|
*/
|
||||||
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)
|
static inline void atomic_add(int i, atomic_t *v)
|
||||||
{
|
{
|
||||||
unsigned long tmp;
|
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
|
#error SMP not supported on pre-ARMv6 CPUs
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define atomic_set(v,i) (((v)->counter) = (i))
|
|
||||||
|
|
||||||
static inline int atomic_add_return(int i, atomic_t *v)
|
static inline int atomic_add_return(int i, atomic_t *v)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
|
|
||||||
#include <mach/hardware.h> /* for PCIBIOS_MIN_* */
|
#include <mach/hardware.h> /* for PCIBIOS_MIN_* */
|
||||||
|
|
||||||
#define pcibios_scan_all_fns(a, b) 0
|
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_HOST_ITE8152
|
#ifdef CONFIG_PCI_HOST_ITE8152
|
||||||
/* ITE bridge requires setting latency timer to avoid early bus access
|
/* ITE bridge requires setting latency timer to avoid early bus access
|
||||||
termination by PIC bus mater devices
|
termination by PIC bus mater devices
|
||||||
|
@ -35,7 +35,9 @@
|
|||||||
|
|
||||||
#define ARM(x...)
|
#define ARM(x...)
|
||||||
#define THUMB(x...) x
|
#define THUMB(x...) x
|
||||||
|
#ifdef __ASSEMBLY__
|
||||||
#define W(instr) instr.w
|
#define W(instr) instr.w
|
||||||
|
#endif
|
||||||
#define BSYM(sym) sym + 1
|
#define BSYM(sym) sym + 1
|
||||||
|
|
||||||
#else /* !CONFIG_THUMB2_KERNEL */
|
#else /* !CONFIG_THUMB2_KERNEL */
|
||||||
@ -45,7 +47,9 @@
|
|||||||
|
|
||||||
#define ARM(x...) x
|
#define ARM(x...) x
|
||||||
#define THUMB(x...)
|
#define THUMB(x...)
|
||||||
|
#ifdef __ASSEMBLY__
|
||||||
#define W(instr) instr
|
#define W(instr) instr
|
||||||
|
#endif
|
||||||
#define BSYM(sym) sym
|
#define BSYM(sym) sym
|
||||||
|
|
||||||
#endif /* CONFIG_THUMB2_KERNEL */
|
#endif /* CONFIG_THUMB2_KERNEL */
|
||||||
|
@ -272,7 +272,15 @@ __und_svc:
|
|||||||
@
|
@
|
||||||
@ r0 - instruction
|
@ r0 - instruction
|
||||||
@
|
@
|
||||||
|
#ifndef CONFIG_THUMB2_KERNEL
|
||||||
ldr r0, [r2, #-4]
|
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)
|
adr r9, BSYM(1f)
|
||||||
bl call_fpe
|
bl call_fpe
|
||||||
|
|
||||||
@ -678,7 +686,9 @@ ENTRY(fp_enter)
|
|||||||
.word no_fp
|
.word no_fp
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
no_fp: mov pc, lr
|
ENTRY(no_fp)
|
||||||
|
mov pc, lr
|
||||||
|
ENDPROC(no_fp)
|
||||||
|
|
||||||
__und_usr_unknown:
|
__und_usr_unknown:
|
||||||
enable_irq
|
enable_irq
|
||||||
@ -734,13 +744,6 @@ ENTRY(__switch_to)
|
|||||||
#ifdef CONFIG_MMU
|
#ifdef CONFIG_MMU
|
||||||
ldr r6, [r2, #TI_CPU_DOMAIN]
|
ldr r6, [r2, #TI_CPU_DOMAIN]
|
||||||
#endif
|
#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)
|
#if defined(CONFIG_HAS_TLS_REG)
|
||||||
mcr p15, 0, r3, c13, c0, 3 @ set TLS register
|
mcr p15, 0, r3, c13, c0, 3 @ set TLS register
|
||||||
#elif !defined(CONFIG_TLS_REG_EMUL)
|
#elif !defined(CONFIG_TLS_REG_EMUL)
|
||||||
|
@ -76,13 +76,25 @@
|
|||||||
#ifndef CONFIG_THUMB2_KERNEL
|
#ifndef CONFIG_THUMB2_KERNEL
|
||||||
.macro svc_exit, rpsr
|
.macro svc_exit, rpsr
|
||||||
msr spsr_cxsf, \rpsr
|
msr spsr_cxsf, \rpsr
|
||||||
|
#if defined(CONFIG_CPU_32v6K)
|
||||||
|
clrex @ clear the exclusive monitor
|
||||||
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
|
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
|
.endm
|
||||||
|
|
||||||
.macro restore_user_regs, fast = 0, offset = 0
|
.macro restore_user_regs, fast = 0, offset = 0
|
||||||
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
|
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
|
||||||
ldr lr, [sp, #\offset + S_PC]! @ get pc
|
ldr lr, [sp, #\offset + S_PC]! @ get pc
|
||||||
msr spsr_cxsf, r1 @ save in spsr_svc
|
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
|
.if \fast
|
||||||
ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
|
ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
|
||||||
.else
|
.else
|
||||||
@ -98,6 +110,7 @@
|
|||||||
.endm
|
.endm
|
||||||
#else /* CONFIG_THUMB2_KERNEL */
|
#else /* CONFIG_THUMB2_KERNEL */
|
||||||
.macro svc_exit, rpsr
|
.macro svc_exit, rpsr
|
||||||
|
clrex @ clear the exclusive monitor
|
||||||
ldr r0, [sp, #S_SP] @ top of the stack
|
ldr r0, [sp, #S_SP] @ top of the stack
|
||||||
ldr r1, [sp, #S_PC] @ return address
|
ldr r1, [sp, #S_PC] @ return address
|
||||||
tst r0, #4 @ orig stack 8-byte aligned?
|
tst r0, #4 @ orig stack 8-byte aligned?
|
||||||
@ -110,6 +123,7 @@
|
|||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro restore_user_regs, fast = 0, offset = 0
|
.macro restore_user_regs, fast = 0, offset = 0
|
||||||
|
clrex @ clear the exclusive monitor
|
||||||
mov r2, sp
|
mov r2, sp
|
||||||
load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr
|
load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr
|
||||||
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
|
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
|
||||||
|
@ -83,6 +83,7 @@ SECTIONS
|
|||||||
EXIT_TEXT
|
EXIT_TEXT
|
||||||
EXIT_DATA
|
EXIT_DATA
|
||||||
*(.exitcall.exit)
|
*(.exitcall.exit)
|
||||||
|
*(.discard)
|
||||||
*(.ARM.exidx.exit.text)
|
*(.ARM.exidx.exit.text)
|
||||||
*(.ARM.extab.exit.text)
|
*(.ARM.extab.exit.text)
|
||||||
#ifndef CONFIG_HOTPLUG_CPU
|
#ifndef CONFIG_HOTPLUG_CPU
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
|
* 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
|
* - contributed to gcc-3.4 on Sep 30, 2003
|
||||||
* - adapted for the Linux kernel on Oct 2, 2003
|
* - adapted for the Linux kernel on Oct 2, 2003
|
||||||
*/
|
*/
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* SHA transform optimized for ARM
|
* 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
|
* Created: September 17, 2005
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* arch/arm/mach-sa1100/include/mach/assabet.h
|
* 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
|
* This file contains the hardware specific definitions for Assabet
|
||||||
* Only include this file from SA1100-specific files.
|
* Only include this file from SA1100-specific files.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* arch/arm/mach-sa1100/include/mach/hardware.h
|
* 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
|
* This file contains the hardware definitions for SA1100 architecture
|
||||||
*
|
*
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* arch/arm/mach-sa1100/include/mach/memory.h
|
* 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
|
#ifndef __ASM_ARCH_MEMORY_H
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* arch/arm/mach-sa1100/include/mach/neponset.h
|
* 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
|
* This file contains the hardware specific definitions for Assabet
|
||||||
* Only include this file from SA1100-specific files.
|
* Only include this file from SA1100-specific files.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* arch/arm/mach-sa1100/include/mach/system.h
|
* 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>
|
#include <mach/hardware.h>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* arch/arm/mach-sa1100/include/mach/uncompress.h
|
* 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.
|
* Reorganised to be machine independent.
|
||||||
*/
|
*/
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Save more value for the resume function! Support
|
* Save more value for the resume function! Support
|
||||||
* Bitsy/Assabet/Freebird board
|
* 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
|
* Cleaned up, pushed platform dependent stuff
|
||||||
* in the platform specific files.
|
* in the platform specific files.
|
||||||
*
|
*
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Copyright (C) 1998 Deborah Wallach.
|
* Copyright (C) 1998 Deborah Wallach.
|
||||||
* Twiddles (C) 1999 Hugo Fiennes <hugo@empeg.com>
|
* 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.
|
* Rewritten: big cleanup, much simpler, better HZ accuracy.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
*
|
*
|
||||||
* 2001 Sep 08:
|
* 2001 Sep 08:
|
||||||
* Completely revisited, many important fixes
|
* Completely revisited, many important fixes
|
||||||
* Nicolas Pitre <nico@cam.org>
|
* Nicolas Pitre <nico@fluxnic.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* arch/arm/plat-iop/setup.c
|
* 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) 2001 MontaVista Software, Inc.
|
||||||
* Copyright (C) 2004 Intel Corporation.
|
* Copyright (C) 2004 Intel Corporation.
|
||||||
*
|
*
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copied from arch/arm/mach-sa1100/include/mach/system.h
|
* 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
|
#ifndef __ASM_ARCH_SYSTEM_H
|
||||||
#define __ASM_ARCH_SYSTEM_H
|
#define __ASM_ARCH_SYSTEM_H
|
||||||
|
@ -124,14 +124,11 @@ SECTIONS
|
|||||||
_end = .;
|
_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWARF_DEBUG
|
||||||
|
|
||||||
/* When something in the kernel is NOT compiled as a module, the module
|
/* 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
|
* 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.
|
* thrown away, as cleanup code is never called unless it's a module.
|
||||||
*/
|
*/
|
||||||
/DISCARD/ : {
|
DISCARDS
|
||||||
EXIT_DATA
|
|
||||||
*(.exitcall.exit)
|
|
||||||
}
|
|
||||||
|
|
||||||
DWARF_DEBUG
|
|
||||||
}
|
}
|
||||||
|
@ -342,8 +342,9 @@ config MEM_MT48LC64M4A2FB_7E
|
|||||||
config MEM_MT48LC16M16A2TG_75
|
config MEM_MT48LC16M16A2TG_75
|
||||||
bool
|
bool
|
||||||
depends on (BFIN533_EZKIT || BFIN561_EZKIT \
|
depends on (BFIN533_EZKIT || BFIN561_EZKIT \
|
||||||
|| BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM \
|
|| BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM_E \
|
||||||
|| H8606_HVSISTEMAS || BFIN527_BLUETECHNIX_CM)
|
|| BFIN537_BLUETECHNIX_CM_U || H8606_HVSISTEMAS \
|
||||||
|
|| BFIN527_BLUETECHNIX_CM)
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config MEM_MT48LC32M8A2_75
|
config MEM_MT48LC32M8A2_75
|
||||||
@ -459,7 +460,7 @@ config VCO_MULT
|
|||||||
default "45" if BFIN533_STAMP
|
default "45" if BFIN533_STAMP
|
||||||
default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM || BFIN538_EZKIT)
|
default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM || BFIN538_EZKIT)
|
||||||
default "22" if BFIN533_BLUETECHNIX_CM
|
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 "20" if BFIN561_EZKIT
|
||||||
default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN518F_EZBRD)
|
default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN518F_EZBRD)
|
||||||
help
|
help
|
||||||
@ -574,8 +575,8 @@ config MAX_VCO_HZ
|
|||||||
default 400000000 if BF514
|
default 400000000 if BF514
|
||||||
default 400000000 if BF516
|
default 400000000 if BF516
|
||||||
default 400000000 if BF518
|
default 400000000 if BF518
|
||||||
default 600000000 if BF522
|
default 400000000 if BF522
|
||||||
default 400000000 if BF523
|
default 600000000 if BF523
|
||||||
default 400000000 if BF524
|
default 400000000 if BF524
|
||||||
default 600000000 if BF525
|
default 600000000 if BF525
|
||||||
default 400000000 if BF526
|
default 400000000 if BF526
|
||||||
@ -647,7 +648,7 @@ config CYCLES_CLOCKSOURCE
|
|||||||
writing the registers will most likely crash the kernel.
|
writing the registers will most likely crash the kernel.
|
||||||
|
|
||||||
config GPTMR0_CLOCKSOURCE
|
config GPTMR0_CLOCKSOURCE
|
||||||
bool "Use GPTimer0 as a clocksource (higher rating)"
|
bool "Use GPTimer0 as a clocksource"
|
||||||
select BFIN_GPTIMERS
|
select BFIN_GPTIMERS
|
||||||
depends on GENERIC_CLOCKEVENTS
|
depends on GENERIC_CLOCKEVENTS
|
||||||
depends on !TICKSOURCE_GPTMR0
|
depends on !TICKSOURCE_GPTMR0
|
||||||
@ -917,10 +918,6 @@ comment "Cache Support"
|
|||||||
config BFIN_ICACHE
|
config BFIN_ICACHE
|
||||||
bool "Enable ICACHE"
|
bool "Enable ICACHE"
|
||||||
default y
|
default y
|
||||||
config BFIN_ICACHE_LOCK
|
|
||||||
bool "Enable Instruction Cache Locking"
|
|
||||||
depends on BFIN_ICACHE
|
|
||||||
default n
|
|
||||||
config BFIN_EXTMEM_ICACHEABLE
|
config BFIN_EXTMEM_ICACHEABLE
|
||||||
bool "Enable ICACHE for external memory"
|
bool "Enable ICACHE for external memory"
|
||||||
depends on BFIN_ICACHE
|
depends on BFIN_ICACHE
|
||||||
@ -987,7 +984,7 @@ endchoice
|
|||||||
config BFIN_L2_DCACHEABLE
|
config BFIN_L2_DCACHEABLE
|
||||||
bool "Enable DCACHE for L2 SRAM"
|
bool "Enable DCACHE for L2 SRAM"
|
||||||
depends on BFIN_DCACHE
|
depends on BFIN_DCACHE
|
||||||
depends on BF54x || BF561
|
depends on (BF54x || BF561) && !SMP
|
||||||
default n
|
default n
|
||||||
choice
|
choice
|
||||||
prompt "L2 SRAM DCACHE policy"
|
prompt "L2 SRAM DCACHE policy"
|
||||||
@ -995,11 +992,9 @@ choice
|
|||||||
default BFIN_L2_WRITEBACK
|
default BFIN_L2_WRITEBACK
|
||||||
config BFIN_L2_WRITEBACK
|
config BFIN_L2_WRITEBACK
|
||||||
bool "Write back"
|
bool "Write back"
|
||||||
depends on !SMP
|
|
||||||
|
|
||||||
config BFIN_L2_WRITETHROUGH
|
config BFIN_L2_WRITETHROUGH
|
||||||
bool "Write through"
|
bool "Write through"
|
||||||
depends on !SMP
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
|
||||||
@ -1154,11 +1149,12 @@ source "fs/Kconfig.binfmt"
|
|||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
menu "Power management options"
|
menu "Power management options"
|
||||||
|
depends on !SMP
|
||||||
|
|
||||||
source "kernel/power/Kconfig"
|
source "kernel/power/Kconfig"
|
||||||
|
|
||||||
config ARCH_SUSPEND_POSSIBLE
|
config ARCH_SUSPEND_POSSIBLE
|
||||||
def_bool y
|
def_bool y
|
||||||
depends on !SMP
|
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Standby Power Saving Mode"
|
prompt "Standby Power Saving Mode"
|
||||||
@ -1246,6 +1242,7 @@ config PM_BFIN_WAKE_GP
|
|||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
menu "CPU Frequency scaling"
|
menu "CPU Frequency scaling"
|
||||||
|
depends on !SMP
|
||||||
|
|
||||||
source "drivers/cpufreq/Kconfig"
|
source "drivers/cpufreq/Kconfig"
|
||||||
|
|
||||||
|
@ -252,4 +252,10 @@ config ACCESS_CHECK
|
|||||||
|
|
||||||
Say N here to disable that check to improve the performance.
|
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
|
endmenu
|
||||||
|
@ -358,9 +358,9 @@ CONFIG_C_AMBEN_ALL=y
|
|||||||
# EBIU_AMBCTL Control
|
# EBIU_AMBCTL Control
|
||||||
#
|
#
|
||||||
CONFIG_BANK_0=0x7BB0
|
CONFIG_BANK_0=0x7BB0
|
||||||
CONFIG_BANK_1=0x5554
|
CONFIG_BANK_1=0x7BB0
|
||||||
CONFIG_BANK_2=0x7BB0
|
CONFIG_BANK_2=0x7BB0
|
||||||
CONFIG_BANK_3=0xFFC0
|
CONFIG_BANK_3=0x99B2
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
|
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
|
||||||
|
@ -359,9 +359,9 @@ CONFIG_C_AMBEN_ALL=y
|
|||||||
# EBIU_AMBCTL Control
|
# EBIU_AMBCTL Control
|
||||||
#
|
#
|
||||||
CONFIG_BANK_0=0x7BB0
|
CONFIG_BANK_0=0x7BB0
|
||||||
CONFIG_BANK_1=0x5554
|
CONFIG_BANK_1=0x7BB0
|
||||||
CONFIG_BANK_2=0x7BB0
|
CONFIG_BANK_2=0x7BB0
|
||||||
CONFIG_BANK_3=0xFFC0
|
CONFIG_BANK_3=0x99B2
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
|
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
|
||||||
|
@ -363,9 +363,9 @@ CONFIG_C_AMBEN_ALL=y
|
|||||||
# EBIU_AMBCTL Control
|
# EBIU_AMBCTL Control
|
||||||
#
|
#
|
||||||
CONFIG_BANK_0=0x7BB0
|
CONFIG_BANK_0=0x7BB0
|
||||||
CONFIG_BANK_1=0x5554
|
CONFIG_BANK_1=0x7BB0
|
||||||
CONFIG_BANK_2=0x7BB0
|
CONFIG_BANK_2=0x7BB0
|
||||||
CONFIG_BANK_3=0xFFC0
|
CONFIG_BANK_3=0x99B2
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
|
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
|
||||||
|
@ -400,7 +400,7 @@ CONFIG_C_AMBEN_ALL=y
|
|||||||
# EBIU_AMBCTL Control
|
# EBIU_AMBCTL Control
|
||||||
#
|
#
|
||||||
CONFIG_BANK_0=0x7BB0
|
CONFIG_BANK_0=0x7BB0
|
||||||
CONFIG_BANK_1=0x5554
|
CONFIG_BANK_1=0x7BB0
|
||||||
CONFIG_BANK_2=0x7BB0
|
CONFIG_BANK_2=0x7BB0
|
||||||
CONFIG_BANK_3=0x99B2
|
CONFIG_BANK_3=0x99B2
|
||||||
CONFIG_EBIU_MBSCTLVAL=0x0
|
CONFIG_EBIU_MBSCTLVAL=0x0
|
||||||
|
@ -66,7 +66,6 @@ extern void program_IAR(void);
|
|||||||
|
|
||||||
extern asmlinkage void lower_to_irq14(void);
|
extern asmlinkage void lower_to_irq14(void);
|
||||||
extern asmlinkage void bfin_return_from_exception(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 asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs);
|
||||||
extern int bfin_internal_set_wake(unsigned int irq, unsigned int state);
|
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 unsigned vr_wakeup;
|
||||||
extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */
|
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
|
||||||
|
|
||||||
#endif /* _BLACKFIN_H_ */
|
#endif /* _BLACKFIN_H_ */
|
||||||
|
@ -127,6 +127,7 @@ struct bfin5xx_spi_chip {
|
|||||||
u32 cs_gpio;
|
u32 cs_gpio;
|
||||||
/* Value to send if no TX value is supplied, usually 0x0 or 0xFFFF */
|
/* Value to send if no TX value is supplied, usually 0x0 or 0xFFFF */
|
||||||
u16 idle_tx_val;
|
u16 idle_tx_val;
|
||||||
|
u8 pio_interrupt; /* Enable spi data irq */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _SPI_CHANNEL_H_ */
|
#endif /* _SPI_CHANNEL_H_ */
|
||||||
|
@ -125,4 +125,48 @@
|
|||||||
#define FAULT_USERSUPV (1 << 17)
|
#define FAULT_USERSUPV (1 << 17)
|
||||||
#define FAULT_CPLBBITS 0x0000ffff
|
#define FAULT_CPLBBITS 0x0000ffff
|
||||||
|
|
||||||
|
#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 */
|
#endif /* _CPLB_H */
|
||||||
|
@ -21,8 +21,32 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __ASM_EARLY_PRINTK_H__
|
||||||
|
#define __ASM_EARLY_PRINTK_H__
|
||||||
|
|
||||||
#ifdef CONFIG_EARLY_PRINTK
|
#ifdef CONFIG_EARLY_PRINTK
|
||||||
|
/* For those that don't include it already */
|
||||||
|
#include <linux/console.h>
|
||||||
|
|
||||||
extern int setup_early_printk(char *);
|
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
|
#else
|
||||||
#define setup_early_printk(fmt) do { } while (0)
|
#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 /* 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)) */
|
#define ELF_NGREG 40 /* (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) */
|
||||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
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.
|
* This is used to ensure we don't load something for the wrong architecture.
|
||||||
*/
|
*/
|
||||||
|
@ -36,6 +36,21 @@
|
|||||||
# define LOAD_IPIPE_IPEND
|
# define LOAD_IPIPE_IPEND
|
||||||
#endif
|
#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
|
#ifndef CONFIG_EXACT_HWERR
|
||||||
/* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
|
/* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
|
||||||
* otherwise it is a waste of cycles.
|
* 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
|
* 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
|
* make sure the read/writes complete, and another to make sure the hardware
|
||||||
* error is recognized by the core.
|
* 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) \
|
#define INTERRUPT_ENTRY(N) \
|
||||||
SSYNC; \
|
|
||||||
SSYNC; \
|
|
||||||
[--sp] = SYSCFG; \
|
[--sp] = SYSCFG; \
|
||||||
[--sp] = P0; /*orig_p0*/ \
|
[--sp] = P0; /*orig_p0*/ \
|
||||||
[--sp] = R0; /*orig_r0*/ \
|
[--sp] = R0; /*orig_r0*/ \
|
||||||
[--sp] = (R7:0,P5:0); \
|
[--sp] = (R7:0,P5:0); \
|
||||||
R1 = ASTAT; \
|
R1 = ASTAT; \
|
||||||
|
ANOMALY_283_315_WORKAROUND(p0, r0) \
|
||||||
P0.L = LO(ILAT); \
|
P0.L = LO(ILAT); \
|
||||||
P0.H = HI(ILAT); \
|
P0.H = HI(ILAT); \
|
||||||
|
NOP; \
|
||||||
|
SSYNC; \
|
||||||
|
SSYNC; \
|
||||||
R0 = [P0]; \
|
R0 = [P0]; \
|
||||||
CC = BITTST(R0, EVT_IVHW_P); \
|
CC = BITTST(R0, EVT_IVHW_P); \
|
||||||
IF CC JUMP 1f; \
|
IF CC JUMP 1f; \
|
||||||
@ -118,15 +138,17 @@
|
|||||||
RTI;
|
RTI;
|
||||||
|
|
||||||
#define TIMER_INTERRUPT_ENTRY(N) \
|
#define TIMER_INTERRUPT_ENTRY(N) \
|
||||||
SSYNC; \
|
|
||||||
SSYNC; \
|
|
||||||
[--sp] = SYSCFG; \
|
[--sp] = SYSCFG; \
|
||||||
[--sp] = P0; /*orig_p0*/ \
|
[--sp] = P0; /*orig_p0*/ \
|
||||||
[--sp] = R0; /*orig_r0*/ \
|
[--sp] = R0; /*orig_r0*/ \
|
||||||
[--sp] = (R7:0,P5:0); \
|
[--sp] = (R7:0,P5:0); \
|
||||||
R1 = ASTAT; \
|
R1 = ASTAT; \
|
||||||
|
ANOMALY_283_315_WORKAROUND(p0, r0) \
|
||||||
P0.L = LO(ILAT); \
|
P0.L = LO(ILAT); \
|
||||||
P0.H = HI(ILAT); \
|
P0.H = HI(ILAT); \
|
||||||
|
NOP; \
|
||||||
|
SSYNC; \
|
||||||
|
SSYNC; \
|
||||||
R0 = [P0]; \
|
R0 = [P0]; \
|
||||||
CC = BITTST(R0, EVT_IVHW_P); \
|
CC = BITTST(R0, EVT_IVHW_P); \
|
||||||
IF CC JUMP 1f; \
|
IF CC JUMP 1f; \
|
||||||
|
@ -8,6 +8,6 @@
|
|||||||
#ifndef __ASM_BFIN_FTRACE_H__
|
#ifndef __ASM_BFIN_FTRACE_H__
|
||||||
#define __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
|
#endif
|
||||||
|
@ -145,10 +145,6 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs);
|
|||||||
|
|
||||||
int __ipipe_get_irq_priority(unsigned irq);
|
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, ...);
|
void __ipipe_serial_debug(const char *fmt, ...);
|
||||||
|
|
||||||
asmlinkage void __ipipe_call_irqtail(unsigned long addr);
|
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 task_hijacked(p) 0
|
||||||
#define ipipe_trap_notify(t, r) 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_init_irq_threads() do { } while (0)
|
||||||
#define ipipe_start_irq_thread(irq, desc) 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_evt11(void);
|
||||||
asmlinkage void evt_evt12(void);
|
asmlinkage void evt_evt12(void);
|
||||||
asmlinkage void evt_evt13(void);
|
asmlinkage void evt_evt13(void);
|
||||||
|
asmlinkage void evt_evt14(void);
|
||||||
asmlinkage void evt_soft_int1(void);
|
asmlinkage void evt_soft_int1(void);
|
||||||
asmlinkage void evt_system_call(void);
|
asmlinkage void evt_system_call(void);
|
||||||
asmlinkage void init_exception_buff(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 idx = page >> 5;
|
||||||
unsigned long bit = 1 << (page & 31);
|
unsigned long bit = 1 << (page & 31);
|
||||||
|
|
||||||
if (flags & VM_MAYREAD)
|
if (flags & VM_READ)
|
||||||
mask[idx] |= bit;
|
mask[idx] |= bit;
|
||||||
else
|
else
|
||||||
mask[idx] &= ~bit;
|
mask[idx] &= ~bit;
|
||||||
mask += page_mask_nelts;
|
mask += page_mask_nelts;
|
||||||
if (flags & VM_MAYWRITE)
|
if (flags & VM_WRITE)
|
||||||
mask[idx] |= bit;
|
mask[idx] |= bit;
|
||||||
else
|
else
|
||||||
mask[idx] &= ~bit;
|
mask[idx] &= ~bit;
|
||||||
mask += page_mask_nelts;
|
mask += page_mask_nelts;
|
||||||
if (flags & VM_MAYEXEC)
|
if (flags & VM_EXEC)
|
||||||
mask[idx] |= bit;
|
mask[idx] |= bit;
|
||||||
else
|
else
|
||||||
mask[idx] &= ~bit;
|
mask[idx] &= ~bit;
|
||||||
|
@ -50,6 +50,7 @@ struct blackfin_pda { /* Per-processor Data Area */
|
|||||||
unsigned long ex_optr;
|
unsigned long ex_optr;
|
||||||
unsigned long ex_buf[4];
|
unsigned long ex_buf[4];
|
||||||
unsigned long ex_imask; /* Saved imask from exception */
|
unsigned long ex_imask; /* Saved imask from exception */
|
||||||
|
unsigned long ex_ipend; /* Saved IPEND from exception */
|
||||||
unsigned long *ex_stack; /* Exception stack space */
|
unsigned long *ex_stack; /* Exception stack space */
|
||||||
|
|
||||||
#ifdef ANOMALY_05000261
|
#ifdef ANOMALY_05000261
|
||||||
@ -60,6 +61,12 @@ struct blackfin_pda { /* Per-processor Data Area */
|
|||||||
unsigned long retx;
|
unsigned long retx;
|
||||||
unsigned long seqstat;
|
unsigned long seqstat;
|
||||||
unsigned int __nmi_count; /* number of times NMI asserted on this CPU */
|
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[];
|
extern struct blackfin_pda cpu_pda[];
|
||||||
|
@ -26,6 +26,7 @@ obj-$(CONFIG_MODULES) += module.o
|
|||||||
obj-$(CONFIG_KGDB) += kgdb.o
|
obj-$(CONFIG_KGDB) += kgdb.o
|
||||||
obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o
|
obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o
|
||||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||||
|
obj-$(CONFIG_EARLY_PRINTK) += shadow_console.o
|
||||||
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||||
|
|
||||||
# the kgdb test puts code into L2 and without linker
|
# 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_EXBUF, offsetof(struct blackfin_pda, ex_buf));
|
||||||
DEFINE(PDA_EXIMASK, offsetof(struct blackfin_pda, ex_imask));
|
DEFINE(PDA_EXIMASK, offsetof(struct blackfin_pda, ex_imask));
|
||||||
DEFINE(PDA_EXSTACK, offsetof(struct blackfin_pda, ex_stack));
|
DEFINE(PDA_EXSTACK, offsetof(struct blackfin_pda, ex_stack));
|
||||||
|
DEFINE(PDA_EXIPEND, offsetof(struct blackfin_pda, ex_ipend));
|
||||||
#ifdef ANOMALY_05000261
|
#ifdef ANOMALY_05000261
|
||||||
DEFINE(PDA_LFRETX, offsetof(struct blackfin_pda, last_cplb_fault_retx));
|
DEFINE(PDA_LFRETX, offsetof(struct blackfin_pda, last_cplb_fault_retx));
|
||||||
#endif
|
#endif
|
||||||
@ -152,6 +153,12 @@ int main(void)
|
|||||||
DEFINE(PDA_ICPLB, offsetof(struct blackfin_pda, icplb_fault_addr));
|
DEFINE(PDA_ICPLB, offsetof(struct blackfin_pda, icplb_fault_addr));
|
||||||
DEFINE(PDA_RETX, offsetof(struct blackfin_pda, retx));
|
DEFINE(PDA_RETX, offsetof(struct blackfin_pda, retx));
|
||||||
DEFINE(PDA_SEQSTAT, offsetof(struct blackfin_pda, seqstat));
|
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
|
#ifdef CONFIG_SMP
|
||||||
/* Inter-core lock (in L2 SRAM) */
|
/* Inter-core lock (in L2 SRAM) */
|
||||||
DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot));
|
DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot));
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/dma.h>
|
#include <asm/dma.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
#include <asm/early_printk.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To make sure we work around 05000119 - we always check DMA_DONE bit,
|
* 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)
|
int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data)
|
||||||
{
|
{
|
||||||
BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
|
BUG_ON(channel >= MAX_DMA_CHANNELS ||
|
||||||
&& channel < MAX_DMA_CHANNELS));
|
dma_ch[channel].chan_status == DMA_CHANNEL_FREE);
|
||||||
|
|
||||||
if (callback != NULL) {
|
if (callback != NULL) {
|
||||||
int ret;
|
int ret;
|
||||||
@ -181,8 +182,8 @@ static void clear_dma_buffer(unsigned int channel)
|
|||||||
void free_dma(unsigned int channel)
|
void free_dma(unsigned int channel)
|
||||||
{
|
{
|
||||||
pr_debug("freedma() : BEGIN \n");
|
pr_debug("freedma() : BEGIN \n");
|
||||||
BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
|
BUG_ON(channel >= MAX_DMA_CHANNELS ||
|
||||||
&& channel < MAX_DMA_CHANNELS));
|
dma_ch[channel].chan_status == DMA_CHANNEL_FREE);
|
||||||
|
|
||||||
/* Halt the DMA */
|
/* Halt the DMA */
|
||||||
disable_dma(channel);
|
disable_dma(channel);
|
||||||
@ -236,6 +237,7 @@ void blackfin_dma_resume(void)
|
|||||||
*/
|
*/
|
||||||
void __init blackfin_dma_early_init(void)
|
void __init blackfin_dma_early_init(void)
|
||||||
{
|
{
|
||||||
|
early_shadow_stamp();
|
||||||
bfin_write_MDMA_S0_CONFIG(0);
|
bfin_write_MDMA_S0_CONFIG(0);
|
||||||
bfin_write_MDMA_S1_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;
|
unsigned long src = (unsigned long)psrc;
|
||||||
struct dma_register *dst_ch, *src_ch;
|
struct dma_register *dst_ch, *src_ch;
|
||||||
|
|
||||||
|
early_shadow_stamp();
|
||||||
|
|
||||||
/* We assume that everything is 4 byte aligned, so include
|
/* We assume that everything is 4 byte aligned, so include
|
||||||
* a basic sanity check
|
* 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)
|
void __init early_dma_memcpy_done(void)
|
||||||
{
|
{
|
||||||
|
early_shadow_stamp();
|
||||||
|
|
||||||
while ((bfin_read_MDMA_S0_CONFIG() && !(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) ||
|
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)))
|
(bfin_read_MDMA_S1_CONFIG() && !(bfin_read_MDMA_D1_IRQ_STATUS() & DMA_DONE)))
|
||||||
continue;
|
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].fer = gpio_array[bank]->port_fer;
|
||||||
gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
|
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].data = gpio_array[bank]->data;
|
|
||||||
gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
|
gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
|
||||||
gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;
|
gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# arch/blackfin/kernel/cplb-nompu/Makefile
|
# 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 \
|
CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \
|
||||||
-ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \
|
-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/blackfin.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/cplb.h>
|
||||||
#include <asm/cplbinit.h>
|
#include <asm/cplbinit.h>
|
||||||
#include <asm/mmu_context.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_icplb_supv_miss[NR_CPUS], nr_dcplb_prot[NR_CPUS];
|
||||||
int nr_cplb_flush[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
|
* Given the contents of the status register, return the index of the
|
||||||
* CPLB that caused the fault.
|
* 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].addr = addr;
|
||||||
dcplb_tbl[cpu][idx].data = d_data;
|
dcplb_tbl[cpu][idx].data = d_data;
|
||||||
|
|
||||||
disable_dcplb();
|
_disable_dcplb();
|
||||||
bfin_write32(DCPLB_DATA0 + idx * 4, d_data);
|
bfin_write32(DCPLB_DATA0 + idx * 4, d_data);
|
||||||
bfin_write32(DCPLB_ADDR0 + idx * 4, addr);
|
bfin_write32(DCPLB_ADDR0 + idx * 4, addr);
|
||||||
enable_dcplb();
|
_enable_dcplb();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -288,10 +249,10 @@ static noinline int icplb_miss(unsigned int cpu)
|
|||||||
icplb_tbl[cpu][idx].addr = addr;
|
icplb_tbl[cpu][idx].addr = addr;
|
||||||
icplb_tbl[cpu][idx].data = i_data;
|
icplb_tbl[cpu][idx].data = i_data;
|
||||||
|
|
||||||
disable_icplb();
|
_disable_icplb();
|
||||||
bfin_write32(ICPLB_DATA0 + idx * 4, i_data);
|
bfin_write32(ICPLB_DATA0 + idx * 4, i_data);
|
||||||
bfin_write32(ICPLB_ADDR0 + idx * 4, addr);
|
bfin_write32(ICPLB_ADDR0 + idx * 4, addr);
|
||||||
enable_icplb();
|
_enable_icplb();
|
||||||
|
|
||||||
return 0;
|
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 cplb_hdr(int seqstat, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int cause = seqstat & 0x3f;
|
int cause = seqstat & 0x3f;
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = raw_smp_processor_id();
|
||||||
switch (cause) {
|
switch (cause) {
|
||||||
case 0x23:
|
case 0x23:
|
||||||
return dcplb_protection_fault(cpu);
|
return dcplb_protection_fault(cpu);
|
||||||
@ -340,19 +301,19 @@ void flush_switched_cplbs(unsigned int cpu)
|
|||||||
nr_cplb_flush[cpu]++;
|
nr_cplb_flush[cpu]++;
|
||||||
|
|
||||||
local_irq_save_hw(flags);
|
local_irq_save_hw(flags);
|
||||||
disable_icplb();
|
_disable_icplb();
|
||||||
for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
|
for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
|
||||||
icplb_tbl[cpu][i].data = 0;
|
icplb_tbl[cpu][i].data = 0;
|
||||||
bfin_write32(ICPLB_DATA0 + i * 4, 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++) {
|
for (i = first_switched_dcplb; i < MAX_CPLBS; i++) {
|
||||||
dcplb_tbl[cpu][i].data = 0;
|
dcplb_tbl[cpu][i].data = 0;
|
||||||
bfin_write32(DCPLB_DATA0 + i * 4, 0);
|
bfin_write32(DCPLB_DATA0 + i * 4, 0);
|
||||||
}
|
}
|
||||||
enable_dcplb();
|
_enable_dcplb();
|
||||||
local_irq_restore_hw(flags);
|
local_irq_restore_hw(flags);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -385,7 +346,7 @@ void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
disable_dcplb();
|
_disable_dcplb();
|
||||||
for (i = first_mask_dcplb; i < first_switched_dcplb; i++) {
|
for (i = first_mask_dcplb; i < first_switched_dcplb; i++) {
|
||||||
dcplb_tbl[cpu][i].addr = addr;
|
dcplb_tbl[cpu][i].addr = addr;
|
||||||
dcplb_tbl[cpu][i].data = d_data;
|
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);
|
bfin_write32(DCPLB_ADDR0 + i * 4, addr);
|
||||||
addr += PAGE_SIZE;
|
addr += PAGE_SIZE;
|
||||||
}
|
}
|
||||||
enable_dcplb();
|
_enable_dcplb();
|
||||||
local_irq_restore_hw(flags);
|
local_irq_restore_hw(flags);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# arch/blackfin/kernel/cplb-nompu/Makefile
|
# 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 \
|
CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \
|
||||||
-ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \
|
-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;
|
int first_switched_dcplb PDT_ATTR;
|
||||||
|
|
||||||
struct cplb_boundary dcplb_bounds[9] 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 icplb_nr_bounds PDT_ATTR;
|
||||||
int dcplb_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 ?
|
icplb_bounds[i_i++].data = (reserved_mem_icache_on ?
|
||||||
SDRAM_IGENERIC : SDRAM_INON_CHBL);
|
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. */
|
/* Addressing hole up to BootROM. */
|
||||||
icplb_bounds[i_i].eaddr = BOOT_ROM_START;
|
icplb_bounds[i_i].eaddr = BOOT_ROM_START;
|
||||||
icplb_bounds[i_i++].data = 0;
|
icplb_bounds[i_i++].data = 0;
|
||||||
/* BootROM -- largest one should be less than 1 meg. */
|
/* BootROM -- largest one should be less than 1 meg. */
|
||||||
icplb_bounds[i_i].eaddr = BOOT_ROM_START + (1 * 1024 * 1024);
|
icplb_bounds[i_i].eaddr = BOOT_ROM_START + (1 * 1024 * 1024);
|
||||||
icplb_bounds[i_i++].data = SDRAM_IGENERIC;
|
icplb_bounds[i_i++].data = SDRAM_IGENERIC;
|
||||||
|
|
||||||
if (L2_LENGTH) {
|
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].eaddr = L2_START;
|
||||||
icplb_bounds[i_i++].data = 0;
|
icplb_bounds[i_i++].data = 0;
|
||||||
/* L2 SRAM. */
|
/* L2 SRAM. */
|
||||||
|
@ -48,36 +48,13 @@ int nr_cplb_flush[NR_CPUS], nr_dcplb_prot[NR_CPUS];
|
|||||||
#define MGR_ATTR
|
#define MGR_ATTR
|
||||||
#endif
|
#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,
|
static inline void write_dcplb_data(int cpu, int idx, unsigned long data,
|
||||||
unsigned long addr)
|
unsigned long addr)
|
||||||
{
|
{
|
||||||
unsigned long ctrl = bfin_read_DMEM_CONTROL();
|
_disable_dcplb();
|
||||||
bfin_write_DMEM_CONTROL_SSYNC(ctrl & ~ENDCPLB);
|
|
||||||
bfin_write32(DCPLB_DATA0 + idx * 4, data);
|
bfin_write32(DCPLB_DATA0 + idx * 4, data);
|
||||||
bfin_write32(DCPLB_ADDR0 + idx * 4, addr);
|
bfin_write32(DCPLB_ADDR0 + idx * 4, addr);
|
||||||
bfin_write_DMEM_CONTROL_SSYNC(ctrl);
|
_enable_dcplb();
|
||||||
|
|
||||||
#ifdef CONFIG_CPLB_INFO
|
#ifdef CONFIG_CPLB_INFO
|
||||||
dcplb_tbl[cpu][idx].addr = addr;
|
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,
|
static inline void write_icplb_data(int cpu, int idx, unsigned long data,
|
||||||
unsigned long addr)
|
unsigned long addr)
|
||||||
{
|
{
|
||||||
unsigned long ctrl = bfin_read_IMEM_CONTROL();
|
_disable_icplb();
|
||||||
|
|
||||||
bfin_write_IMEM_CONTROL_SSYNC(ctrl & ~ENICPLB);
|
|
||||||
bfin_write32(ICPLB_DATA0 + idx * 4, data);
|
bfin_write32(ICPLB_DATA0 + idx * 4, data);
|
||||||
bfin_write32(ICPLB_ADDR0 + idx * 4, addr);
|
bfin_write32(ICPLB_ADDR0 + idx * 4, addr);
|
||||||
bfin_write_IMEM_CONTROL_SSYNC(ctrl);
|
_enable_icplb();
|
||||||
|
|
||||||
#ifdef CONFIG_CPLB_INFO
|
#ifdef CONFIG_CPLB_INFO
|
||||||
icplb_tbl[cpu][idx].addr = addr;
|
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)
|
MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int cause = seqstat & 0x3f;
|
int cause = seqstat & 0x3f;
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = raw_smp_processor_id();
|
||||||
switch (cause) {
|
switch (cause) {
|
||||||
case VEC_CPLB_I_M:
|
case VEC_CPLB_I_M:
|
||||||
return icplb_miss(cpu);
|
return icplb_miss(cpu);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
#include <asm/blackfin.h>
|
#include <asm/blackfin.h>
|
||||||
#include <asm/irq_handler.h>
|
#include <asm/irq_handler.h>
|
||||||
#include <asm/early_printk.h>
|
#include <asm/early_printk.h>
|
||||||
@ -181,6 +182,22 @@ asmlinkage void __init init_early_exception_vectors(void)
|
|||||||
u32 evt;
|
u32 evt;
|
||||||
SSYNC();
|
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:
|
/* cannot program in software:
|
||||||
* evt0 - emulation (jtag)
|
* evt0 - emulation (jtag)
|
||||||
* evt1 - reset
|
* 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)
|
asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)
|
||||||
{
|
{
|
||||||
/* This can happen before the uart is initialized, so initialize
|
/* 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())
|
if (likely(early_console == NULL) && CPUID == bfin_cpuid())
|
||||||
setup_early_printk(DEFAULT_EARLY_PORT);
|
setup_early_printk(DEFAULT_EARLY_PORT);
|
||||||
|
|
||||||
|
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");
|
printk(KERN_EMERG "Early panic\n");
|
||||||
dump_bfin_mem(fp);
|
|
||||||
show_regs(fp);
|
show_regs(fp);
|
||||||
dump_bfin_trace_buffer();
|
dump_bfin_trace_buffer();
|
||||||
|
}
|
||||||
|
|
||||||
panic("Died early");
|
panic("Died early");
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,28 @@
|
|||||||
|
|
||||||
ENTRY(_ret_from_fork)
|
ENTRY(_ret_from_fork)
|
||||||
#ifdef CONFIG_IPIPE
|
#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 */
|
#endif /* CONFIG_IPIPE */
|
||||||
SP += -12;
|
SP += -12;
|
||||||
call _schedule_tail;
|
call _schedule_tail;
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
* only one we can blow away. With pointer registers, we have P0-P2.
|
* 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
|
* 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
|
* function. And since GCC pushed the previous RETS for us, the previous
|
||||||
* will be waiting there. mmmm pie.
|
* function will be waiting there. mmmm pie.
|
||||||
*/
|
*/
|
||||||
ENTRY(__mcount)
|
ENTRY(__mcount)
|
||||||
/* save third function arg early so we can do testing below */
|
/* save third function arg early so we can do testing below */
|
||||||
@ -70,14 +70,14 @@ ENTRY(__mcount)
|
|||||||
/* setup the tracer function */
|
/* setup the tracer function */
|
||||||
p0 = r3;
|
p0 = r3;
|
||||||
|
|
||||||
/* tracer(ulong frompc, ulong selfpc):
|
/* function_trace_call(unsigned long ip, unsigned long parent_ip):
|
||||||
* frompc: the pc that did the call to ...
|
* ip: this point was called by ...
|
||||||
* selfpc: ... this location
|
* parent_ip: ... this function
|
||||||
* the selfpc itself will need adjusting for the mcount call
|
* the ip itself will need adjusting for the mcount call
|
||||||
*/
|
*/
|
||||||
r1 = rets;
|
r0 = rets;
|
||||||
r0 = [fp + 4];
|
r1 = [sp + 16]; /* skip the 4 local regs on stack */
|
||||||
r1 += -MCOUNT_INSN_SIZE;
|
r0 += -MCOUNT_INSN_SIZE;
|
||||||
|
|
||||||
/* call the tracer */
|
/* call the tracer */
|
||||||
call (p0);
|
call (p0);
|
||||||
@ -106,9 +106,10 @@ ENTRY(_ftrace_graph_caller)
|
|||||||
[--sp] = r1;
|
[--sp] = r1;
|
||||||
[--sp] = rets;
|
[--sp] = rets;
|
||||||
|
|
||||||
r0 = fp;
|
/* prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) */
|
||||||
|
r0 = sp;
|
||||||
r1 = rets;
|
r1 = rets;
|
||||||
r0 += 4;
|
r0 += 16; /* skip the 4 local regs on stack */
|
||||||
r1 += -MCOUNT_INSN_SIZE;
|
r1 += -MCOUNT_INSN_SIZE;
|
||||||
call _prepare_ftrace_return;
|
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)))
|
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
||||||
return;
|
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;
|
return;
|
||||||
|
|
||||||
trace.func = self_addr;
|
trace.func = self_addr;
|
||||||
|
@ -30,10 +30,10 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <asm/unistd.h>
|
#include <linux/unistd.h>
|
||||||
|
#include <linux/io.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/io.h>
|
|
||||||
|
|
||||||
DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
|
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_percpu_domain_data *p = ipipe_root_cpudom_ptr();
|
||||||
struct ipipe_domain *this_domain, *next_domain;
|
struct ipipe_domain *this_domain, *next_domain;
|
||||||
struct list_head *head, *pos;
|
struct list_head *head, *pos;
|
||||||
|
struct ipipe_irqdesc *idesc;
|
||||||
int m_ack, s = -1;
|
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);
|
m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR);
|
||||||
this_domain = __ipipe_current_domain;
|
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;
|
head = &this_domain->p_link;
|
||||||
else {
|
else {
|
||||||
head = __ipipe_pipeline.next;
|
head = __ipipe_pipeline.next;
|
||||||
next_domain = list_entry(head, struct ipipe_domain, p_link);
|
next_domain = list_entry(head, struct ipipe_domain, p_link);
|
||||||
if (likely(test_bit(IPIPE_WIRED_FLAG, &next_domain->irqs[irq].control))) {
|
idesc = &next_domain->irqs[irq];
|
||||||
if (!m_ack && next_domain->irqs[irq].acknowledge != NULL)
|
if (likely(test_bit(IPIPE_WIRED_FLAG, &idesc->control))) {
|
||||||
next_domain->irqs[irq].acknowledge(irq, irq_to_desc(irq));
|
if (!m_ack && idesc->acknowledge != NULL)
|
||||||
|
idesc->acknowledge(irq, irq_to_desc(irq));
|
||||||
if (test_bit(IPIPE_SYNCDEFER_FLAG, &p->status))
|
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);
|
__ipipe_dispatch_wired(next_domain, irq);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -121,14 +125,15 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
|
|||||||
pos = head;
|
pos = head;
|
||||||
while (pos != &__ipipe_pipeline) {
|
while (pos != &__ipipe_pipeline) {
|
||||||
next_domain = list_entry(pos, struct ipipe_domain, p_link);
|
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);
|
__ipipe_set_irq_pending(next_domain, irq);
|
||||||
if (!m_ack && next_domain->irqs[irq].acknowledge != NULL) {
|
if (!m_ack && idesc->acknowledge != NULL) {
|
||||||
next_domain->irqs[irq].acknowledge(irq, irq_to_desc(irq));
|
idesc->acknowledge(irq, irq_to_desc(irq));
|
||||||
m_ack = 1;
|
m_ack = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!test_bit(IPIPE_PASS_FLAG, &next_domain->irqs[irq].control))
|
if (!test_bit(IPIPE_PASS_FLAG, &idesc->control))
|
||||||
break;
|
break;
|
||||||
pos = next_domain->p_link.next;
|
pos = next_domain->p_link.next;
|
||||||
}
|
}
|
||||||
@ -159,11 +164,6 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
|
|||||||
__clear_bit(IPIPE_STALL_FLAG, &p->status);
|
__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)
|
void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc = irq_to_desc(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);
|
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)
|
int __ipipe_syscall_root(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct ipipe_percpu_domain_data *p;
|
struct ipipe_percpu_domain_data *p;
|
||||||
@ -333,12 +309,29 @@ asmlinkage void __ipipe_sync_root(void)
|
|||||||
|
|
||||||
void ___ipipe_sync_pipeline(unsigned long syncmask)
|
void ___ipipe_sync_pipeline(unsigned long syncmask)
|
||||||
{
|
{
|
||||||
if (__ipipe_root_domain_p) {
|
if (__ipipe_root_domain_p &&
|
||||||
if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
|
test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
__ipipe_sync_stage(syncmask);
|
__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)
|
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;
|
count = z;
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) "module %s: " fmt
|
||||||
|
|
||||||
#include <linux/moduleloader.h>
|
#include <linux/moduleloader.h>
|
||||||
#include <linux/elf.h>
|
#include <linux/elf.h>
|
||||||
@ -36,6 +37,7 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <asm/dma.h>
|
#include <asm/dma.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
void *module_alloc(unsigned long size)
|
void *module_alloc(unsigned long size)
|
||||||
{
|
{
|
||||||
@ -63,126 +65,119 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
|
|||||||
* NOTE: this breaks the semantic of mod->arch structure.
|
* NOTE: this breaks the semantic of mod->arch structure.
|
||||||
*/
|
*/
|
||||||
Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
|
Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
|
||||||
void *dest = NULL;
|
void *dest;
|
||||||
|
|
||||||
for (s = sechdrs; s < sechdrs_end; ++s) {
|
for (s = sechdrs; s < sechdrs_end; ++s) {
|
||||||
if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) ||
|
const char *shname = secstrings + s->sh_name;
|
||||||
((strcmp(".text", secstrings + s->sh_name) == 0) &&
|
|
||||||
(hdr->e_flags & EF_BFIN_CODE_IN_L1) && (s->sh_size > 0))) {
|
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);
|
dest = l1_inst_sram_alloc(s->sh_size);
|
||||||
mod->arch.text_l1 = dest;
|
mod->arch.text_l1 = dest;
|
||||||
if (dest == NULL) {
|
if (dest == NULL) {
|
||||||
printk(KERN_ERR
|
pr_err("L1 inst memory allocation failed\n",
|
||||||
"module %s: L1 instruction memory allocation failed\n",
|
|
||||||
mod->name);
|
mod->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dma_memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
dma_memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
||||||
s->sh_flags &= ~SHF_ALLOC;
|
|
||||||
s->sh_addr = (unsigned long)dest;
|
} else if (!strcmp(".l1.data", shname) ||
|
||||||
}
|
(!strcmp(".data", shname) &&
|
||||||
if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) ||
|
(hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
|
||||||
((strcmp(".data", 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);
|
dest = l1_data_sram_alloc(s->sh_size);
|
||||||
mod->arch.data_a_l1 = dest;
|
mod->arch.data_a_l1 = dest;
|
||||||
if (dest == NULL) {
|
if (dest == NULL) {
|
||||||
printk(KERN_ERR
|
pr_err("L1 data memory allocation failed\n",
|
||||||
"module %s: L1 data memory allocation failed\n",
|
|
||||||
mod->name);
|
mod->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
||||||
s->sh_flags &= ~SHF_ALLOC;
|
|
||||||
s->sh_addr = (unsigned long)dest;
|
} else if (!strcmp(".l1.bss", shname) ||
|
||||||
}
|
(!strcmp(".bss", shname) &&
|
||||||
if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 ||
|
(hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
|
||||||
((strcmp(".bss", secstrings + s->sh_name) == 0) &&
|
|
||||||
(hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) {
|
dest = l1_data_sram_zalloc(s->sh_size);
|
||||||
dest = l1_data_sram_alloc(s->sh_size);
|
|
||||||
mod->arch.bss_a_l1 = dest;
|
mod->arch.bss_a_l1 = dest;
|
||||||
if (dest == NULL) {
|
if (dest == NULL) {
|
||||||
printk(KERN_ERR
|
pr_err("L1 data memory allocation failed\n",
|
||||||
"module %s: L1 data memory allocation failed\n",
|
|
||||||
mod->name);
|
mod->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(dest, 0, s->sh_size);
|
|
||||||
s->sh_flags &= ~SHF_ALLOC;
|
} else if (!strcmp(".l1.data.B", shname)) {
|
||||||
s->sh_addr = (unsigned long)dest;
|
|
||||||
}
|
|
||||||
if (strcmp(".l1.data.B", secstrings + s->sh_name) == 0) {
|
|
||||||
dest = l1_data_B_sram_alloc(s->sh_size);
|
dest = l1_data_B_sram_alloc(s->sh_size);
|
||||||
mod->arch.data_b_l1 = dest;
|
mod->arch.data_b_l1 = dest;
|
||||||
if (dest == NULL) {
|
if (dest == NULL) {
|
||||||
printk(KERN_ERR
|
pr_err("L1 data memory allocation failed\n",
|
||||||
"module %s: L1 data memory allocation failed\n",
|
|
||||||
mod->name);
|
mod->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
||||||
s->sh_flags &= ~SHF_ALLOC;
|
|
||||||
s->sh_addr = (unsigned long)dest;
|
} else if (!strcmp(".l1.bss.B", shname)) {
|
||||||
}
|
|
||||||
if (strcmp(".l1.bss.B", secstrings + s->sh_name) == 0) {
|
|
||||||
dest = l1_data_B_sram_alloc(s->sh_size);
|
dest = l1_data_B_sram_alloc(s->sh_size);
|
||||||
mod->arch.bss_b_l1 = dest;
|
mod->arch.bss_b_l1 = dest;
|
||||||
if (dest == NULL) {
|
if (dest == NULL) {
|
||||||
printk(KERN_ERR
|
pr_err("L1 data memory allocation failed\n",
|
||||||
"module %s: L1 data memory allocation failed\n",
|
|
||||||
mod->name);
|
mod->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(dest, 0, s->sh_size);
|
memset(dest, 0, s->sh_size);
|
||||||
s->sh_flags &= ~SHF_ALLOC;
|
|
||||||
s->sh_addr = (unsigned long)dest;
|
} else if (!strcmp(".l2.text", shname) ||
|
||||||
}
|
(!strcmp(".text", shname) &&
|
||||||
if ((strcmp(".l2.text", secstrings + s->sh_name) == 0) ||
|
(hdr->e_flags & EF_BFIN_CODE_IN_L2))) {
|
||||||
((strcmp(".text", secstrings + s->sh_name) == 0) &&
|
|
||||||
(hdr->e_flags & EF_BFIN_CODE_IN_L2) && (s->sh_size > 0))) {
|
|
||||||
dest = l2_sram_alloc(s->sh_size);
|
dest = l2_sram_alloc(s->sh_size);
|
||||||
mod->arch.text_l2 = dest;
|
mod->arch.text_l2 = dest;
|
||||||
if (dest == NULL) {
|
if (dest == NULL) {
|
||||||
printk(KERN_ERR
|
pr_err("L2 SRAM allocation failed\n",
|
||||||
"module %s: L2 SRAM allocation failed\n",
|
|
||||||
mod->name);
|
mod->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
||||||
s->sh_flags &= ~SHF_ALLOC;
|
|
||||||
s->sh_addr = (unsigned long)dest;
|
} else if (!strcmp(".l2.data", shname) ||
|
||||||
}
|
(!strcmp(".data", shname) &&
|
||||||
if ((strcmp(".l2.data", secstrings + s->sh_name) == 0) ||
|
(hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
|
||||||
((strcmp(".data", secstrings + s->sh_name) == 0) &&
|
|
||||||
(hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
|
|
||||||
dest = l2_sram_alloc(s->sh_size);
|
dest = l2_sram_alloc(s->sh_size);
|
||||||
mod->arch.data_l2 = dest;
|
mod->arch.data_l2 = dest;
|
||||||
if (dest == NULL) {
|
if (dest == NULL) {
|
||||||
printk(KERN_ERR
|
pr_err("L2 SRAM allocation failed\n",
|
||||||
"module %s: L2 SRAM allocation failed\n",
|
|
||||||
mod->name);
|
mod->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
memcpy(dest, (void *)s->sh_addr, s->sh_size);
|
||||||
s->sh_flags &= ~SHF_ALLOC;
|
|
||||||
s->sh_addr = (unsigned long)dest;
|
} else if (!strcmp(".l2.bss", shname) ||
|
||||||
}
|
(!strcmp(".bss", shname) &&
|
||||||
if (strcmp(".l2.bss", secstrings + s->sh_name) == 0 ||
|
(hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
|
||||||
((strcmp(".bss", secstrings + s->sh_name) == 0) &&
|
|
||||||
(hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
|
dest = l2_sram_zalloc(s->sh_size);
|
||||||
dest = l2_sram_alloc(s->sh_size);
|
|
||||||
mod->arch.bss_l2 = dest;
|
mod->arch.bss_l2 = dest;
|
||||||
if (dest == NULL) {
|
if (dest == NULL) {
|
||||||
printk(KERN_ERR
|
pr_err("L2 SRAM allocation failed\n",
|
||||||
"module %s: L2 SRAM allocation failed\n",
|
|
||||||
mod->name);
|
mod->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(dest, 0, s->sh_size);
|
|
||||||
|
} else
|
||||||
|
continue;
|
||||||
|
|
||||||
s->sh_flags &= ~SHF_ALLOC;
|
s->sh_flags &= ~SHF_ALLOC;
|
||||||
s->sh_addr = (unsigned long)dest;
|
s->sh_addr = (unsigned long)dest;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +185,7 @@ int
|
|||||||
apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
|
apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
|
||||||
unsigned int symindex, unsigned int relsec, struct module *me)
|
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;
|
return -ENOEXEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,104 +205,81 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
|
|||||||
struct module *mod)
|
struct module *mod)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned short tmp;
|
|
||||||
Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
|
Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym;
|
||||||
uint32_t *location32;
|
unsigned long location, value, size;
|
||||||
uint16_t *location16;
|
|
||||||
uint32_t value;
|
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++) {
|
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
|
||||||
/* This is where to make the change */
|
/* This is where to make the change */
|
||||||
location16 =
|
location = sechdrs[sechdrs[relsec].sh_info].sh_addr +
|
||||||
(uint16_t *) (sechdrs[sechdrs[relsec].sh_info].sh_addr +
|
rel[i].r_offset;
|
||||||
rel[i].r_offset);
|
|
||||||
location32 = (uint32_t *) location16;
|
|
||||||
/* This is the symbol it is referring to. Note that all
|
/* This is the symbol it is referring to. Note that all
|
||||||
undefined symbols have been resolved. */
|
undefined symbols have been resolved. */
|
||||||
sym = (Elf32_Sym *) sechdrs[symindex].sh_addr
|
sym = (Elf32_Sym *) sechdrs[symindex].sh_addr
|
||||||
+ ELF32_R_SYM(rel[i].r_info);
|
+ ELF32_R_SYM(rel[i].r_info);
|
||||||
value = sym->st_value;
|
value = sym->st_value;
|
||||||
value += rel[i].r_addend;
|
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
|
#ifdef CONFIG_SMP
|
||||||
if ((unsigned long)location16 >= COREB_L1_DATA_A_START) {
|
if (location >= COREB_L1_DATA_A_START) {
|
||||||
printk(KERN_ERR "module %s: cannot relocate in L1: %u (SMP kernel)",
|
pr_err("cannot relocate in L1: %u (SMP kernel)",
|
||||||
mod->name, ELF32_R_TYPE(rel[i].r_info));
|
mod->name, ELF32_R_TYPE(rel[i].r_info));
|
||||||
return -ENOEXEC;
|
return -ENOEXEC;
|
||||||
}
|
}
|
||||||
#endif
|
#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)) {
|
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:
|
||||||
case R_BFIN_PCREL24_JUMP_L:
|
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:
|
||||||
case R_BFIN_PCREL12_JUMP_S:
|
case R_BFIN_PCREL12_JUMP_S:
|
||||||
value -= (uint32_t) location32;
|
|
||||||
value >>= 1;
|
|
||||||
*location16 = (value & 0xfff);
|
|
||||||
break;
|
|
||||||
case R_BFIN_PCREL10:
|
case R_BFIN_PCREL10:
|
||||||
value -= (uint32_t) location32;
|
pr_err("unsupported relocation: %u (no -mlong-calls?)\n",
|
||||||
value >>= 1;
|
mod->name, ELF32_R_TYPE(rel[i].r_info));
|
||||||
*location16 = (value & 0x3ff);
|
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;
|
break;
|
||||||
case R_BFIN_LUIMM16:
|
case BFIN_MEM_ACCESS_DMA:
|
||||||
pr_debug("before %x after %x\n", *location16,
|
dma_memcpy((void *)location, &value, size);
|
||||||
(value & 0xffff));
|
|
||||||
tmp = (value & 0xffff);
|
|
||||||
if ((unsigned long)location16 >= L1_CODE_START) {
|
|
||||||
dma_memcpy(location16, &tmp, 2);
|
|
||||||
} else
|
|
||||||
*location16 = tmp;
|
|
||||||
break;
|
break;
|
||||||
case R_BFIN_HUIMM16:
|
case BFIN_MEM_ACCESS_ITEST:
|
||||||
pr_debug("before %x after %x\n", *location16,
|
isram_memcpy((void *)location, &value, size);
|
||||||
((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;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
|
pr_err("invalid relocation for %#lx\n",
|
||||||
mod->name, ELF32_R_TYPE(rel[i].r_info));
|
mod->name, location);
|
||||||
return -ENOEXEC;
|
return -ENOEXEC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,22 +304,28 @@ module_finalize(const Elf_Ehdr * hdr,
|
|||||||
for (i = 1; i < hdr->e_shnum; i++) {
|
for (i = 1; i < hdr->e_shnum; i++) {
|
||||||
const char *strtab = (char *)sechdrs[strindex].sh_addr;
|
const char *strtab = (char *)sechdrs[strindex].sh_addr;
|
||||||
unsigned int info = sechdrs[i].sh_info;
|
unsigned int info = sechdrs[i].sh_info;
|
||||||
|
const char *shname = secstrings + sechdrs[i].sh_name;
|
||||||
|
|
||||||
/* Not a valid relocation section? */
|
/* Not a valid relocation section? */
|
||||||
if (info >= hdr->e_shnum)
|
if (info >= hdr->e_shnum)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((sechdrs[i].sh_type == SHT_RELA) &&
|
/* Only support RELA relocation types */
|
||||||
((strcmp(".rela.l2.text", secstrings + sechdrs[i].sh_name) == 0) ||
|
if (sechdrs[i].sh_type != SHT_RELA)
|
||||||
(strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
|
continue;
|
||||||
((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
|
|
||||||
(hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) {
|
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,
|
err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
|
||||||
symindex, i, mod);
|
symindex, i, mod);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return -ENOEXEC;
|
return -ENOEXEC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,24 +282,18 @@ void finish_atomic_sections (struct pt_regs *regs)
|
|||||||
{
|
{
|
||||||
int __user *up0 = (int __user *)regs->p0;
|
int __user *up0 = (int __user *)regs->p0;
|
||||||
|
|
||||||
if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (regs->pc) {
|
switch (regs->pc) {
|
||||||
case ATOMIC_XCHG32 + 2:
|
case ATOMIC_XCHG32 + 2:
|
||||||
put_user(regs->r1, up0);
|
put_user(regs->r1, up0);
|
||||||
regs->pc += 2;
|
regs->pc = ATOMIC_XCHG32 + 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ATOMIC_CAS32 + 2:
|
case ATOMIC_CAS32 + 2:
|
||||||
case ATOMIC_CAS32 + 4:
|
case ATOMIC_CAS32 + 4:
|
||||||
if (regs->r0 == regs->r1)
|
if (regs->r0 == regs->r1)
|
||||||
put_user(regs->r2, up0);
|
|
||||||
regs->pc = ATOMIC_CAS32 + 8;
|
|
||||||
break;
|
|
||||||
case ATOMIC_CAS32 + 6:
|
case ATOMIC_CAS32 + 6:
|
||||||
put_user(regs->r2, up0);
|
put_user(regs->r2, up0);
|
||||||
regs->pc += 2;
|
regs->pc = ATOMIC_CAS32 + 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ATOMIC_ADD32 + 2:
|
case ATOMIC_ADD32 + 2:
|
||||||
|
@ -206,6 +206,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
unsigned long __user *datap = (unsigned long __user *)data;
|
unsigned long __user *datap = (unsigned long __user *)data;
|
||||||
|
void *paddr = (void *)addr;
|
||||||
|
|
||||||
switch (request) {
|
switch (request) {
|
||||||
/* when I and D space are separate, these will need to be fixed. */
|
/* when I and D space are separate, these will need to be fixed. */
|
||||||
@ -215,41 +216,48 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||||||
case PTRACE_PEEKTEXT: /* read word at location addr. */
|
case PTRACE_PEEKTEXT: /* read word at location addr. */
|
||||||
{
|
{
|
||||||
unsigned long tmp = 0;
|
unsigned long tmp = 0;
|
||||||
int copied;
|
int copied = 0, to_copy = sizeof(tmp);
|
||||||
|
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %ld\n", addr, sizeof(data));
|
pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %i\n", addr, to_copy);
|
||||||
if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
|
if (is_user_addr_valid(child, addr, to_copy) < 0)
|
||||||
break;
|
break;
|
||||||
pr_debug("ptrace: user address is valid\n");
|
pr_debug("ptrace: user address is valid\n");
|
||||||
|
|
||||||
if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
|
switch (bfin_mem_access_type(addr, to_copy)) {
|
||||||
&& addr + sizeof(tmp) <= get_l1_code_start() + L1_CODE_LENGTH) {
|
case BFIN_MEM_ACCESS_CORE:
|
||||||
safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp));
|
case BFIN_MEM_ACCESS_CORE_ONLY:
|
||||||
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
|
|
||||||
copied = access_process_vm(child, addr, &tmp,
|
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);
|
pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp);
|
||||||
if (copied != sizeof(tmp))
|
if (copied == to_copy)
|
||||||
break;
|
|
||||||
ret = put_user(tmp, datap);
|
ret = put_user(tmp, datap);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -277,9 +285,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||||||
tmp = child->mm->start_data;
|
tmp = child->mm->start_data;
|
||||||
#ifdef CONFIG_BINFMT_ELF_FDPIC
|
#ifdef CONFIG_BINFMT_ELF_FDPIC
|
||||||
} else if (addr == (sizeof(struct pt_regs) + 12)) {
|
} 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)) {
|
} else if (addr == (sizeof(struct pt_regs) + 16)) {
|
||||||
tmp = child->mm->context.interp_fdpic_loadmap;
|
goto case_PTRACE_GETFDPIC_INTERP;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
tmp = get_reg(child, addr);
|
tmp = get_reg(child, addr);
|
||||||
@ -288,48 +296,77 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||||||
break;
|
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. */
|
/* when I and D space are separate, this will have to be fixed. */
|
||||||
case PTRACE_POKEDATA:
|
case PTRACE_POKEDATA:
|
||||||
pr_debug("ptrace: PTRACE_PEEKDATA\n");
|
pr_debug("ptrace: PTRACE_PEEKDATA\n");
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case PTRACE_POKETEXT: /* write the word at location addr. */
|
case PTRACE_POKETEXT: /* write the word at location addr. */
|
||||||
{
|
{
|
||||||
int copied;
|
int copied = 0, to_copy = sizeof(data);
|
||||||
|
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
pr_debug("ptrace: POKETEXT at addr 0x%08lx + %ld bytes %lx\n",
|
pr_debug("ptrace: POKETEXT at addr 0x%08lx + %i bytes %lx\n",
|
||||||
addr, sizeof(data), data);
|
addr, to_copy, data);
|
||||||
if (is_user_addr_valid(child, addr, sizeof(data)) < 0)
|
if (is_user_addr_valid(child, addr, to_copy) < 0)
|
||||||
break;
|
break;
|
||||||
pr_debug("ptrace: user address is valid\n");
|
pr_debug("ptrace: user address is valid\n");
|
||||||
|
|
||||||
if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
|
switch (bfin_mem_access_type(addr, to_copy)) {
|
||||||
&& addr + sizeof(data) <= get_l1_code_start() + L1_CODE_LENGTH) {
|
case BFIN_MEM_ACCESS_CORE:
|
||||||
safe_dma_memcpy ((void *)(addr), &data, sizeof(data));
|
case BFIN_MEM_ACCESS_CORE_ONLY:
|
||||||
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
|
|
||||||
copied = access_process_vm(child, addr, &data,
|
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);
|
pr_debug("ptrace: copied size %d\n", copied);
|
||||||
if (copied != sizeof(data))
|
if (copied == to_copy)
|
||||||
break;
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ void __cpuinit bfin_setup_caches(unsigned int cpu)
|
|||||||
/*
|
/*
|
||||||
* In cache coherence emulation mode, we need to have the
|
* In cache coherence emulation mode, we need to have the
|
||||||
* D-cache enabled before running any atomic operation which
|
* 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.
|
* So printk's are deferred until then.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_BFIN_ICACHE
|
#ifdef CONFIG_BFIN_ICACHE
|
||||||
@ -187,6 +187,8 @@ void __init bfin_relocate_l1_mem(void)
|
|||||||
unsigned long l1_data_b_length;
|
unsigned long l1_data_b_length;
|
||||||
unsigned long l2_length;
|
unsigned long l2_length;
|
||||||
|
|
||||||
|
early_shadow_stamp();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* due to the ALIGN(4) in the arch/blackfin/kernel/vmlinux.lds.S
|
* 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,
|
* 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
|
#ifdef CONFIG_MTD_UCLINUX
|
||||||
unsigned long mtd_phys = 0;
|
unsigned long mtd_phys = 0;
|
||||||
#endif
|
#endif
|
||||||
|
unsigned long max_mem;
|
||||||
|
|
||||||
_rambase = (unsigned long)_stext;
|
_rambase = (unsigned long)_stext;
|
||||||
_ramstart = (unsigned long)_end;
|
_ramstart = (unsigned long)_end;
|
||||||
@ -520,7 +523,22 @@ static __init void memory_setup(void)
|
|||||||
panic("DMA region exceeds memory limit: %lu.",
|
panic("DMA region exceeds memory limit: %lu.",
|
||||||
_ramend - _ramstart);
|
_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
|
#ifdef CONFIG_MPU
|
||||||
/* Round up to multiple of 4MB */
|
/* Round up to multiple of 4MB */
|
||||||
@ -549,22 +567,16 @@ static __init void memory_setup(void)
|
|||||||
|
|
||||||
# if defined(CONFIG_ROMFS_FS)
|
# if defined(CONFIG_ROMFS_FS)
|
||||||
if (((unsigned long *)mtd_phys)[0] == ROMSB_WORD0
|
if (((unsigned long *)mtd_phys)[0] == ROMSB_WORD0
|
||||||
&& ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1)
|
&& ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1) {
|
||||||
mtd_size =
|
mtd_size =
|
||||||
PAGE_ALIGN(be32_to_cpu(((unsigned long *)mtd_phys)[2]));
|
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
|
/* ROM_FS is XIP, so if we found it, we need to limit memory */
|
||||||
* instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
|
if (memory_end > max_mem) {
|
||||||
* 05000263 - Hardware loop corrupted when taking an ICPLB exception
|
pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20);
|
||||||
*/
|
memory_end = max_mem;
|
||||||
# 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 */
|
|
||||||
# endif /* CONFIG_ROMFS_FS */
|
# endif /* CONFIG_ROMFS_FS */
|
||||||
|
|
||||||
/* Since the default MTD_UCLINUX has no magic number, we just blindly
|
/* 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 */
|
#endif /* CONFIG_MTD_UCLINUX */
|
||||||
|
|
||||||
#if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
|
/* We need lo limit memory, since everything could have a text section
|
||||||
/* Due to a Hardware Anomaly we need to limit the size of usable
|
* of userspace in it, and expose anomaly 05000263. If the anomaly
|
||||||
* instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
|
* doesn't exist, or we don't need to - then dont.
|
||||||
* 05000263 - Hardware loop corrupted when taking an ICPLB exception
|
|
||||||
*/
|
*/
|
||||||
#if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
|
if (memory_end > max_mem) {
|
||||||
if (memory_end >= 56 * 1024 * 1024)
|
pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20);
|
||||||
memory_end = 56 * 1024 * 1024;
|
memory_end = max_mem;
|
||||||
#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 */
|
|
||||||
|
|
||||||
#ifdef CONFIG_MPU
|
#ifdef CONFIG_MPU
|
||||||
page_mask_nelts = ((_ramend >> PAGE_SHIFT) + 31) / 32;
|
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);
|
sanitize_memmap(bfin_memmap.map, &bfin_memmap.nr_map);
|
||||||
print_memory_map("boot memmap");
|
print_memory_map("boot memmap");
|
||||||
|
|
||||||
/* intialize globals in linux/bootmem.h */
|
/* initialize globals in linux/bootmem.h */
|
||||||
find_min_max_pfn();
|
find_min_max_pfn();
|
||||||
/* pfn of the last usable page frame */
|
/* pfn of the last usable page frame */
|
||||||
if (max_pfn > memory_end >> PAGE_SHIFT)
|
if (max_pfn > memory_end >> PAGE_SHIFT)
|
||||||
@ -806,6 +812,8 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
{
|
{
|
||||||
unsigned long sclk, cclk;
|
unsigned long sclk, cclk;
|
||||||
|
|
||||||
|
enable_shadow_console();
|
||||||
|
|
||||||
/* Check to make sure we are running on the right processor */
|
/* Check to make sure we are running on the right processor */
|
||||||
if (unlikely(CPUID != bfin_cpuid()))
|
if (unlikely(CPUID != bfin_cpuid()))
|
||||||
printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n",
|
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
|
#ifdef __ARCH_SYNC_CORE_ICACHE
|
||||||
seq_printf(m, "SMP Icache Flushes\t: %lu\n\n", cpudata->icache_invld_count);
|
seq_printf(m, "SMP Icache Flushes\t: %lu\n\n", cpudata->icache_invld_count);
|
||||||
#endif
|
#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)
|
if (cpu_num != num_possible_cpus() - 1)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1346,6 +1303,7 @@ const struct seq_operations cpuinfo_op = {
|
|||||||
|
|
||||||
void __init cmdline_init(const char *r0)
|
void __init cmdline_init(const char *r0)
|
||||||
{
|
{
|
||||||
|
early_shadow_stamp();
|
||||||
if (r0)
|
if (r0)
|
||||||
strncpy(command_line, r0, COMMAND_LINE_SIZE);
|
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 = {
|
static struct clocksource bfin_cs_cycles = {
|
||||||
.name = "bfin_cs_cycles",
|
.name = "bfin_cs_cycles",
|
||||||
.rating = 350,
|
.rating = 400,
|
||||||
.read = bfin_read_cycles,
|
.read = bfin_read_cycles,
|
||||||
.mask = CLOCKSOURCE_MASK(64),
|
.mask = CLOCKSOURCE_MASK(64),
|
||||||
.shift = 22,
|
.shift = 22,
|
||||||
@ -115,7 +115,7 @@ static cycle_t bfin_read_gptimer0(void)
|
|||||||
|
|
||||||
static struct clocksource bfin_cs_gptimer0 = {
|
static struct clocksource bfin_cs_gptimer0 = {
|
||||||
.name = "bfin_cs_gptimer0",
|
.name = "bfin_cs_gptimer0",
|
||||||
.rating = 400,
|
.rating = 350,
|
||||||
.read = bfin_read_gptimer0,
|
.read = bfin_read_gptimer0,
|
||||||
.mask = CLOCKSOURCE_MASK(32),
|
.mask = CLOCKSOURCE_MASK(32),
|
||||||
.shift = 22,
|
.shift = 22,
|
||||||
|
@ -100,7 +100,11 @@ static void decode_address(char *buf, unsigned long address)
|
|||||||
char *modname;
|
char *modname;
|
||||||
char *delim = ":";
|
char *delim = ":";
|
||||||
char namebuf[128];
|
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 */
|
/* look up the address and see if we are in kernel space */
|
||||||
symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
|
symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
|
||||||
|
|
||||||
@ -108,23 +112,33 @@ static void decode_address(char *buf, unsigned long address)
|
|||||||
/* yeah! kernel space! */
|
/* yeah! kernel space! */
|
||||||
if (!modname)
|
if (!modname)
|
||||||
modname = delim = "";
|
modname = delim = "";
|
||||||
sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }",
|
sprintf(buf, "{ %s%s%s%s + 0x%lx }",
|
||||||
(void *)address, delim, modname, delim, symname,
|
delim, modname, delim, symname,
|
||||||
(unsigned long)offset);
|
(unsigned long)offset);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Problem in fixed code section? */
|
|
||||||
if (address >= FIXED_CODE_START && address < FIXED_CODE_END) {
|
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;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
|
} else if (address < CONFIG_BOOT_LOAD) {
|
||||||
/* Problem somewhere before the kernel start address */
|
/* Problem somewhere before the kernel start address */
|
||||||
if (address < CONFIG_BOOT_LOAD) {
|
strcat(buf, "/* Maybe null pointer? */");
|
||||||
sprintf(buf, "<0x%p> /* Maybe null pointer? */", (void *)address);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,18 +186,16 @@ static void decode_address(char *buf, unsigned long address)
|
|||||||
offset = (address - vma->vm_start) +
|
offset = (address - vma->vm_start) +
|
||||||
(vma->vm_pgoff << PAGE_SHIFT);
|
(vma->vm_pgoff << PAGE_SHIFT);
|
||||||
|
|
||||||
sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
|
sprintf(buf, "[ %s + 0x%lx ]", name, offset);
|
||||||
(void *)address, name, offset);
|
|
||||||
} else
|
} else
|
||||||
sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]",
|
sprintf(buf, "[ %s vma:0x%lx-0x%lx]",
|
||||||
(void *)address, name,
|
name, vma->vm_start, vma->vm_end);
|
||||||
vma->vm_start, vma->vm_end);
|
|
||||||
|
|
||||||
if (!in_atomic)
|
if (!in_atomic)
|
||||||
mmput(mm);
|
mmput(mm);
|
||||||
|
|
||||||
if (!strlen(buf))
|
if (buf[0] == '\0')
|
||||||
sprintf(buf, "<0x%p> [ %s ] dynamic memory", (void *)address, name);
|
sprintf(buf, "[ %s ] dynamic memory", name);
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -193,7 +205,7 @@ static void decode_address(char *buf, unsigned long address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* we were unable to find this address anywhere */
|
/* we were unable to find this address anywhere */
|
||||||
sprintf(buf, "<0x%p> /* kernel dynamic memory */", (void *)address);
|
sprintf(buf, "/* kernel dynamic memory */");
|
||||||
|
|
||||||
done:
|
done:
|
||||||
write_unlock_irqrestore(&tasklist_lock, flags);
|
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");
|
printk(KERN_EMERG "Double Fault\n");
|
||||||
#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
|
#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
|
||||||
if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) {
|
if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) {
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = raw_smp_processor_id();
|
||||||
char buf[150];
|
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",
|
printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
|
||||||
(unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf);
|
(unsigned int)cpu_pda[cpu].seqstat_doublefault & SEQSTAT_EXCAUSE, buf);
|
||||||
decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
|
decode_address(buf, cpu_pda[cpu].dcplb_doublefault_addr);
|
||||||
printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf);
|
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);
|
printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf);
|
||||||
|
|
||||||
decode_address(buf, fp->retx);
|
decode_address(buf, fp->retx);
|
||||||
@ -245,13 +257,13 @@ static int kernel_mode_regs(struct pt_regs *regs)
|
|||||||
return regs->ipend & 0xffc0;
|
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
|
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
|
||||||
int j;
|
int j;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = raw_smp_processor_id();
|
||||||
#endif
|
#endif
|
||||||
const char *strerror = NULL;
|
const char *strerror = NULL;
|
||||||
int sig = 0;
|
int sig = 0;
|
||||||
@ -267,11 +279,6 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
* double faults if the stack has become corrupt
|
* 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
|
/* trap_c() will be called for exceptions. During exceptions
|
||||||
* processing, the pc value should be set with retx value.
|
* processing, the pc value should be set with retx value.
|
||||||
* With this change we can cleanup some code in signal.c- TODO
|
* 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 */
|
/* 0x23 - Data CPLB protection violation, handled here */
|
||||||
case VEC_CPLB_VL:
|
case VEC_CPLB_VL:
|
||||||
info.si_code = ILL_CPLB_VI;
|
info.si_code = ILL_CPLB_VI;
|
||||||
sig = SIGBUS;
|
sig = SIGSEGV;
|
||||||
strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE);
|
strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
@ -904,7 +911,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
|
|||||||
frame_no = 0;
|
frame_no = 0;
|
||||||
|
|
||||||
for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
|
for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
|
||||||
addr <= endstack; addr++, i++) {
|
addr < endstack; addr++, i++) {
|
||||||
|
|
||||||
ret_addr = 0;
|
ret_addr = 0;
|
||||||
if (!j && i % 8 == 0)
|
if (!j && i % 8 == 0)
|
||||||
@ -949,6 +956,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(show_stack);
|
||||||
|
|
||||||
void dump_stack(void)
|
void dump_stack(void)
|
||||||
{
|
{
|
||||||
@ -1090,7 +1098,7 @@ void show_regs(struct pt_regs *fp)
|
|||||||
struct irqaction *action;
|
struct irqaction *action;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned long flags = 0;
|
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();
|
unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
|
||||||
|
|
||||||
verbose_printk(KERN_NOTICE "\n");
|
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 "%s", linux_banner);
|
||||||
|
|
||||||
verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n",
|
verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", print_tainted());
|
||||||
print_tainted());
|
verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx IMASK: %04lx SYSCFG: %04lx\n",
|
||||||
verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
|
(long)fp->seqstat, fp->ipend, cpu_pda[raw_smp_processor_id()].ex_imask, fp->syscfg);
|
||||||
(long)fp->seqstat, fp->ipend, 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) {
|
if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
|
||||||
verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n",
|
verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n",
|
||||||
(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
|
(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
|
||||||
|
@ -221,7 +221,7 @@ SECTIONS
|
|||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
__ebss_l1 = .;
|
__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))
|
.data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1))
|
||||||
{
|
{
|
||||||
@ -262,7 +262,7 @@ SECTIONS
|
|||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
__ebss_l2 = .;
|
__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
|
/* Force trailing alignment of our init section so that when we
|
||||||
* free our init memory, we don't leave behind a partial page.
|
* free our init memory, we don't leave behind a partial page.
|
||||||
@ -277,8 +277,5 @@ SECTIONS
|
|||||||
|
|
||||||
DWARF_DEBUG
|
DWARF_DEBUG
|
||||||
|
|
||||||
/DISCARD/ :
|
DISCARDS
|
||||||
{
|
|
||||||
*(.exitcall.exit)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user