Merge branch 'for-rmk' of git://linux-arm.org/linux-2.6

This commit is contained in:
Russell King 2009-09-19 13:47:57 +01:00
commit 40d743b8c1
2683 changed files with 353759 additions and 233832 deletions

View file

@ -2800,7 +2800,7 @@ D: Starter of Linux1394 effort
S: ask per mail for current address
N: Nicolas Pitre
E: nico@cam.org
E: nico@fluxnic.net
D: StrongARM SA1100 support integrator & hacker
D: Xscale PXA architecture
D: unified SMC 91C9x/91C11x ethernet driver (smc91x)

View file

@ -84,6 +84,16 @@ Description:
from this part of the device tree.
Depends on CONFIG_HOTPLUG.
What: /sys/bus/pci/devices/.../reset
Date: July 2009
Contact: Michael S. Tsirkin <mst@redhat.com>
Description:
Some devices allow an individual function to be reset
without affecting other functions in the same device.
For devices that have this support, a file named reset
will be present in sysfs. Writing 1 to this file
will perform reset.
What: /sys/bus/pci/devices/.../vpd
Date: February 2008
Contact: Ben Hutchings <bhutchings@solarflare.com>

View file

@ -25,6 +25,10 @@
<year>2006-2008</year>
<holder>Hans-Jürgen Koch.</holder>
</copyright>
<copyright>
<year>2009</year>
<holder>Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)</holder>
</copyright>
<legalnotice>
<para>
@ -41,6 +45,13 @@ GPL version 2.
</abstract>
<revhistory>
<revision>
<revnumber>0.9</revnumber>
<date>2009-07-16</date>
<authorinitials>mst</authorinitials>
<revremark>Added generic pci driver
</revremark>
</revision>
<revision>
<revnumber>0.8</revnumber>
<date>2008-12-24</date>
@ -809,6 +820,158 @@ framework to set up sysfs files for this region. Simply leave it alone.
</chapter>
<chapter id="uio_pci_generic" xreflabel="Using Generic driver for PCI cards">
<?dbhtml filename="uio_pci_generic.html"?>
<title>Generic PCI UIO driver</title>
<para>
The generic driver is a kernel module named uio_pci_generic.
It can work with any device compliant to PCI 2.3 (circa 2002) and
any compliant PCI Express device. Using this, you only need to
write the userspace driver, removing the need to write
a hardware-specific kernel module.
</para>
<sect1 id="uio_pci_generic_binding">
<title>Making the driver recognize the device</title>
<para>
Since the driver does not declare any device ids, it will not get loaded
automatically and will not automatically bind to any devices, you must load it
and allocate id to the driver yourself. For example:
<programlisting>
modprobe uio_pci_generic
echo &quot;8086 10f5&quot; &gt; /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 &gt; /sys/bus/pci/drivers/e1000e/unbind
echo -n 0000:00:19.0 &gt; /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 -&gt; ../../../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 &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;errno.h&gt;
int main()
{
int uiofd;
int configfd;
int err;
int i;
unsigned icount;
unsigned char command_high;
uiofd = open(&quot;/dev/uio0&quot;, O_RDONLY);
if (uiofd &lt; 0) {
perror(&quot;uio open:&quot;);
return errno;
}
configfd = open(&quot;/sys/class/uio/uio0/device/config&quot;, O_RDWR);
if (uiofd &lt; 0) {
perror(&quot;config open:&quot;);
return errno;
}
/* Read and cache command value */
err = pread(configfd, &amp;command_high, 1, 5);
if (err != 1) {
perror(&quot;command config read:&quot;);
return errno;
}
command_high &amp;= ~0x4;
for(i = 0;; ++i) {
/* Print out a message, for debugging. */
if (i == 0)
fprintf(stderr, &quot;Started uio test driver.\n&quot;);
else
fprintf(stderr, &quot;Interrupts: %d\n&quot;, icount);
/****************************************/
/* Here we got an interrupt from the
device. Do something to it. */
/****************************************/
/* Re-enable interrupts. */
err = pwrite(configfd, &amp;command_high, 1, 5);
if (err != 1) {
perror(&quot;config write:&quot;);
break;
}
/* Wait for next interrupt. */
err = read(uiofd, &amp;icount, 4);
if (err != 4) {
perror(&quot;uio read:&quot;);
break;
}
}
return errno;
}
</programlisting>
</para>
</sect1>
</chapter>
<appendix id="app1">
<title>Further information</title>
<itemizedlist>

View file

@ -4,15 +4,17 @@
February 2, 2006
Current document maintainer:
Linas Vepstas <linas@austin.ibm.com>
Linas Vepstas <linasvepstas@gmail.com>
updated by Richard Lary <rlary@us.ibm.com>
and Mike Mason <mmlnx@us.ibm.com> on 27-Jul-2009
Many PCI bus controllers are able to detect a variety of hardware
PCI errors on the bus, such as parity errors on the data and address
busses, as well as SERR and PERR errors. Some of the more advanced
chipsets are able to deal with these errors; these include PCI-E chipsets,
and the PCI-host bridges found on IBM Power4 and Power5-based pSeries
boxes. A typical action taken is to disconnect the affected device,
and the PCI-host bridges found on IBM Power4, Power5 and Power6-based
pSeries boxes. A typical action taken is to disconnect the affected device,
halting all I/O to it. The goal of a disconnection is to avoid system
corruption; for example, to halt system memory corruption due to DMA's
to "wild" addresses. Typically, a reconnection mechanism is also
@ -37,10 +39,11 @@ is forced by the need to handle multi-function devices, that is,
devices that have multiple device drivers associated with them.
In the first stage, each driver is allowed to indicate what type
of reset it desires, the choices being a simple re-enabling of I/O
or requesting a hard reset (a full electrical #RST of the PCI card).
If any driver requests a full reset, that is what will be done.
or requesting a slot reset.
After a full reset and/or a re-enabling of I/O, all drivers are
If any driver requests a slot reset, that is what will be done.
After a reset and/or a re-enabling of I/O, all drivers are
again notified, so that they may then perform any device setup/config
that may be required. After these have all completed, a final
"resume normal operations" event is sent out.
@ -101,7 +104,7 @@ if it implements any, it must implement error_detected(). If a callback
is not implemented, the corresponding feature is considered unsupported.
For example, if mmio_enabled() and resume() aren't there, then it
is assumed that the driver is not doing any direct recovery and requires
a reset. If link_reset() is not implemented, the card is assumed as
a slot reset. If link_reset() is not implemented, the card is assumed to
not care about link resets. Typically a driver will want to know about
a slot_reset().
@ -111,7 +114,7 @@ sequence described below.
STEP 0: Error Event
-------------------
PCI bus error is detect by the PCI hardware. On powerpc, the slot
A PCI bus error is detected by the PCI hardware. On powerpc, the slot
is isolated, in that all I/O is blocked: all reads return 0xffffffff,
all writes are ignored.
@ -139,7 +142,7 @@ The driver must return one of the following result codes:
a chance to extract some diagnostic information (see
mmio_enable, below).
- PCI_ERS_RESULT_NEED_RESET:
Driver returns this if it can't recover without a hard
Driver returns this if it can't recover without a
slot reset.
- PCI_ERS_RESULT_DISCONNECT:
Driver returns this if it doesn't want to recover at all.
@ -169,11 +172,11 @@ is STEP 6 (Permanent Failure).
>>> The current powerpc implementation doesn't much care if the device
>>> attempts I/O at this point, or not. I/O's will fail, returning
>>> a value of 0xff on read, and writes will be dropped. If the device
>>> driver attempts more than 10K I/O's to a frozen adapter, it will
>>> assume that the device driver has gone into an infinite loop, and
>>> it will panic the kernel. There doesn't seem to be any other
>>> way of stopping a device driver that insists on spinning on I/O.
>>> a value of 0xff on read, and writes will be dropped. If more than
>>> EEH_MAX_FAILS I/O's are attempted to a frozen adapter, EEH
>>> assumes that the device driver has gone into an infinite loop
>>> and prints an error to syslog. A reboot is then required to
>>> get the device working again.
STEP 2: MMIO Enabled
-------------------
@ -182,15 +185,14 @@ DMA), and then calls the mmio_enabled() callback on all affected
device drivers.
This is the "early recovery" call. IOs are allowed again, but DMA is
not (hrm... to be discussed, I prefer not), with some restrictions. This
is NOT a callback for the driver to start operations again, only to
peek/poke at the device, extract diagnostic information, if any, and
eventually do things like trigger a device local reset or some such,
but not restart operations. This is callback is made if all drivers on
a segment agree that they can try to recover and if no automatic link reset
was performed by the HW. If the platform can't just re-enable IOs without
a slot reset or a link reset, it wont call this callback, and instead
will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
not, with some restrictions. This is NOT a callback for the driver to
start operations again, only to peek/poke at the device, extract diagnostic
information, if any, and eventually do things like trigger a device local
reset or some such, but not restart operations. This callback is made if
all drivers on a segment agree that they can try to recover and if no automatic
link reset was performed by the HW. If the platform can't just re-enable IOs
without a slot reset or a link reset, it will not call this callback, and
instead will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
>>> The following is proposed; no platform implements this yet:
>>> Proposal: All I/O's should be done _synchronously_ from within
@ -228,9 +230,6 @@ proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations).
If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform
proceeds to STEP 4 (Slot Reset)
>>> The current powerpc implementation does not implement this callback.
STEP 3: Link Reset
------------------
The platform resets the link, and then calls the link_reset() callback
@ -253,16 +252,33 @@ The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5
>>> The current powerpc implementation does not implement this callback.
STEP 4: Slot Reset
------------------
The platform performs a soft or hard reset of the device, and then
calls the slot_reset() callback.
A soft reset consists of asserting the adapter #RST line and then
In response to a return value of PCI_ERS_RESULT_NEED_RESET, the
the platform will peform a slot reset on the requesting PCI device(s).
The actual steps taken by a platform to perform a slot reset
will be platform-dependent. Upon completion of slot reset, the
platform will call the device slot_reset() callback.
Powerpc platforms implement two levels of slot reset:
soft reset(default) and fundamental(optional) reset.
Powerpc soft reset consists of asserting the adapter #RST line and then
restoring the PCI BAR's and PCI configuration header to a state
that is equivalent to what it would be after a fresh system
power-on followed by power-on BIOS/system firmware initialization.
Soft reset is also known as hot-reset.
Powerpc fundamental reset is supported by PCI Express cards only
and results in device's state machines, hardware logic, port states and
configuration registers to initialize to their default conditions.
For most PCI devices, a soft reset will be sufficient for recovery.
Optional fundamental reset is provided to support a limited number
of PCI Express PCI devices for which a soft reset is not sufficient
for recovery.
If the platform supports PCI hotplug, then the reset might be
performed by toggling the slot electrical power off/on.
@ -274,10 +290,12 @@ may result in hung devices, kernel panics, or silent data corruption.
This call gives drivers the chance to re-initialize the hardware
(re-download firmware, etc.). At this point, the driver may assume
that he card is in a fresh state and is fully functional. In
particular, interrupt generation should work normally.
that the card is in a fresh state and is fully functional. The slot
is unfrozen and the driver has full access to PCI config space,
memory mapped I/O space and DMA. Interrupts (Legacy, MSI, or MSI-X)
will also be available.
Drivers should not yet restart normal I/O processing operations
Drivers should not restart normal I/O processing operations
at this point. If all device drivers report success on this
callback, the platform will call resume() to complete the sequence,
and let the driver restart normal I/O processing.
@ -302,11 +320,21 @@ driver performs device init only from PCI function 0:
- PCI_ERS_RESULT_DISCONNECT
Same as above.
Drivers for PCI Express cards that require a fundamental reset must
set the needs_freset bit in the pci_dev structure in their probe function.
For example, the QLogic qla2xxx driver sets the needs_freset bit for certain
PCI card types:
+ /* Set EEH reset type to fundamental if required by hba */
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha))
+ pdev->needs_freset = 1;
+
Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent
Failure).
>>> The current powerpc implementation does not currently try a
>>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
>>> The current powerpc implementation does not try a power-cycle
>>> reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
>>> However, it probably should.
@ -348,7 +376,7 @@ software errors.
Conclusion; General Remarks
---------------------------
The way those callbacks are called is platform policy. A platform with
The way the callbacks are called is platform policy. A platform with
no slot reset capability may want to just "ignore" drivers that can't
recover (disconnect them) and try to let other cards on the same segment
recover. Keep in mind that in most real life cases, though, there will
@ -361,8 +389,8 @@ That is, the recovery API only requires that:
- There is no guarantee that interrupt delivery can proceed from any
device on the segment starting from the error detection and until the
resume callback is sent, at which point interrupts are expected to be
fully operational.
slot_reset callback is called, at which point interrupts are expected
to be fully operational.
- There is no guarantee that interrupt delivery is stopped, that is,
a driver that gets an interrupt after detecting an error, or that detects
@ -381,16 +409,23 @@ anyway :)
>>> Implementation details for the powerpc platform are discussed in
>>> the file Documentation/powerpc/eeh-pci-error-recovery.txt
>>> As of this writing, there are six device drivers with patches
>>> implementing error recovery. Not all of these patches are in
>>> As of this writing, there is a growing list of device drivers with
>>> patches implementing error recovery. Not all of these patches are in
>>> mainline yet. These may be used as "examples":
>>>
>>> drivers/scsi/ipr.c
>>> drivers/scsi/sym53cxx_2
>>> drivers/scsi/ipr
>>> drivers/scsi/sym53c8xx_2
>>> drivers/scsi/qla2xxx
>>> drivers/scsi/lpfc
>>> drivers/next/bnx2.c
>>> drivers/next/e100.c
>>> drivers/net/e1000
>>> drivers/net/e1000e
>>> drivers/net/ixgb
>>> drivers/net/ixgbe
>>> drivers/net/cxgb3
>>> drivers/net/s2io.c
>>> drivers/net/qlge
The End
-------

View file

@ -40,4 +40,4 @@ Notes:
mode, the timing is off so the image is corrupted. This will be
fixed soon.
Any contribution can be sent to nico@cam.org and will be greatly welcome!
Any contribution can be sent to nico@fluxnic.net and will be greatly welcome!

View file

@ -240,7 +240,7 @@ Then, rebooting the Assabet is just a matter of waiting for the login prompt.
Nicolas Pitre
nico@cam.org
nico@fluxnic.net
June 12, 2001

View file

@ -60,7 +60,7 @@ little modifications.
Any contribution is welcome.
Please send patches to nico@cam.org
Please send patches to nico@fluxnic.net
Have Fun !

View file

@ -4,7 +4,7 @@ For more details, contact Applied Data Systems or see
http://www.applieddata.net/products.html
The original Linux support for this product has been provided by
Nicolas Pitre <nico@cam.org>. Continued development work by
Nicolas Pitre <nico@fluxnic.net>. Continued development work by
Woojung Huh <whuh@applieddata.net>
It's currently possible to mount a root filesystem via NFS providing a
@ -94,5 +94,5 @@ Notes:
mode, the timing is off so the image is corrupted. This will be
fixed soon.
Any contribution can be sent to nico@cam.org and will be greatly welcome!
Any contribution can be sent to nico@fluxnic.net and will be greatly welcome!

View file

@ -4,7 +4,7 @@ For more details, contact Applied Data Systems or see
http://www.applieddata.net/products.html
The original Linux support for this product has been provided by
Nicolas Pitre <nico@cam.org>. Continued development work by
Nicolas Pitre <nico@fluxnic.net>. Continued development work by
Woojung Huh <whuh@applieddata.net>
Use 'make graphicsmaster_config' before any 'make config'.
@ -50,4 +50,4 @@ Notes:
mode, the timing is off so the image is corrupted. This will be
fixed soon.
Any contribution can be sent to nico@cam.org and will be greatly welcome!
Any contribution can be sent to nico@fluxnic.net and will be greatly welcome!

View file

@ -9,7 +9,7 @@ Of course Victor is using Linux as its main operating system.
The Victor implementation for Linux is maintained by Nicolas Pitre:
nico@visuaide.com
nico@cam.org
nico@fluxnic.net
For any comments, please feel free to contact me through the above
addresses.

View file

@ -152,7 +152,6 @@ piggy.gz
piggyback
pnmtologo
ppc_defs.h*
promcon_tbl.c
pss_boot.h
qconf
raid6altivec*.c

View file

@ -428,16 +428,6 @@ Who: Johannes Berg <johannes@sipsolutions.net>
----------------------------
What: CONFIG_X86_OLD_MCE
When: 2.6.32
Why: Remove the old legacy 32bit machine check code. This has been
superseded by the newer machine check code from the 64bit port,
but the old version has been kept around for easier testing. Note this
doesn't impact the old P5 and WinChip machine check handlers.
Who: Andi Kleen <andi@firstfloor.org>
----------------------------
What: lock_policy_rwsem_* and unlock_policy_rwsem_* will not be
exported interface anymore.
When: 2.6.33

View file

@ -2,11 +2,11 @@ Kernel driver pcf8591
=====================
Supported chips:
* Philips PCF8591
* Philips/NXP PCF8591
Prefix: 'pcf8591'
Addresses scanned: I2C 0x48 - 0x4f
Datasheet: Publicly available at the Philips Semiconductor website
http://www.semiconductors.philips.com/pip/PCF8591P.html
Datasheet: Publicly available at the NXP website
http://www.nxp.com/pip/PCF8591_6.html
Authors:
Aurelien Jarno <aurelien@aurel32.net>
@ -16,9 +16,10 @@ Authors:
Description
-----------
The PCF8591 is an 8-bit A/D and D/A converter (4 analog inputs and one
analog output) for the I2C bus produced by Philips Semiconductors. It
is designed to provide a byte I2C interface to up to 4 separate devices.
analog output) for the I2C bus produced by Philips Semiconductors (now NXP).
It is designed to provide a byte I2C interface to up to 4 separate devices.
The PCF8591 has 4 analog inputs programmable as single-ended or
differential inputs :
@ -58,8 +59,8 @@ Accessing PCF8591 via /sys interface
-------------------------------------
! Be careful !
The PCF8591 is plainly impossible to detect ! Stupid chip.
So every chip with address in the interval [48..4f] is
The PCF8591 is plainly impossible to detect! Stupid chip.
So every chip with address in the interval [0x48..0x4f] is
detected as PCF8591. If you have other chips in this address
range, the workaround is to load this module after the one
for your others chips.
@ -67,19 +68,20 @@ for your others chips.
On detection (i.e. insmod, modprobe et al.), directories are being
created for each detected PCF8591:
/sys/bus/devices/<0>-<1>/
/sys/bus/i2c/devices/<0>-<1>/
where <0> is the bus the chip was detected on (e. g. i2c-0)
and <1> the chip address ([48..4f])
Inside these directories, there are such files:
in0, in1, in2, in3, out0_enable, out0_output, name
in0_input, in1_input, in2_input, in3_input, out0_enable, out0_output, name
Name contains chip name.
The in0, in1, in2 and in3 files are RO. Reading gives the value of the
corresponding channel. Depending on the current analog inputs configuration,
files in2 and/or in3 do not exist. Values range are from 0 to 255 for single
ended inputs and -128 to +127 for differential inputs (8-bit ADC).
The in0_input, in1_input, in2_input and in3_input files are RO. Reading gives
the value of the corresponding channel. Depending on the current analog inputs
configuration, files in2_input and in3_input may not exist. Values range
from 0 to 255 for single ended inputs and -128 to +127 for differential inputs
(8-bit ADC).
The out0_enable file is RW. Reading gives "1" for analog output enabled and
"0" for analog output disabled. Writing accepts "0" and "1" accordingly.

View 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
View 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.

View file

@ -1286,6 +1286,10 @@ and is between 256 and 4096 characters. It is defined in the file
(machvec) in a generic kernel.
Example: machvec=hpzx1_swiotlb
machtype= [Loongson] Share the same kernel image file between different
yeeloong laptop.
Example: machtype=lemote-yeeloong-2f-7inch
max_addr=nn[KMG] [KNL,BOOT,ia64] All physical memory greater
than or equal to this physical address is ignored.
@ -1971,11 +1975,12 @@ and is between 256 and 4096 characters. It is defined in the file
Format: { 0 | 1 }
See arch/parisc/kernel/pdc_chassis.c
percpu_alloc= [X86] Select which percpu first chunk allocator to use.
Allowed values are one of "lpage", "embed" and "4k".
See comments in arch/x86/kernel/setup_percpu.c for
details on each allocator. This parameter is primarily
for debugging and performance comparison.
percpu_alloc= Select which percpu first chunk allocator to use.
Currently supported values are "embed" and "page".
Archs may support subset or none of the selections.
See comments in mm/percpu.c for details on each
allocator. This parameter is primarily for debugging
and performance comparison.
pf. [PARIDE]
See Documentation/blockdev/paride.txt.

View file

@ -1,7 +1,7 @@
Event Tracing
Documentation written by Theodore Ts'o
Updated by Li Zefan
Updated by Li Zefan and Tom Zanussi
1. Introduction
===============
@ -22,12 +22,12 @@ tracing information should be printed.
---------------------------------
The events which are available for tracing can be found in the file
/debug/tracing/available_events.
/sys/kernel/debug/tracing/available_events.
To enable a particular event, such as 'sched_wakeup', simply echo it
to /debug/tracing/set_event. For example:
to /sys/kernel/debug/tracing/set_event. For example:
# echo sched_wakeup >> /debug/tracing/set_event
# echo sched_wakeup >> /sys/kernel/debug/tracing/set_event
[ Note: '>>' is necessary, otherwise it will firstly disable
all the events. ]
@ -35,15 +35,15 @@ to /debug/tracing/set_event. For example:
To disable an event, echo the event name to the set_event file prefixed
with an exclamation point:
# echo '!sched_wakeup' >> /debug/tracing/set_event
# echo '!sched_wakeup' >> /sys/kernel/debug/tracing/set_event
To disable all events, echo an empty line to the set_event file:
# echo > /debug/tracing/set_event
# echo > /sys/kernel/debug/tracing/set_event
To enable all events, echo '*:*' or '*:' to the set_event file:
# echo *:* > /debug/tracing/set_event
# echo *:* > /sys/kernel/debug/tracing/set_event
The events are organized into subsystems, such as ext4, irq, sched,
etc., and a full event name looks like this: <subsystem>:<event>. The
@ -52,29 +52,29 @@ file. All of the events in a subsystem can be specified via the syntax
"<subsystem>:*"; for example, to enable all irq events, you can use the
command:
# echo 'irq:*' > /debug/tracing/set_event
# echo 'irq:*' > /sys/kernel/debug/tracing/set_event
2.2 Via the 'enable' toggle
---------------------------
The events available are also listed in /debug/tracing/events/ hierarchy
The events available are also listed in /sys/kernel/debug/tracing/events/ hierarchy
of directories.
To enable event 'sched_wakeup':
# echo 1 > /debug/tracing/events/sched/sched_wakeup/enable
# echo 1 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
To disable it:
# echo 0 > /debug/tracing/events/sched/sched_wakeup/enable
# echo 0 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
To enable all events in sched subsystem:
# echo 1 > /debug/tracing/events/sched/enable
# echo 1 > /sys/kernel/debug/tracing/events/sched/enable
To eanble all events:
# echo 1 > /debug/tracing/events/enable
# echo 1 > /sys/kernel/debug/tracing/events/enable
When reading one of these enable files, there are four results:
@ -97,3 +97,185 @@ The format of this boot option is the same as described in section 2.1.
See The example provided in samples/trace_events
4. Event formats
================
Each trace event has a 'format' file associated with it that contains
a description of each field in a logged event. This information can
be used to parse the binary trace stream, and is also the place to
find the field names that can be used in event filters (see section 5).
It also displays the format string that will be used to print the
event in text mode, along with the event name and ID used for
profiling.
Every event has a set of 'common' fields associated with it; these are
the fields prefixed with 'common_'. The other fields vary between
events and correspond to the fields defined in the TRACE_EVENT
definition for that event.
Each field in the format has the form:
field:field-type field-name; offset:N; size:N;
where offset is the offset of the field in the trace record and size
is the size of the data item, in bytes.
For example, here's the information displayed for the 'sched_wakeup'
event:
# cat /debug/tracing/events/sched/sched_wakeup/format
name: sched_wakeup
ID: 60
format:
field:unsigned short common_type; offset:0; size:2;
field:unsigned char common_flags; offset:2; size:1;
field:unsigned char common_preempt_count; offset:3; size:1;
field:int common_pid; offset:4; size:4;
field:int common_tgid; offset:8; size:4;
field:char comm[TASK_COMM_LEN]; offset:12; size:16;
field:pid_t pid; offset:28; size:4;
field:int prio; offset:32; size:4;
field:int success; offset:36; size:4;
field:int cpu; offset:40; size:4;
print fmt: "task %s:%d [%d] success=%d [%03d]", REC->comm, REC->pid,
REC->prio, REC->success, REC->cpu
This event contains 10 fields, the first 5 common and the remaining 5
event-specific. All the fields for this event are numeric, except for
'comm' which is a string, a distinction important for event filtering.
5. Event filtering
==================
Trace events can be filtered in the kernel by associating boolean
'filter expressions' with them. As soon as an event is logged into
the trace buffer, its fields are checked against the filter expression
associated with that event type. An event with field values that
'match' the filter will appear in the trace output, and an event whose
values don't match will be discarded. An event with no filter
associated with it matches everything, and is the default when no
filter has been set for an event.
5.1 Expression syntax
---------------------
A filter expression consists of one or more 'predicates' that can be
combined using the logical operators '&&' and '||'. A predicate is
simply a clause that compares the value of a field contained within a
logged event with a constant value and returns either 0 or 1 depending
on whether the field value matched (1) or didn't match (0):
field-name relational-operator value
Parentheses can be used to provide arbitrary logical groupings and
double-quotes can be used to prevent the shell from interpreting
operators as shell metacharacters.
The field-names available for use in filters can be found in the
'format' files for trace events (see section 4).
The relational-operators depend on the type of the field being tested:
The operators available for numeric fields are:
==, !=, <, <=, >, >=
And for string fields they are:
==, !=
Currently, only exact string matches are supported.
Currently, the maximum number of predicates in a filter is 16.
5.2 Setting filters
-------------------
A filter for an individual event is set by writing a filter expression
to the 'filter' file for the given event.
For example:
# cd /debug/tracing/events/sched/sched_wakeup
# echo "common_preempt_count > 4" > filter
A slightly more involved example:
# cd /debug/tracing/events/sched/sched_signal_send
# echo "((sig >= 10 && sig < 15) || sig == 17) && comm != bash" > filter
If there is an error in the expression, you'll get an 'Invalid
argument' error when setting it, and the erroneous string along with
an error message can be seen by looking at the filter e.g.:
# cd /debug/tracing/events/sched/sched_signal_send
# echo "((sig >= 10 && sig < 15) || dsig == 17) && comm != bash" > filter
-bash: echo: write error: Invalid argument
# cat filter
((sig >= 10 && sig < 15) || dsig == 17) && comm != bash
^
parse_error: Field not found
Currently the caret ('^') for an error always appears at the beginning of
the filter string; the error message should still be useful though
even without more accurate position info.
5.3 Clearing filters
--------------------
To clear the filter for an event, write a '0' to the event's filter
file.
To clear the filters for all events in a subsystem, write a '0' to the
subsystem's filter file.
5.3 Subsystem filters
---------------------
For convenience, filters for every event in a subsystem can be set or
cleared as a group by writing a filter expression into the filter file
at the root of the subsytem. Note however, that if a filter for any
event within the subsystem lacks a field specified in the subsystem
filter, or if the filter can't be applied for any other reason, the
filter for that event will retain its previous setting. This can
result in an unintended mixture of filters which could lead to
confusing (to the user who might think different filters are in
effect) trace output. Only filters that reference just the common
fields can be guaranteed to propagate successfully to all events.
Here are a few subsystem filter examples that also illustrate the
above points:
Clear the filters on all events in the sched subsytem:
# cd /sys/kernel/debug/tracing/events/sched
# echo 0 > filter
# cat sched_switch/filter
none
# cat sched_wakeup/filter
none
Set a filter using only common fields for all events in the sched
subsytem (all events end up with the same filter):
# cd /sys/kernel/debug/tracing/events/sched
# echo common_pid == 0 > filter
# cat sched_switch/filter
common_pid == 0
# cat sched_wakeup/filter
common_pid == 0
Attempt to set a filter using a non-common field for all events in the
sched subsytem (all events but those that have a prev_pid field retain
their old filters):
# cd /sys/kernel/debug/tracing/events/sched
# echo prev_pid == 0 > filter
# cat sched_switch/filter
prev_pid == 0
# cat sched_wakeup/filter
common_pid == 0

View 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>

View file

@ -26,6 +26,12 @@ disabled, and more (ftrace allows for tracer plugins, which
means that the list of tracers can always grow).
Implementation Details
----------------------
See ftrace-design.txt for details for arch porters and such.
The File System
---------------

View 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

View file

@ -21,3 +21,5 @@
20 -> Hauppauge WinTV-HVR1255 [0070:2251]
21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295]
22 -> Mygica X8506 DMB-TH [14f1:8651]
23 -> Magic-Pro ProHDTV Extreme 2 [14f1:8657]
24 -> Hauppauge WinTV-HVR1850 [0070:8541]

View file

@ -80,3 +80,4 @@
79 -> Terratec Cinergy HT PCI MKII [153b:1177]
80 -> Hauppauge WinTV-IR Only [0070:9290]
81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654]
82 -> WinFast DTV2000 H rev. J [107d:6f2b]

View file

@ -7,7 +7,7 @@
6 -> Terratec Cinergy 200 USB (em2800)
7 -> Leadtek Winfast USB II (em2800) [0413:6023]
8 -> Kworld USB2800 (em2800)
9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,2304:0207,2304:021a]
9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,1b80:e304,2304:0207,2304:021a]
10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
12 -> Kworld PVR TV 2800 RF (em2820/em2840)
@ -33,7 +33,7 @@
34 -> Terratec Cinergy A Hybrid XS (em2860) [0ccd:004f]
35 -> Typhoon DVD Maker (em2860)
36 -> NetGMBH Cam (em2860)
37 -> Gadmei UTV330 (em2860)
37 -> Gadmei UTV330 (em2860) [eb1a:50a6]
38 -> Yakumo MovieMixer (em2861)
39 -> KWorld PVRTV 300U (em2861) [eb1a:e300]
40 -> Plextor ConvertX PX-TV100U (em2861) [093b:a005]
@ -67,3 +67,4 @@
69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313]
70 -> Evga inDtube (em2882)
71 -> Silvercrest Webcam 1.3mpix (em2820/em2840)
72 -> Gadmei UTV330+ (em2861)

View file

@ -167,3 +167,7 @@
166 -> Beholder BeholdTV 607 RDS [5ace:6073]
167 -> Beholder BeholdTV 609 RDS [5ace:6092]
168 -> Beholder BeholdTV 609 RDS [5ace:6093]
169 -> Compro VideoMate S350/S300 [185b:c900]
170 -> AverMedia AverTV Studio 505 [1461:a115]
171 -> Beholder BeholdTV X7 [5ace:7595]
172 -> RoverMedia TV Link Pro FM [19d1:0138]

View file

@ -78,3 +78,4 @@ tuner=77 - TCL tuner MF02GIP-5N-E
tuner=78 - Philips FMD1216MEX MK3 Hybrid Tuner
tuner=79 - Philips PAL/SECAM multi (FM1216 MK5)
tuner=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough
tuner=81 - Partsnic (Daewoo) PTI-5NF05

View file

@ -18,8 +18,8 @@ Table of Contents
1.0 Introduction
The file ../drivers/char/c-qcam.c is a device driver for the
Logitech (nee Connectix) parallel port interface color CCD camera.
The file ../../drivers/media/video/c-qcam.c is a device driver for
the Logitech (nee Connectix) parallel port interface color CCD camera.
This is a fairly inexpensive device for capturing images. Logitech
does not currently provide information for developers, but many people
have engineered several solutions for non-Microsoft use of the Color

View file

@ -140,6 +140,7 @@ spca500 04fc:7333 PalmPixDC85
sunplus 04fc:ffff Pure DigitalDakota
spca501 0506:00df 3Com HomeConnect Lite
sunplus 052b:1513 Megapix V4
sunplus 052b:1803 MegaImage VI
tv8532 0545:808b Veo Stingray
tv8532 0545:8333 Veo Stingray
sunplus 0546:3155 Polaroid PDC3070
@ -182,6 +183,7 @@ ov534 06f8:3002 Hercules Blog Webcam
ov534 06f8:3003 Hercules Dualpix HD Weblog
sonixj 06f8:3004 Hercules Classic Silver
sonixj 06f8:3008 Hercules Deluxe Optical Glass
pac7311 06f8:3009 Hercules Classic Link
spca508 0733:0110 ViewQuest VQ110
spca508 0130:0130 Clone Digital Webcam 11043
spca501 0733:0401 Intel Create and Share
@ -235,8 +237,10 @@ pac7311 093a:2621 PAC731x
pac7311 093a:2622 Genius Eye 312
pac7311 093a:2624 PAC7302
pac7311 093a:2626 Labtec 2200
pac7311 093a:2629 Genious iSlim 300
pac7311 093a:262a Webcam 300k
pac7311 093a:262c Philips SPC 230 NC
jeilinj 0979:0280 Sakar 57379
zc3xx 0ac8:0302 Z-star Vimicro zc0302
vc032x 0ac8:0321 Vimicro generic vc0321
vc032x 0ac8:0323 Vimicro Vc0323
@ -247,6 +251,7 @@ zc3xx 0ac8:305b Z-star Vimicro zc0305b
zc3xx 0ac8:307b Ldlc VC302+Ov7620
vc032x 0ac8:c001 Sony embedded vimicro
vc032x 0ac8:c002 Sony embedded vimicro
vc032x 0ac8:c301 Samsung Q1 Ultra Premium
spca508 0af9:0010 Hama USB Sightcam 100
spca508 0af9:0011 Hama USB Sightcam 100
sonixb 0c45:6001 Genius VideoCAM NB
@ -284,6 +289,7 @@ sonixj 0c45:613a Microdia Sonix PC Camera
sonixj 0c45:613b Surfer SN-206
sonixj 0c45:613c Sonix Pccam168
sonixj 0c45:6143 Sonix Pccam168
sonixj 0c45:6148 Digitus DA-70811/ZSMC USB PC Camera ZS211/Microdia
sn9c20x 0c45:6240 PC Camera (SN9C201 + MT9M001)
sn9c20x 0c45:6242 PC Camera (SN9C201 + MT9M111)
sn9c20x 0c45:6248 PC Camera (SN9C201 + OV9655)

View 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"

View file

@ -12,6 +12,7 @@ Offset Proto Name Meaning
000/040 ALL screen_info Text mode or frame buffer information
(struct screen_info)
040/014 ALL apm_bios_info APM BIOS information (struct apm_bios_info)
058/008 ALL tboot_addr Physical address of tboot shared page
060/010 ALL ist_info Intel SpeedStep (IST) BIOS support information
(struct ist_info)
080/010 ALL hd0_info hd0 disk parameter, OBSOLETE!!

View file

@ -931,6 +931,12 @@ W: http://wireless.kernel.org/en/users/Drivers/ar9170
S: Maintained
F: drivers/net/wireless/ath/ar9170/
ATK0110 HWMON DRIVER
M: Luca Tettamanti <kronos.it@gmail.com>
L: lm-sensors@lm-sensors.org
S: Maintained
F: drivers/hwmon/asus_atk0110.c
ATI_REMOTE2 DRIVER
M: Ville Syrjala <syrjala@sci.fi>
S: Maintained
@ -2152,13 +2158,16 @@ F: Documentation/filesystems/caching/
F: fs/fscache/
F: include/linux/fscache*.h
FTRACE
TRACING
M: Steven Rostedt <rostedt@goodmis.org>
M: Frederic Weisbecker <fweisbec@gmail.com>
M: Ingo Molnar <mingo@redhat.com>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git tracing/core
S: Maintained
F: Documentation/trace/ftrace.txt
F: arch/*/*/*/ftrace.h
F: arch/*/kernel/ftrace.c
F: include/*/ftrace.h
F: include/*/ftrace.h include/trace/ include/linux/trace*.h
F: kernel/trace/
FUJITSU FR-V (FRV) PORT
@ -2218,6 +2227,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git
S: Maintained
F: include/asm-generic
GENERIC UIO DRIVER FOR PCI DEVICES
M: Michael S. Tsirkin <mst@redhat.com>
L: kvm@vger.kernel.org
L: linux-kernel@vger.kernel.org
S: Supported
F: drivers/uio/uio_pci_generic.c
GFS2 FILE SYSTEM
M: Steven Whitehouse <swhiteho@redhat.com>
L: cluster-devel@redhat.com
@ -3317,7 +3333,7 @@ S: Supported
F: drivers/net/wireless/mwl8k.c
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
M: Nicolas Pitre <nico@cam.org>
M: Nicolas Pitre <nico@fluxnic.net>
S: Maintained
MARVELL YUKON / SYSKONNECT DRIVER
@ -4689,7 +4705,7 @@ F: include/linux/sl?b*.h
F: mm/sl?b.c
SMC91x ETHERNET DRIVER
M: Nicolas Pitre <nico@cam.org>
M: Nicolas Pitre <nico@fluxnic.net>
S: Maintained
F: drivers/net/smc91x.*
@ -5694,7 +5710,7 @@ F: include/xen/
XFS FILESYSTEM
P: Silicon Graphics Inc
M: Felix Blyakher <felixb@sgi.com>
M: Alex Elder <aelder@sgi.com>
M: xfs-masters@oss.sgi.com
L: xfs@oss.sgi.com
W: http://oss.sgi.com/projects/xfs

View file

@ -325,7 +325,7 @@ CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
MODFLAGS = -DMODULE
CFLAGS_MODULE = $(MODFLAGS)
AFLAGS_MODULE = $(MODFLAGS)
LDFLAGS_MODULE =
LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds
CFLAGS_KERNEL =
AFLAGS_KERNEL =
CFLAGS_GCOV = -fprofile-arcs -ftest-coverage

View file

@ -9,6 +9,7 @@ config OPROFILE
depends on TRACING_SUPPORT
select TRACING
select RING_BUFFER
select RING_BUFFER_ALLOW_SWAP
help
OProfile is a profiling system capable of profiling the
whole system, include the kernel, kernel modules, libraries,

View file

@ -9,10 +9,6 @@
#define unmap_page_from_agp(page)
#define flush_agp_cache() mb()
/* Convert a physical address to an address suitable for the GART. */
#define phys_to_gart(x) (x)
#define gart_to_phys(x) (x)
/* GATT allocation. Returns/accepts GATT kernel virtual address. */
#define alloc_gatt_pages(order) \
((char *)__get_free_pages(GFP_KERNEL, (order)))

View file

@ -52,7 +52,6 @@ struct pci_controller {
bus numbers. */
#define pcibios_assign_all_busses() 1
#define pcibios_scan_all_fns(a, b) 0
#define PCIBIOS_MIN_IO alpha_mv.min_io_address
#define PCIBIOS_MIN_MEM alpha_mv.min_mem_address

View file

@ -1,102 +1,18 @@
#ifndef __ALPHA_PERCPU_H
#define __ALPHA_PERCPU_H
#include <linux/compiler.h>
#include <linux/threads.h>
#include <linux/percpu-defs.h>
/*
* Determine the real variable name from the name visible in the
* kernel sources.
*/
#define per_cpu_var(var) per_cpu__##var
#ifdef CONFIG_SMP
/*
* per_cpu_offset() is the offset that has to be added to a
* percpu variable to get to the instance for a certain processor.
*/
extern unsigned long __per_cpu_offset[NR_CPUS];
#define per_cpu_offset(x) (__per_cpu_offset[x])
#define __my_cpu_offset per_cpu_offset(raw_smp_processor_id())
#ifdef CONFIG_DEBUG_PREEMPT
#define my_cpu_offset per_cpu_offset(smp_processor_id())
#else
#define my_cpu_offset __my_cpu_offset
#endif
#ifndef MODULE
#define SHIFT_PERCPU_PTR(var, offset) RELOC_HIDE(&per_cpu_var(var), (offset))
#define PER_CPU_DEF_ATTRIBUTES
#else
/*
* To calculate addresses of locally defined variables, GCC uses 32-bit
* displacement from the GP. Which doesn't work for per cpu variables in
* modules, as an offset to the kernel per cpu area is way above 4G.
* To calculate addresses of locally defined variables, GCC uses
* 32-bit displacement from the GP. Which doesn't work for per cpu
* variables in modules, as an offset to the kernel per cpu area is
* way above 4G.
*
* This forces allocation of a GOT entry for per cpu variable using
* ldq instruction with a 'literal' relocation.
* Always use weak definitions for percpu variables in modules.
*/
#define SHIFT_PERCPU_PTR(var, offset) ({ \
extern int simple_identifier_##var(void); \
unsigned long __ptr, tmp_gp; \
asm ( "br %1, 1f \n\
1: ldgp %1, 0(%1) \n\
ldq %0, per_cpu__" #var"(%1)\t!literal" \
: "=&r"(__ptr), "=&r"(tmp_gp)); \
(typeof(&per_cpu_var(var)))(__ptr + (offset)); })
#define PER_CPU_DEF_ATTRIBUTES __used
#endif /* MODULE */
/*
* A percpu variable may point to a discarded regions. The following are
* established ways to produce a usable pointer from the percpu variable
* offset.
*/
#define per_cpu(var, cpu) \
(*SHIFT_PERCPU_PTR(var, per_cpu_offset(cpu)))
#define __get_cpu_var(var) \
(*SHIFT_PERCPU_PTR(var, my_cpu_offset))
#define __raw_get_cpu_var(var) \
(*SHIFT_PERCPU_PTR(var, __my_cpu_offset))
#else /* ! SMP */
#define per_cpu(var, cpu) (*((void)(cpu), &per_cpu_var(var)))
#define __get_cpu_var(var) per_cpu_var(var)
#define __raw_get_cpu_var(var) per_cpu_var(var)
#define PER_CPU_DEF_ATTRIBUTES
#endif /* SMP */
#ifdef CONFIG_SMP
#define PER_CPU_BASE_SECTION ".data.percpu"
#else
#define PER_CPU_BASE_SECTION ".data"
#if defined(MODULE) && defined(CONFIG_SMP)
#define ARCH_NEEDS_WEAK_PER_CPU
#endif
#ifdef CONFIG_SMP
#ifdef MODULE
#define PER_CPU_SHARED_ALIGNED_SECTION ""
#else
#define PER_CPU_SHARED_ALIGNED_SECTION ".shared_aligned"
#endif
#define PER_CPU_FIRST_SECTION ".first"
#else
#define PER_CPU_SHARED_ALIGNED_SECTION ""
#define PER_CPU_FIRST_SECTION ""
#endif
#define PER_CPU_ATTRIBUTES
#include <asm-generic/percpu.h>
#endif /* __ALPHA_PERCPU_H */

View file

@ -2,6 +2,7 @@
#define _ALPHA_TLBFLUSH_H
#include <linux/mm.h>
#include <linux/sched.h>
#include <asm/compiler.h>
#include <asm/pgalloc.h>

View file

@ -134,13 +134,6 @@ SECTIONS
__bss_stop = .;
_end = .;
/* Sections to be discarded */
/DISCARD/ : {
EXIT_TEXT
EXIT_DATA
*(.exitcall.exit)
}
.mdebug 0 : {
*(.mdebug)
}
@ -150,4 +143,6 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
DISCARDS
}

View file

@ -1,7 +1,7 @@
/*
* linux/arch/arm/boot/compressed/head-sa1100.S
*
* Copyright (C) 1999 Nicolas Pitre <nico@cam.org>
* Copyright (C) 1999 Nicolas Pitre <nico@fluxnic.net>
*
* SA1100 specific tweaks. This is merged into head.S by the linker.
*

View file

@ -19,31 +19,21 @@
#ifdef __KERNEL__
/*
* On ARM, ordinary assignment (str instruction) doesn't clear the local
* strex/ldrex monitor on some implementations. The reason we can use it for
* atomic_set() is the clrex or dummy strex done on every exception return.
*/
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
#if __LINUX_ARM_ARCH__ >= 6
/*
* ARMv6 UP and SMP safe atomic ops. We use load exclusive and
* store exclusive to ensure that these are atomic. We may loop
* to ensure that the update happens. Writing to 'v->counter'
* without using the following operations WILL break the atomic
* nature of these ops.
* to ensure that the update happens.
*/
static inline void atomic_set(atomic_t *v, int i)
{
unsigned long tmp;
__asm__ __volatile__("@ atomic_set\n"
"1: ldrex %0, [%1]\n"
" strex %0, %2, [%1]\n"
" teq %0, #0\n"
" bne 1b"
: "=&r" (tmp)
: "r" (&v->counter), "r" (i)
: "cc");
}
static inline void atomic_add(int i, atomic_t *v)
{
unsigned long tmp;
@ -163,8 +153,6 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
#error SMP not supported on pre-ARMv6 CPUs
#endif
#define atomic_set(v,i) (((v)->counter) = (i))
static inline int atomic_add_return(int i, atomic_t *v)
{
unsigned long flags;

View file

@ -6,8 +6,6 @@
#include <mach/hardware.h> /* for PCIBIOS_MIN_* */
#define pcibios_scan_all_fns(a, b) 0
#ifdef CONFIG_PCI_HOST_ITE8152
/* ITE bridge requires setting latency timer to avoid early bus access
termination by PIC bus mater devices

View file

@ -35,7 +35,9 @@
#define ARM(x...)
#define THUMB(x...) x
#ifdef __ASSEMBLY__
#define W(instr) instr.w
#endif
#define BSYM(sym) sym + 1
#else /* !CONFIG_THUMB2_KERNEL */
@ -45,7 +47,9 @@
#define ARM(x...) x
#define THUMB(x...)
#ifdef __ASSEMBLY__
#define W(instr) instr
#endif
#define BSYM(sym) sym
#endif /* CONFIG_THUMB2_KERNEL */

View file

@ -272,7 +272,15 @@ __und_svc:
@
@ r0 - instruction
@
#ifndef CONFIG_THUMB2_KERNEL
ldr r0, [r2, #-4]
#else
ldrh r0, [r2, #-2] @ Thumb instruction at LR - 2
and r9, r0, #0xf800
cmp r9, #0xe800 @ 32-bit instruction if xx >= 0
ldrhhs r9, [r2] @ bottom 16 bits
orrhs r0, r9, r0, lsl #16
#endif
adr r9, BSYM(1f)
bl call_fpe
@ -678,7 +686,9 @@ ENTRY(fp_enter)
.word no_fp
.previous
no_fp: mov pc, lr
ENTRY(no_fp)
mov pc, lr
ENDPROC(no_fp)
__und_usr_unknown:
enable_irq
@ -734,13 +744,6 @@ ENTRY(__switch_to)
#ifdef CONFIG_MMU
ldr r6, [r2, #TI_CPU_DOMAIN]
#endif
#if __LINUX_ARM_ARCH__ >= 6
#ifdef CONFIG_CPU_32v6K
clrex
#else
strex r5, r4, [ip] @ Clear exclusive monitor
#endif
#endif
#if defined(CONFIG_HAS_TLS_REG)
mcr p15, 0, r3, c13, c0, 3 @ set TLS register
#elif !defined(CONFIG_TLS_REG_EMUL)

View file

@ -76,13 +76,25 @@
#ifndef CONFIG_THUMB2_KERNEL
.macro svc_exit, rpsr
msr spsr_cxsf, \rpsr
#if defined(CONFIG_CPU_32v6K)
clrex @ clear the exclusive monitor
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
#elif defined (CONFIG_CPU_V6)
ldr r0, [sp]
strex r1, r2, [sp] @ clear the exclusive monitor
ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr
#endif
.endm
.macro restore_user_regs, fast = 0, offset = 0
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
ldr lr, [sp, #\offset + S_PC]! @ get pc
msr spsr_cxsf, r1 @ save in spsr_svc
#if defined(CONFIG_CPU_32v6K)
clrex @ clear the exclusive monitor
#elif defined (CONFIG_CPU_V6)
strex r1, r2, [sp] @ clear the exclusive monitor
#endif
.if \fast
ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
.else
@ -98,6 +110,7 @@
.endm
#else /* CONFIG_THUMB2_KERNEL */
.macro svc_exit, rpsr
clrex @ clear the exclusive monitor
ldr r0, [sp, #S_SP] @ top of the stack
ldr r1, [sp, #S_PC] @ return address
tst r0, #4 @ orig stack 8-byte aligned?
@ -110,6 +123,7 @@
.endm
.macro restore_user_regs, fast = 0, offset = 0
clrex @ clear the exclusive monitor
mov r2, sp
load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr

View file

@ -83,6 +83,7 @@ SECTIONS
EXIT_TEXT
EXIT_DATA
*(.exitcall.exit)
*(.discard)
*(.ARM.exidx.exit.text)
*(.ARM.extab.exit.text)
#ifndef CONFIG_HOTPLUG_CPU

View file

@ -1,7 +1,7 @@
/*
* linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
*
* Author: Nicolas Pitre <nico@cam.org>
* Author: Nicolas Pitre <nico@fluxnic.net>
* - contributed to gcc-3.4 on Sep 30, 2003
* - adapted for the Linux kernel on Oct 2, 2003
*/

View file

@ -3,7 +3,7 @@
*
* SHA transform optimized for ARM
*
* Copyright: (C) 2005 by Nicolas Pitre <nico@cam.org>
* Copyright: (C) 2005 by Nicolas Pitre <nico@fluxnic.net>
* Created: September 17, 2005
*
* This program is free software; you can redistribute it and/or modify

View file

@ -1,7 +1,7 @@
/*
* arch/arm/mach-sa1100/include/mach/assabet.h
*
* Created 2000/06/05 by Nicolas Pitre <nico@cam.org>
* Created 2000/06/05 by Nicolas Pitre <nico@fluxnic.net>
*
* This file contains the hardware specific definitions for Assabet
* Only include this file from SA1100-specific files.

View file

@ -1,7 +1,7 @@
/*
* arch/arm/mach-sa1100/include/mach/hardware.h
*
* Copyright (C) 1998 Nicolas Pitre <nico@cam.org>
* Copyright (C) 1998 Nicolas Pitre <nico@fluxnic.net>
*
* This file contains the hardware definitions for SA1100 architecture
*

View file

@ -1,7 +1,7 @@
/*
* arch/arm/mach-sa1100/include/mach/memory.h
*
* Copyright (C) 1999-2000 Nicolas Pitre <nico@cam.org>
* Copyright (C) 1999-2000 Nicolas Pitre <nico@fluxnic.net>
*/
#ifndef __ASM_ARCH_MEMORY_H

View file

@ -1,7 +1,7 @@
/*
* arch/arm/mach-sa1100/include/mach/neponset.h
*
* Created 2000/06/05 by Nicolas Pitre <nico@cam.org>
* Created 2000/06/05 by Nicolas Pitre <nico@fluxnic.net>
*
* This file contains the hardware specific definitions for Assabet
* Only include this file from SA1100-specific files.

View file

@ -1,7 +1,7 @@
/*
* arch/arm/mach-sa1100/include/mach/system.h
*
* Copyright (c) 1999 Nicolas Pitre <nico@cam.org>
* Copyright (c) 1999 Nicolas Pitre <nico@fluxnic.net>
*/
#include <mach/hardware.h>

View file

@ -1,7 +1,7 @@
/*
* arch/arm/mach-sa1100/include/mach/uncompress.h
*
* (C) 1999 Nicolas Pitre <nico@cam.org>
* (C) 1999 Nicolas Pitre <nico@fluxnic.net>
*
* Reorganised to be machine independent.
*/

View file

@ -15,7 +15,7 @@
* Save more value for the resume function! Support
* Bitsy/Assabet/Freebird board
*
* 2001-08-29: Nicolas Pitre <nico@cam.org>
* 2001-08-29: Nicolas Pitre <nico@fluxnic.net>
* Cleaned up, pushed platform dependent stuff
* in the platform specific files.
*

View file

@ -4,7 +4,7 @@
* Copyright (C) 1998 Deborah Wallach.
* Twiddles (C) 1999 Hugo Fiennes <hugo@empeg.com>
*
* 2000/03/29 (C) Nicolas Pitre <nico@cam.org>
* 2000/03/29 (C) Nicolas Pitre <nico@fluxnic.net>
* Rewritten: big cleanup, much simpler, better HZ accuracy.
*
*/

View file

@ -17,7 +17,7 @@
*
* 2001 Sep 08:
* Completely revisited, many important fixes
* Nicolas Pitre <nico@cam.org>
* Nicolas Pitre <nico@fluxnic.net>
*/
#include <linux/linkage.h>

View file

@ -1,7 +1,7 @@
/*
* arch/arm/plat-iop/setup.c
*
* Author: Nicolas Pitre <nico@cam.org>
* Author: Nicolas Pitre <nico@fluxnic.net>
* Copyright (C) 2001 MontaVista Software, Inc.
* Copyright (C) 2004 Intel Corporation.
*

View file

@ -1,6 +1,6 @@
/*
* Copied from arch/arm/mach-sa1100/include/mach/system.h
* Copyright (c) 1999 Nicolas Pitre <nico@cam.org>
* Copyright (c) 1999 Nicolas Pitre <nico@fluxnic.net>
*/
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H

View file

@ -124,14 +124,11 @@ SECTIONS
_end = .;
}
DWARF_DEBUG
/* When something in the kernel is NOT compiled as a module, the module
* cleanup code and data are put into these segments. Both can then be
* thrown away, as cleanup code is never called unless it's a module.
*/
/DISCARD/ : {
EXIT_DATA
*(.exitcall.exit)
}
DWARF_DEBUG
DISCARDS
}

View file

@ -342,8 +342,9 @@ config MEM_MT48LC64M4A2FB_7E
config MEM_MT48LC16M16A2TG_75
bool
depends on (BFIN533_EZKIT || BFIN561_EZKIT \
|| BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM \
|| H8606_HVSISTEMAS || BFIN527_BLUETECHNIX_CM)
|| BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM_E \
|| BFIN537_BLUETECHNIX_CM_U || H8606_HVSISTEMAS \
|| BFIN527_BLUETECHNIX_CM)
default y
config MEM_MT48LC32M8A2_75
@ -459,7 +460,7 @@ config VCO_MULT
default "45" if BFIN533_STAMP
default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM || BFIN538_EZKIT)
default "22" if BFIN533_BLUETECHNIX_CM
default "20" if (BFIN537_BLUETECHNIX_CM || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM)
default "20" if (BFIN537_BLUETECHNIX_CM_E || BFIN537_BLUETECHNIX_CM_U || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM)
default "20" if BFIN561_EZKIT
default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN518F_EZBRD)
help
@ -574,8 +575,8 @@ config MAX_VCO_HZ
default 400000000 if BF514
default 400000000 if BF516
default 400000000 if BF518
default 600000000 if BF522
default 400000000 if BF523
default 400000000 if BF522
default 600000000 if BF523
default 400000000 if BF524
default 600000000 if BF525
default 400000000 if BF526
@ -647,7 +648,7 @@ config CYCLES_CLOCKSOURCE
writing the registers will most likely crash the kernel.
config GPTMR0_CLOCKSOURCE
bool "Use GPTimer0 as a clocksource (higher rating)"
bool "Use GPTimer0 as a clocksource"
select BFIN_GPTIMERS
depends on GENERIC_CLOCKEVENTS
depends on !TICKSOURCE_GPTMR0
@ -917,10 +918,6 @@ comment "Cache Support"
config BFIN_ICACHE
bool "Enable ICACHE"
default y
config BFIN_ICACHE_LOCK
bool "Enable Instruction Cache Locking"
depends on BFIN_ICACHE
default n
config BFIN_EXTMEM_ICACHEABLE
bool "Enable ICACHE for external memory"
depends on BFIN_ICACHE
@ -987,7 +984,7 @@ endchoice
config BFIN_L2_DCACHEABLE
bool "Enable DCACHE for L2 SRAM"
depends on BFIN_DCACHE
depends on BF54x || BF561
depends on (BF54x || BF561) && !SMP
default n
choice
prompt "L2 SRAM DCACHE policy"
@ -995,11 +992,9 @@ choice
default BFIN_L2_WRITEBACK
config BFIN_L2_WRITEBACK
bool "Write back"
depends on !SMP
config BFIN_L2_WRITETHROUGH
bool "Write through"
depends on !SMP
endchoice
@ -1154,11 +1149,12 @@ source "fs/Kconfig.binfmt"
endmenu
menu "Power management options"
depends on !SMP
source "kernel/power/Kconfig"
config ARCH_SUSPEND_POSSIBLE
def_bool y
depends on !SMP
choice
prompt "Standby Power Saving Mode"
@ -1246,6 +1242,7 @@ config PM_BFIN_WAKE_GP
endmenu
menu "CPU Frequency scaling"
depends on !SMP
source "drivers/cpufreq/Kconfig"

View file

@ -252,4 +252,10 @@ config ACCESS_CHECK
Say N here to disable that check to improve the performance.
config BFIN_ISRAM_SELF_TEST
bool "isram boot self tests"
default n
help
Run some self tests of the isram driver code at boot.
endmenu

View file

@ -358,9 +358,9 @@ CONFIG_C_AMBEN_ALL=y
# EBIU_AMBCTL Control
#
CONFIG_BANK_0=0x7BB0
CONFIG_BANK_1=0x5554
CONFIG_BANK_1=0x7BB0
CONFIG_BANK_2=0x7BB0
CONFIG_BANK_3=0xFFC0
CONFIG_BANK_3=0x99B2
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)

View file

@ -359,9 +359,9 @@ CONFIG_C_AMBEN_ALL=y
# EBIU_AMBCTL Control
#
CONFIG_BANK_0=0x7BB0
CONFIG_BANK_1=0x5554
CONFIG_BANK_1=0x7BB0
CONFIG_BANK_2=0x7BB0
CONFIG_BANK_3=0xFFC0
CONFIG_BANK_3=0x99B2
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)

View file

@ -363,9 +363,9 @@ CONFIG_C_AMBEN_ALL=y
# EBIU_AMBCTL Control
#
CONFIG_BANK_0=0x7BB0
CONFIG_BANK_1=0x5554
CONFIG_BANK_1=0x7BB0
CONFIG_BANK_2=0x7BB0
CONFIG_BANK_3=0xFFC0
CONFIG_BANK_3=0x99B2
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)

View file

@ -400,7 +400,7 @@ CONFIG_C_AMBEN_ALL=y
# EBIU_AMBCTL Control
#
CONFIG_BANK_0=0x7BB0
CONFIG_BANK_1=0x5554
CONFIG_BANK_1=0x7BB0
CONFIG_BANK_2=0x7BB0
CONFIG_BANK_3=0x99B2
CONFIG_EBIU_MBSCTLVAL=0x0

View file

@ -66,7 +66,6 @@ extern void program_IAR(void);
extern asmlinkage void lower_to_irq14(void);
extern asmlinkage void bfin_return_from_exception(void);
extern asmlinkage void evt14_softirq(void);
extern asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs);
extern int bfin_internal_set_wake(unsigned int irq, unsigned int state);
@ -100,11 +99,6 @@ extern unsigned long bfin_sic_iwr[];
extern unsigned vr_wakeup;
extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */
#ifdef CONFIG_BFIN_ICACHE_LOCK
extern void cache_grab_lock(int way);
extern void bfin_cache_lock(int way);
#endif
#endif
#endif /* _BLACKFIN_H_ */

View file

@ -127,6 +127,7 @@ struct bfin5xx_spi_chip {
u32 cs_gpio;
/* Value to send if no TX value is supplied, usually 0x0 or 0xFFFF */
u16 idle_tx_val;
u8 pio_interrupt; /* Enable spi data irq */
};
#endif /* _SPI_CHANNEL_H_ */

View file

@ -125,4 +125,48 @@
#define FAULT_USERSUPV (1 << 17)
#define FAULT_CPLBBITS 0x0000ffff
#endif /* _CPLB_H */
#ifndef __ASSEMBLY__
static inline void _disable_cplb(u32 mmr, u32 mask)
{
u32 ctrl = bfin_read32(mmr) & ~mask;
/* CSYNC to ensure load store ordering */
__builtin_bfin_csync();
bfin_write32(mmr, ctrl);
__builtin_bfin_ssync();
}
static inline void disable_cplb(u32 mmr, u32 mask)
{
u32 ctrl = bfin_read32(mmr) & ~mask;
CSYNC();
bfin_write32(mmr, ctrl);
SSYNC();
}
#define _disable_dcplb() _disable_cplb(DMEM_CONTROL, ENDCPLB)
#define disable_dcplb() disable_cplb(DMEM_CONTROL, ENDCPLB)
#define _disable_icplb() _disable_cplb(IMEM_CONTROL, ENICPLB)
#define disable_icplb() disable_cplb(IMEM_CONTROL, ENICPLB)
static inline void _enable_cplb(u32 mmr, u32 mask)
{
u32 ctrl = bfin_read32(mmr) | mask;
/* CSYNC to ensure load store ordering */
__builtin_bfin_csync();
bfin_write32(mmr, ctrl);
__builtin_bfin_ssync();
}
static inline void enable_cplb(u32 mmr, u32 mask)
{
u32 ctrl = bfin_read32(mmr) | mask;
CSYNC();
bfin_write32(mmr, ctrl);
SSYNC();
}
#define _enable_dcplb() _enable_cplb(DMEM_CONTROL, ENDCPLB)
#define enable_dcplb() enable_cplb(DMEM_CONTROL, ENDCPLB)
#define _enable_icplb() _enable_cplb(IMEM_CONTROL, ENICPLB)
#define enable_icplb() enable_cplb(IMEM_CONTROL, ENICPLB)
#endif /* __ASSEMBLY__ */
#endif /* _CPLB_H */

View file

@ -21,8 +21,32 @@
* GNU General Public License for more details.
*/
#ifndef __ASM_EARLY_PRINTK_H__
#define __ASM_EARLY_PRINTK_H__
#ifdef CONFIG_EARLY_PRINTK
/* For those that don't include it already */
#include <linux/console.h>
extern int setup_early_printk(char *);
extern void enable_shadow_console(void);
extern int shadow_console_enabled(void);
extern void mark_shadow_error(void);
extern void early_shadow_reg(unsigned long reg, unsigned int n);
extern void early_shadow_write(struct console *con, const char *s,
unsigned int n) __attribute__((nonnull(2)));
#define early_shadow_puts(str) early_shadow_write(NULL, str, strlen(str))
#define early_shadow_stamp() \
do { \
early_shadow_puts(__FILE__ " : " __stringify(__LINE__) " ["); \
early_shadow_puts(__func__); \
early_shadow_puts("]\n"); \
} while (0)
#else
#define setup_early_printk(fmt) do { } while (0)
#define enable_shadow_console(fmt) do { } while (0)
#define early_shadow_stamp() do { } while (0)
#endif /* CONFIG_EARLY_PRINTK */
#endif /* __ASM_EARLY_PRINTK_H__ */

View file

@ -23,7 +23,7 @@ typedef unsigned long elf_greg_t;
#define ELF_NGREG 40 /* (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) */
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
typedef struct user_bfinfp_struct elf_fpregset_t;
typedef struct { } elf_fpregset_t;
/*
* This is used to ensure we don't load something for the wrong architecture.
*/

View file

@ -36,6 +36,21 @@
# define LOAD_IPIPE_IPEND
#endif
/*
* Workaround for anomalies 05000283 and 05000315
*/
#if ANOMALY_05000283 || ANOMALY_05000315
# define ANOMALY_283_315_WORKAROUND(preg, dreg) \
cc = dreg == dreg; \
preg.h = HI(CHIPID); \
preg.l = LO(CHIPID); \
if cc jump 1f; \
dreg.l = W[preg]; \
1:
#else
# define ANOMALY_283_315_WORKAROUND(preg, dreg)
#endif /* ANOMALY_05000283 || ANOMALY_05000315 */
#ifndef CONFIG_EXACT_HWERR
/* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
* otherwise it is a waste of cycles.
@ -88,17 +103,22 @@
* As you can see by the code - we actually need to do two SSYNCS - one to
* make sure the read/writes complete, and another to make sure the hardware
* error is recognized by the core.
*
* The extra nop before the SSYNC is to make sure we work around 05000244,
* since the 283/315 workaround includes a branch to the end
*/
#define INTERRUPT_ENTRY(N) \
SSYNC; \
SSYNC; \
[--sp] = SYSCFG; \
[--sp] = P0; /*orig_p0*/ \
[--sp] = R0; /*orig_r0*/ \
[--sp] = (R7:0,P5:0); \
R1 = ASTAT; \
ANOMALY_283_315_WORKAROUND(p0, r0) \
P0.L = LO(ILAT); \
P0.H = HI(ILAT); \
NOP; \
SSYNC; \
SSYNC; \
R0 = [P0]; \
CC = BITTST(R0, EVT_IVHW_P); \
IF CC JUMP 1f; \
@ -118,15 +138,17 @@
RTI;
#define TIMER_INTERRUPT_ENTRY(N) \
SSYNC; \
SSYNC; \
[--sp] = SYSCFG; \
[--sp] = P0; /*orig_p0*/ \
[--sp] = R0; /*orig_r0*/ \
[--sp] = (R7:0,P5:0); \
R1 = ASTAT; \
ANOMALY_283_315_WORKAROUND(p0, r0) \
P0.L = LO(ILAT); \
P0.H = HI(ILAT); \
NOP; \
SSYNC; \
SSYNC; \
R0 = [P0]; \
CC = BITTST(R0, EVT_IVHW_P); \
IF CC JUMP 1f; \

View file

@ -8,6 +8,6 @@
#ifndef __ASM_BFIN_FTRACE_H__
#define __ASM_BFIN_FTRACE_H__
#define MCOUNT_INSN_SIZE 8 /* sizeof mcount call: LINK + CALL */
#define MCOUNT_INSN_SIZE 6 /* sizeof "[++sp] = rets; call __mcount;" */
#endif

View file

@ -145,10 +145,6 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs);
int __ipipe_get_irq_priority(unsigned irq);
void __ipipe_stall_root_raw(void);
void __ipipe_unstall_root_raw(void);
void __ipipe_serial_debug(const char *fmt, ...);
asmlinkage void __ipipe_call_irqtail(unsigned long addr);
@ -234,9 +230,6 @@ int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
#define task_hijacked(p) 0
#define ipipe_trap_notify(t, r) 0
#define __ipipe_stall_root_raw() do { } while (0)
#define __ipipe_unstall_root_raw() do { } while (0)
#define ipipe_init_irq_threads() do { } while (0)
#define ipipe_start_irq_thread(irq, desc) 0

View file

@ -17,6 +17,7 @@ asmlinkage void evt_evt10(void);
asmlinkage void evt_evt11(void);
asmlinkage void evt_evt12(void);
asmlinkage void evt_evt13(void);
asmlinkage void evt_evt14(void);
asmlinkage void evt_soft_int1(void);
asmlinkage void evt_system_call(void);
asmlinkage void init_exception_buff(void);

View file

@ -127,17 +127,17 @@ static inline void protect_page(struct mm_struct *mm, unsigned long addr,
unsigned long idx = page >> 5;
unsigned long bit = 1 << (page & 31);
if (flags & VM_MAYREAD)
if (flags & VM_READ)
mask[idx] |= bit;
else
mask[idx] &= ~bit;
mask += page_mask_nelts;
if (flags & VM_MAYWRITE)
if (flags & VM_WRITE)
mask[idx] |= bit;
else
mask[idx] &= ~bit;
mask += page_mask_nelts;
if (flags & VM_MAYEXEC)
if (flags & VM_EXEC)
mask[idx] |= bit;
else
mask[idx] &= ~bit;

View file

@ -50,6 +50,7 @@ struct blackfin_pda { /* Per-processor Data Area */
unsigned long ex_optr;
unsigned long ex_buf[4];
unsigned long ex_imask; /* Saved imask from exception */
unsigned long ex_ipend; /* Saved IPEND from exception */
unsigned long *ex_stack; /* Exception stack space */
#ifdef ANOMALY_05000261
@ -60,6 +61,12 @@ struct blackfin_pda { /* Per-processor Data Area */
unsigned long retx;
unsigned long seqstat;
unsigned int __nmi_count; /* number of times NMI asserted on this CPU */
#ifdef CONFIG_DEBUG_DOUBLEFAULT
unsigned long dcplb_doublefault_addr;
unsigned long icplb_doublefault_addr;
unsigned long retx_doublefault;
unsigned long seqstat_doublefault;
#endif
};
extern struct blackfin_pda cpu_pda[];

View file

@ -26,6 +26,7 @@ obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_EARLY_PRINTK) += shadow_console.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
# the kgdb test puts code into L2 and without linker

View file

@ -145,6 +145,7 @@ int main(void)
DEFINE(PDA_EXBUF, offsetof(struct blackfin_pda, ex_buf));
DEFINE(PDA_EXIMASK, offsetof(struct blackfin_pda, ex_imask));
DEFINE(PDA_EXSTACK, offsetof(struct blackfin_pda, ex_stack));
DEFINE(PDA_EXIPEND, offsetof(struct blackfin_pda, ex_ipend));
#ifdef ANOMALY_05000261
DEFINE(PDA_LFRETX, offsetof(struct blackfin_pda, last_cplb_fault_retx));
#endif
@ -152,6 +153,12 @@ int main(void)
DEFINE(PDA_ICPLB, offsetof(struct blackfin_pda, icplb_fault_addr));
DEFINE(PDA_RETX, offsetof(struct blackfin_pda, retx));
DEFINE(PDA_SEQSTAT, offsetof(struct blackfin_pda, seqstat));
#ifdef CONFIG_DEBUG_DOUBLEFAULT
DEFINE(PDA_DF_DCPLB, offsetof(struct blackfin_pda, dcplb_doublefault_addr));
DEFINE(PDA_DF_ICPLB, offsetof(struct blackfin_pda, icplb_doublefault_addr));
DEFINE(PDA_DF_SEQSTAT, offsetof(struct blackfin_pda, seqstat_doublefault));
DEFINE(PDA_DF_RETX, offsetof(struct blackfin_pda, retx_doublefault));
#endif
#ifdef CONFIG_SMP
/* Inter-core lock (in L2 SRAM) */
DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot));

View file

@ -19,6 +19,7 @@
#include <asm/cacheflush.h>
#include <asm/dma.h>
#include <asm/uaccess.h>
#include <asm/early_printk.h>
/*
* To make sure we work around 05000119 - we always check DMA_DONE bit,
@ -146,8 +147,8 @@ EXPORT_SYMBOL(request_dma);
int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data)
{
BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
&& channel < MAX_DMA_CHANNELS));
BUG_ON(channel >= MAX_DMA_CHANNELS ||
dma_ch[channel].chan_status == DMA_CHANNEL_FREE);
if (callback != NULL) {
int ret;
@ -181,8 +182,8 @@ static void clear_dma_buffer(unsigned int channel)
void free_dma(unsigned int channel)
{
pr_debug("freedma() : BEGIN \n");
BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
&& channel < MAX_DMA_CHANNELS));
BUG_ON(channel >= MAX_DMA_CHANNELS ||
dma_ch[channel].chan_status == DMA_CHANNEL_FREE);
/* Halt the DMA */
disable_dma(channel);
@ -236,6 +237,7 @@ void blackfin_dma_resume(void)
*/
void __init blackfin_dma_early_init(void)
{
early_shadow_stamp();
bfin_write_MDMA_S0_CONFIG(0);
bfin_write_MDMA_S1_CONFIG(0);
}
@ -246,6 +248,8 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size)
unsigned long src = (unsigned long)psrc;
struct dma_register *dst_ch, *src_ch;
early_shadow_stamp();
/* We assume that everything is 4 byte aligned, so include
* a basic sanity check
*/
@ -300,6 +304,8 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size)
void __init early_dma_memcpy_done(void)
{
early_shadow_stamp();
while ((bfin_read_MDMA_S0_CONFIG() && !(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) ||
(bfin_read_MDMA_S1_CONFIG() && !(bfin_read_MDMA_D1_IRQ_STATUS() & DMA_DONE)))
continue;

View file

@ -722,7 +722,6 @@ void bfin_gpio_pm_hibernate_suspend(void)
gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
gpio_bank_saved[bank].data = gpio_array[bank]->data;
gpio_bank_saved[bank].data = gpio_array[bank]->data;
gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;
}

View file

@ -2,7 +2,7 @@
# arch/blackfin/kernel/cplb-nompu/Makefile
#
obj-y := cplbinit.o cacheinit.o cplbmgr.o
obj-y := cplbinit.o cplbmgr.o
CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \
-ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \

View file

@ -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

View file

@ -22,6 +22,7 @@
#include <asm/blackfin.h>
#include <asm/cacheflush.h>
#include <asm/cplb.h>
#include <asm/cplbinit.h>
#include <asm/mmu_context.h>
@ -41,46 +42,6 @@ int nr_dcplb_miss[NR_CPUS], nr_icplb_miss[NR_CPUS];
int nr_icplb_supv_miss[NR_CPUS], nr_dcplb_prot[NR_CPUS];
int nr_cplb_flush[NR_CPUS];
static inline void disable_dcplb(void)
{
unsigned long ctrl;
SSYNC();
ctrl = bfin_read_DMEM_CONTROL();
ctrl &= ~ENDCPLB;
bfin_write_DMEM_CONTROL(ctrl);
SSYNC();
}
static inline void enable_dcplb(void)
{
unsigned long ctrl;
SSYNC();
ctrl = bfin_read_DMEM_CONTROL();
ctrl |= ENDCPLB;
bfin_write_DMEM_CONTROL(ctrl);
SSYNC();
}
static inline void disable_icplb(void)
{
unsigned long ctrl;
SSYNC();
ctrl = bfin_read_IMEM_CONTROL();
ctrl &= ~ENICPLB;
bfin_write_IMEM_CONTROL(ctrl);
SSYNC();
}
static inline void enable_icplb(void)
{
unsigned long ctrl;
SSYNC();
ctrl = bfin_read_IMEM_CONTROL();
ctrl |= ENICPLB;
bfin_write_IMEM_CONTROL(ctrl);
SSYNC();
}
/*
* Given the contents of the status register, return the index of the
* CPLB that caused the fault.
@ -198,10 +159,10 @@ static noinline int dcplb_miss(unsigned int cpu)
dcplb_tbl[cpu][idx].addr = addr;
dcplb_tbl[cpu][idx].data = d_data;
disable_dcplb();
_disable_dcplb();
bfin_write32(DCPLB_DATA0 + idx * 4, d_data);
bfin_write32(DCPLB_ADDR0 + idx * 4, addr);
enable_dcplb();
_enable_dcplb();
return 0;
}
@ -288,10 +249,10 @@ static noinline int icplb_miss(unsigned int cpu)
icplb_tbl[cpu][idx].addr = addr;
icplb_tbl[cpu][idx].data = i_data;
disable_icplb();
_disable_icplb();
bfin_write32(ICPLB_DATA0 + idx * 4, i_data);
bfin_write32(ICPLB_ADDR0 + idx * 4, addr);
enable_icplb();
_enable_icplb();
return 0;
}
@ -319,7 +280,7 @@ static noinline int dcplb_protection_fault(unsigned int cpu)
int cplb_hdr(int seqstat, struct pt_regs *regs)
{
int cause = seqstat & 0x3f;
unsigned int cpu = smp_processor_id();
unsigned int cpu = raw_smp_processor_id();
switch (cause) {
case 0x23:
return dcplb_protection_fault(cpu);
@ -340,19 +301,19 @@ void flush_switched_cplbs(unsigned int cpu)
nr_cplb_flush[cpu]++;
local_irq_save_hw(flags);
disable_icplb();
_disable_icplb();
for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
icplb_tbl[cpu][i].data = 0;
bfin_write32(ICPLB_DATA0 + i * 4, 0);
}
enable_icplb();
_enable_icplb();
disable_dcplb();
_disable_dcplb();
for (i = first_switched_dcplb; i < MAX_CPLBS; i++) {
dcplb_tbl[cpu][i].data = 0;
bfin_write32(DCPLB_DATA0 + i * 4, 0);
}
enable_dcplb();
_enable_dcplb();
local_irq_restore_hw(flags);
}
@ -385,7 +346,7 @@ void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
#endif
}
disable_dcplb();
_disable_dcplb();
for (i = first_mask_dcplb; i < first_switched_dcplb; i++) {
dcplb_tbl[cpu][i].addr = addr;
dcplb_tbl[cpu][i].data = d_data;
@ -393,6 +354,6 @@ void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
bfin_write32(DCPLB_ADDR0 + i * 4, addr);
addr += PAGE_SIZE;
}
enable_dcplb();
_enable_dcplb();
local_irq_restore_hw(flags);
}

View file

@ -2,7 +2,7 @@
# arch/blackfin/kernel/cplb-nompu/Makefile
#
obj-y := cplbinit.o cacheinit.o cplbmgr.o
obj-y := cplbinit.o cplbmgr.o
CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \
-ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \

View file

@ -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

View file

@ -36,7 +36,7 @@ int first_switched_icplb PDT_ATTR;
int first_switched_dcplb PDT_ATTR;
struct cplb_boundary dcplb_bounds[9] PDT_ATTR;
struct cplb_boundary icplb_bounds[7] PDT_ATTR;
struct cplb_boundary icplb_bounds[9] PDT_ATTR;
int icplb_nr_bounds PDT_ATTR;
int dcplb_nr_bounds PDT_ATTR;
@ -167,14 +167,21 @@ void __init generate_cplb_tables_all(void)
icplb_bounds[i_i++].data = (reserved_mem_icache_on ?
SDRAM_IGENERIC : SDRAM_INON_CHBL);
}
/* Addressing hole up to the async bank. */
icplb_bounds[i_i].eaddr = ASYNC_BANK0_BASE;
icplb_bounds[i_i++].data = 0;
/* ASYNC banks. */
icplb_bounds[i_i].eaddr = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE;
icplb_bounds[i_i++].data = SDRAM_EBIU;
/* Addressing hole up to BootROM. */
icplb_bounds[i_i].eaddr = BOOT_ROM_START;
icplb_bounds[i_i++].data = 0;
/* BootROM -- largest one should be less than 1 meg. */
icplb_bounds[i_i].eaddr = BOOT_ROM_START + (1 * 1024 * 1024);
icplb_bounds[i_i++].data = SDRAM_IGENERIC;
if (L2_LENGTH) {
/* Addressing hole up to L2 SRAM, including the async bank. */
/* Addressing hole up to L2 SRAM. */
icplb_bounds[i_i].eaddr = L2_START;
icplb_bounds[i_i++].data = 0;
/* L2 SRAM. */

View file

@ -48,36 +48,13 @@ int nr_cplb_flush[NR_CPUS], nr_dcplb_prot[NR_CPUS];
#define MGR_ATTR
#endif
/*
* We're in an exception handler. The normal cli nop nop workaround
* isn't going to do very much, as the only thing that can interrupt
* us is an NMI, and the cli isn't going to stop that.
*/
#define NOWA_SSYNC __asm__ __volatile__ ("ssync;")
/* Anomaly handlers provide SSYNCs, so avoid extra if anomaly is present */
#if ANOMALY_05000125
#define bfin_write_DMEM_CONTROL_SSYNC(v) bfin_write_DMEM_CONTROL(v)
#define bfin_write_IMEM_CONTROL_SSYNC(v) bfin_write_IMEM_CONTROL(v)
#else
#define bfin_write_DMEM_CONTROL_SSYNC(v) \
do { NOWA_SSYNC; bfin_write_DMEM_CONTROL(v); NOWA_SSYNC; } while (0)
#define bfin_write_IMEM_CONTROL_SSYNC(v) \
do { NOWA_SSYNC; bfin_write_IMEM_CONTROL(v); NOWA_SSYNC; } while (0)
#endif
static inline void write_dcplb_data(int cpu, int idx, unsigned long data,
unsigned long addr)
{
unsigned long ctrl = bfin_read_DMEM_CONTROL();
bfin_write_DMEM_CONTROL_SSYNC(ctrl & ~ENDCPLB);
_disable_dcplb();
bfin_write32(DCPLB_DATA0 + idx * 4, data);
bfin_write32(DCPLB_ADDR0 + idx * 4, addr);
bfin_write_DMEM_CONTROL_SSYNC(ctrl);
_enable_dcplb();
#ifdef CONFIG_CPLB_INFO
dcplb_tbl[cpu][idx].addr = addr;
@ -88,12 +65,10 @@ static inline void write_dcplb_data(int cpu, int idx, unsigned long data,
static inline void write_icplb_data(int cpu, int idx, unsigned long data,
unsigned long addr)
{
unsigned long ctrl = bfin_read_IMEM_CONTROL();
bfin_write_IMEM_CONTROL_SSYNC(ctrl & ~ENICPLB);
_disable_icplb();
bfin_write32(ICPLB_DATA0 + idx * 4, data);
bfin_write32(ICPLB_ADDR0 + idx * 4, addr);
bfin_write_IMEM_CONTROL_SSYNC(ctrl);
_enable_icplb();
#ifdef CONFIG_CPLB_INFO
icplb_tbl[cpu][idx].addr = addr;
@ -227,7 +202,7 @@ MGR_ATTR static int dcplb_miss(int cpu)
MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs)
{
int cause = seqstat & 0x3f;
unsigned int cpu = smp_processor_id();
unsigned int cpu = raw_smp_processor_id();
switch (cause) {
case VEC_CPLB_I_M:
return icplb_miss(cpu);

View file

@ -27,6 +27,7 @@
#include <linux/serial_core.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/reboot.h>
#include <asm/blackfin.h>
#include <asm/irq_handler.h>
#include <asm/early_printk.h>
@ -181,6 +182,22 @@ asmlinkage void __init init_early_exception_vectors(void)
u32 evt;
SSYNC();
/*
* This starts up the shadow buffer, incase anything crashes before
* setup arch
*/
mark_shadow_error();
early_shadow_puts(linux_banner);
early_shadow_stamp();
if (CPUID != bfin_cpuid()) {
early_shadow_puts("Running on wrong machine type, expected");
early_shadow_reg(CPUID, 16);
early_shadow_puts(", but running on");
early_shadow_reg(bfin_cpuid(), 16);
early_shadow_puts("\n");
}
/* cannot program in software:
* evt0 - emulation (jtag)
* evt1 - reset
@ -199,6 +216,7 @@ asmlinkage void __init init_early_exception_vectors(void)
}
__attribute__((__noreturn__))
asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)
{
/* This can happen before the uart is initialized, so initialize
@ -210,10 +228,58 @@ asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)
if (likely(early_console == NULL) && CPUID == bfin_cpuid())
setup_early_printk(DEFAULT_EARLY_PORT);
printk(KERN_EMERG "Early panic\n");
dump_bfin_mem(fp);
show_regs(fp);
dump_bfin_trace_buffer();
if (!shadow_console_enabled()) {
/* crap - we crashed before setup_arch() */
early_shadow_puts("panic before setup_arch\n");
early_shadow_puts("IPEND:");
early_shadow_reg(fp->ipend, 16);
if (fp->seqstat & SEQSTAT_EXCAUSE) {
early_shadow_puts("\nEXCAUSE:");
early_shadow_reg(fp->seqstat & SEQSTAT_EXCAUSE, 8);
}
if (fp->seqstat & SEQSTAT_HWERRCAUSE) {
early_shadow_puts("\nHWERRCAUSE:");
early_shadow_reg(
(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14, 8);
}
early_shadow_puts("\nErr @");
if (fp->ipend & EVT_EVX)
early_shadow_reg(fp->retx, 32);
else
early_shadow_reg(fp->pc, 32);
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
early_shadow_puts("\nTrace:");
if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
while (bfin_read_TBUFSTAT() & TBUFCNT) {
early_shadow_puts("\nT :");
early_shadow_reg(bfin_read_TBUF(), 32);
early_shadow_puts("\n S :");
early_shadow_reg(bfin_read_TBUF(), 32);
}
}
#endif
early_shadow_puts("\nUse bfin-elf-addr2line to determine "
"function names\n");
/*
* We should panic(), but we can't - since panic calls printk,
* and printk uses memcpy.
* we want to reboot, but if the machine type is different,
* can't due to machine specific reboot sequences
*/
if (CPUID == bfin_cpuid()) {
early_shadow_puts("Trying to restart\n");
machine_restart("");
}
early_shadow_puts("Halting, since it is not safe to restart\n");
while (1)
asm volatile ("EMUEXCPT; IDLE;\n");
} else {
printk(KERN_EMERG "Early panic\n");
show_regs(fp);
dump_bfin_trace_buffer();
}
panic("Died early");
}

View file

@ -43,8 +43,28 @@
ENTRY(_ret_from_fork)
#ifdef CONFIG_IPIPE
[--sp] = reti; /* IRQs on. */
SP += 4;
/*
* Hw IRQs are off on entry, and we don't want the scheduling tail
* code to starve high priority domains from interrupts while it
* runs. Therefore we first stall the root stage to have the
* virtual interrupt state reflect IMASK.
*/
p0.l = ___ipipe_root_status;
p0.h = ___ipipe_root_status;
r4 = [p0];
bitset(r4, 0);
[p0] = r4;
/*
* Then we may enable hw IRQs, allowing preemption from high
* priority domains. schedule_tail() will do local_irq_enable()
* since Blackfin does not define __ARCH_WANT_UNLOCKED_CTXSW, so
* there is no need to unstall the root domain by ourselves
* afterwards.
*/
p0.l = _bfin_irq_flags;
p0.h = _bfin_irq_flags;
r4 = [p0];
sti r4;
#endif /* CONFIG_IPIPE */
SP += -12;
call _schedule_tail;

View file

@ -17,8 +17,8 @@
* only one we can blow away. With pointer registers, we have P0-P2.
*
* Upon entry, the RETS will point to the top of the current profiled
* function. And since GCC setup the frame for us, the previous function
* will be waiting there. mmmm pie.
* function. And since GCC pushed the previous RETS for us, the previous
* function will be waiting there. mmmm pie.
*/
ENTRY(__mcount)
/* save third function arg early so we can do testing below */
@ -70,14 +70,14 @@ ENTRY(__mcount)
/* setup the tracer function */
p0 = r3;
/* tracer(ulong frompc, ulong selfpc):
* frompc: the pc that did the call to ...
* selfpc: ... this location
* the selfpc itself will need adjusting for the mcount call
/* function_trace_call(unsigned long ip, unsigned long parent_ip):
* ip: this point was called by ...
* parent_ip: ... this function
* the ip itself will need adjusting for the mcount call
*/
r1 = rets;
r0 = [fp + 4];
r1 += -MCOUNT_INSN_SIZE;
r0 = rets;
r1 = [sp + 16]; /* skip the 4 local regs on stack */
r0 += -MCOUNT_INSN_SIZE;
/* call the tracer */
call (p0);
@ -106,9 +106,10 @@ ENTRY(_ftrace_graph_caller)
[--sp] = r1;
[--sp] = rets;
r0 = fp;
/* prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) */
r0 = sp;
r1 = rets;
r0 += 4;
r0 += 16; /* skip the 4 local regs on stack */
r1 += -MCOUNT_INSN_SIZE;
call _prepare_ftrace_return;

View file

@ -24,7 +24,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
if (unlikely(atomic_read(&current->tracing_graph_pause)))
return;
if (ftrace_push_return_trace(*parent, self_addr, &trace.depth) == -EBUSY)
if (ftrace_push_return_trace(*parent, self_addr, &trace.depth, 0) == -EBUSY)
return;
trace.func = self_addr;

View file

@ -30,10 +30,10 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/kthread.h>
#include <asm/unistd.h>
#include <linux/unistd.h>
#include <linux/io.h>
#include <asm/system.h>
#include <asm/atomic.h>
#include <asm/io.h>
DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
@ -90,6 +90,7 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr();
struct ipipe_domain *this_domain, *next_domain;
struct list_head *head, *pos;
struct ipipe_irqdesc *idesc;
int m_ack, s = -1;
/*
@ -100,17 +101,20 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
*/
m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR);
this_domain = __ipipe_current_domain;
idesc = &this_domain->irqs[irq];
if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control)))
if (unlikely(test_bit(IPIPE_STICKY_FLAG, &idesc->control)))
head = &this_domain->p_link;
else {
head = __ipipe_pipeline.next;
next_domain = list_entry(head, struct ipipe_domain, p_link);
if (likely(test_bit(IPIPE_WIRED_FLAG, &next_domain->irqs[irq].control))) {
if (!m_ack && next_domain->irqs[irq].acknowledge != NULL)
next_domain->irqs[irq].acknowledge(irq, irq_to_desc(irq));
idesc = &next_domain->irqs[irq];
if (likely(test_bit(IPIPE_WIRED_FLAG, &idesc->control))) {
if (!m_ack && idesc->acknowledge != NULL)
idesc->acknowledge(irq, irq_to_desc(irq));
if (test_bit(IPIPE_SYNCDEFER_FLAG, &p->status))
s = __test_and_set_bit(IPIPE_STALL_FLAG, &p->status);
s = __test_and_set_bit(IPIPE_STALL_FLAG,
&p->status);
__ipipe_dispatch_wired(next_domain, irq);
goto out;
}
@ -121,14 +125,15 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
pos = head;
while (pos != &__ipipe_pipeline) {
next_domain = list_entry(pos, struct ipipe_domain, p_link);
if (test_bit(IPIPE_HANDLE_FLAG, &next_domain->irqs[irq].control)) {
idesc = &next_domain->irqs[irq];
if (test_bit(IPIPE_HANDLE_FLAG, &idesc->control)) {
__ipipe_set_irq_pending(next_domain, irq);
if (!m_ack && next_domain->irqs[irq].acknowledge != NULL) {
next_domain->irqs[irq].acknowledge(irq, irq_to_desc(irq));
if (!m_ack && idesc->acknowledge != NULL) {
idesc->acknowledge(irq, irq_to_desc(irq));
m_ack = 1;
}
}
if (!test_bit(IPIPE_PASS_FLAG, &next_domain->irqs[irq].control))
if (!test_bit(IPIPE_PASS_FLAG, &idesc->control))
break;
pos = next_domain->p_link.next;
}
@ -159,11 +164,6 @@ out:
__clear_bit(IPIPE_STALL_FLAG, &p->status);
}
int __ipipe_check_root(void)
{
return ipipe_root_domain_p;
}
void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
{
struct irq_desc *desc = irq_to_desc(irq);
@ -186,30 +186,6 @@ void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
}
EXPORT_SYMBOL(__ipipe_disable_irqdesc);
void __ipipe_stall_root_raw(void)
{
/*
* This code is called by the ins{bwl} routines (see
* arch/blackfin/lib/ins.S), which are heavily used by the
* network stack. It masks all interrupts but those handled by
* non-root domains, so that we keep decent network transfer
* rates for Linux without inducing pathological jitter for
* the real-time domain.
*/
__asm__ __volatile__ ("sti %0;" : : "d"(__ipipe_irq_lvmask));
__set_bit(IPIPE_STALL_FLAG,
&ipipe_root_cpudom_var(status));
}
void __ipipe_unstall_root_raw(void)
{
__clear_bit(IPIPE_STALL_FLAG,
&ipipe_root_cpudom_var(status));
__asm__ __volatile__ ("sti %0;" : : "d"(bfin_irq_flags));
}
int __ipipe_syscall_root(struct pt_regs *regs)
{
struct ipipe_percpu_domain_data *p;
@ -333,12 +309,29 @@ asmlinkage void __ipipe_sync_root(void)
void ___ipipe_sync_pipeline(unsigned long syncmask)
{
if (__ipipe_root_domain_p) {
if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
return;
}
if (__ipipe_root_domain_p &&
test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
return;
__ipipe_sync_stage(syncmask);
}
EXPORT_SYMBOL(show_stack);
void __ipipe_disable_root_irqs_hw(void)
{
/*
* This code is called by the ins{bwl} routines (see
* arch/blackfin/lib/ins.S), which are heavily used by the
* network stack. It masks all interrupts but those handled by
* non-root domains, so that we keep decent network transfer
* rates for Linux without inducing pathological jitter for
* the real-time domain.
*/
bfin_sti(__ipipe_irq_lvmask);
__set_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status));
}
void __ipipe_enable_root_irqs_hw(void)
{
__clear_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status));
bfin_sti(bfin_irq_flags);
}

View file

@ -54,7 +54,7 @@ void kgdb_l2_test(void)
int kgdb_test(char *name, int len, int count, int z)
{
printk(KERN_DEBUG "kgdb name(%d): %s, %d, %d\n", len, name, count, z);
printk(KERN_ALERT "kgdb name(%d): %s, %d, %d\n", len, name, count, z);
count = z;
return count;
}

View file

@ -27,6 +27,7 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define pr_fmt(fmt) "module %s: " fmt
#include <linux/moduleloader.h>
#include <linux/elf.h>
@ -36,6 +37,7 @@
#include <linux/kernel.h>
#include <asm/dma.h>
#include <asm/cacheflush.h>
#include <asm/uaccess.h>
void *module_alloc(unsigned long size)
{
@ -52,7 +54,7 @@ void module_free(struct module *mod, void *module_region)
/* Transfer the section to the L1 memory */
int
module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
char *secstrings, struct module *mod)
{
/*
@ -63,126 +65,119 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
* NOTE: this breaks the semantic of mod->arch structure.
*/
Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
void *dest = NULL;
void *dest;
for (s = sechdrs; s < sechdrs_end; ++s) {
if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) ||
((strcmp(".text", secstrings + s->sh_name) == 0) &&
(hdr->e_flags & EF_BFIN_CODE_IN_L1) && (s->sh_size > 0))) {
const char *shname = secstrings + s->sh_name;
if (s->sh_size == 0)
continue;
if (!strcmp(".l1.text", shname) ||
(!strcmp(".text", shname) &&
(hdr->e_flags & EF_BFIN_CODE_IN_L1))) {
dest = l1_inst_sram_alloc(s->sh_size);
mod->arch.text_l1 = dest;
if (dest == NULL) {
printk(KERN_ERR
"module %s: L1 instruction memory allocation failed\n",
mod->name);
pr_err("L1 inst memory allocation failed\n",
mod->name);
return -1;
}
dma_memcpy(dest, (void *)s->sh_addr, s->sh_size);
s->sh_flags &= ~SHF_ALLOC;
s->sh_addr = (unsigned long)dest;
}
if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) ||
((strcmp(".data", secstrings + s->sh_name) == 0) &&
(hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) {
} else if (!strcmp(".l1.data", shname) ||
(!strcmp(".data", shname) &&
(hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
dest = l1_data_sram_alloc(s->sh_size);
mod->arch.data_a_l1 = dest;
if (dest == NULL) {
printk(KERN_ERR
"module %s: L1 data memory allocation failed\n",
pr_err("L1 data memory allocation failed\n",
mod->name);
return -1;
}
memcpy(dest, (void *)s->sh_addr, s->sh_size);
s->sh_flags &= ~SHF_ALLOC;
s->sh_addr = (unsigned long)dest;
}
if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 ||
((strcmp(".bss", secstrings + s->sh_name) == 0) &&
(hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) {
dest = l1_data_sram_alloc(s->sh_size);
} else if (!strcmp(".l1.bss", shname) ||
(!strcmp(".bss", shname) &&
(hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
dest = l1_data_sram_zalloc(s->sh_size);
mod->arch.bss_a_l1 = dest;
if (dest == NULL) {
printk(KERN_ERR
"module %s: L1 data memory allocation failed\n",
pr_err("L1 data memory allocation failed\n",
mod->name);
return -1;
}
memset(dest, 0, s->sh_size);
s->sh_flags &= ~SHF_ALLOC;
s->sh_addr = (unsigned long)dest;
}
if (strcmp(".l1.data.B", secstrings + s->sh_name) == 0) {
} else if (!strcmp(".l1.data.B", shname)) {
dest = l1_data_B_sram_alloc(s->sh_size);
mod->arch.data_b_l1 = dest;
if (dest == NULL) {
printk(KERN_ERR
"module %s: L1 data memory allocation failed\n",
pr_err("L1 data memory allocation failed\n",
mod->name);
return -1;
}
memcpy(dest, (void *)s->sh_addr, s->sh_size);
s->sh_flags &= ~SHF_ALLOC;
s->sh_addr = (unsigned long)dest;
}
if (strcmp(".l1.bss.B", secstrings + s->sh_name) == 0) {
} else if (!strcmp(".l1.bss.B", shname)) {
dest = l1_data_B_sram_alloc(s->sh_size);
mod->arch.bss_b_l1 = dest;
if (dest == NULL) {
printk(KERN_ERR
"module %s: L1 data memory allocation failed\n",
pr_err("L1 data memory allocation failed\n",
mod->name);
return -1;
}
memset(dest, 0, s->sh_size);
s->sh_flags &= ~SHF_ALLOC;
s->sh_addr = (unsigned long)dest;
}
if ((strcmp(".l2.text", secstrings + s->sh_name) == 0) ||
((strcmp(".text", secstrings + s->sh_name) == 0) &&
(hdr->e_flags & EF_BFIN_CODE_IN_L2) && (s->sh_size > 0))) {
} else if (!strcmp(".l2.text", shname) ||
(!strcmp(".text", shname) &&
(hdr->e_flags & EF_BFIN_CODE_IN_L2))) {
dest = l2_sram_alloc(s->sh_size);
mod->arch.text_l2 = dest;
if (dest == NULL) {
printk(KERN_ERR
"module %s: L2 SRAM allocation failed\n",
mod->name);
pr_err("L2 SRAM allocation failed\n",
mod->name);
return -1;
}
memcpy(dest, (void *)s->sh_addr, s->sh_size);
s->sh_flags &= ~SHF_ALLOC;
s->sh_addr = (unsigned long)dest;
}
if ((strcmp(".l2.data", secstrings + s->sh_name) == 0) ||
((strcmp(".data", secstrings + s->sh_name) == 0) &&
(hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
} else if (!strcmp(".l2.data", shname) ||
(!strcmp(".data", shname) &&
(hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
dest = l2_sram_alloc(s->sh_size);
mod->arch.data_l2 = dest;
if (dest == NULL) {
printk(KERN_ERR
"module %s: L2 SRAM allocation failed\n",
pr_err("L2 SRAM allocation failed\n",
mod->name);
return -1;
}
memcpy(dest, (void *)s->sh_addr, s->sh_size);
s->sh_flags &= ~SHF_ALLOC;
s->sh_addr = (unsigned long)dest;
}
if (strcmp(".l2.bss", secstrings + s->sh_name) == 0 ||
((strcmp(".bss", secstrings + s->sh_name) == 0) &&
(hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
dest = l2_sram_alloc(s->sh_size);
} else if (!strcmp(".l2.bss", shname) ||
(!strcmp(".bss", shname) &&
(hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
dest = l2_sram_zalloc(s->sh_size);
mod->arch.bss_l2 = dest;
if (dest == NULL) {
printk(KERN_ERR
"module %s: L2 SRAM allocation failed\n",
pr_err("L2 SRAM allocation failed\n",
mod->name);
return -1;
}
memset(dest, 0, s->sh_size);
s->sh_flags &= ~SHF_ALLOC;
s->sh_addr = (unsigned long)dest;
}
} else
continue;
s->sh_flags &= ~SHF_ALLOC;
s->sh_addr = (unsigned long)dest;
}
return 0;
}
@ -190,7 +185,7 @@ int
apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
unsigned int symindex, unsigned int relsec, struct module *me)
{
printk(KERN_ERR "module %s: .rel unsupported\n", me->name);
pr_err(".rel unsupported\n", me->name);
return -ENOEXEC;
}
@ -205,109 +200,86 @@ apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
/* gas does not generate it. */
/*************************************************************************/
int
apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
unsigned int symindex, unsigned int relsec,
struct module *mod)
{
unsigned int i;
unsigned short tmp;
Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
Elf32_Sym *sym;
uint32_t *location32;
uint16_t *location16;
uint32_t value;
unsigned long location, value, size;
pr_debug("applying relocate section %u to %u\n", mod->name,
relsec, sechdrs[relsec].sh_info);
pr_debug("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */
location16 =
(uint16_t *) (sechdrs[sechdrs[relsec].sh_info].sh_addr +
rel[i].r_offset);
location32 = (uint32_t *) location16;
location = sechdrs[sechdrs[relsec].sh_info].sh_addr +
rel[i].r_offset;
/* This is the symbol it is referring to. Note that all
undefined symbols have been resolved. */
sym = (Elf32_Sym *) sechdrs[symindex].sh_addr
+ ELF32_R_SYM(rel[i].r_info);
value = sym->st_value;
value += rel[i].r_addend;
pr_debug("location is %x, value is %x type is %d \n",
(unsigned int) location32, value,
ELF32_R_TYPE(rel[i].r_info));
#ifdef CONFIG_SMP
if ((unsigned long)location16 >= COREB_L1_DATA_A_START) {
printk(KERN_ERR "module %s: cannot relocate in L1: %u (SMP kernel)",
mod->name, ELF32_R_TYPE(rel[i].r_info));
if (location >= COREB_L1_DATA_A_START) {
pr_err("cannot relocate in L1: %u (SMP kernel)",
mod->name, ELF32_R_TYPE(rel[i].r_info));
return -ENOEXEC;
}
#endif
pr_debug("location is %lx, value is %lx type is %d\n",
mod->name, location, value, ELF32_R_TYPE(rel[i].r_info));
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_BFIN_HUIMM16:
value >>= 16;
case R_BFIN_LUIMM16:
case R_BFIN_RIMM16:
size = 2;
break;
case R_BFIN_BYTE4_DATA:
size = 4;
break;
case R_BFIN_PCREL24:
case R_BFIN_PCREL24_JUMP_L:
/* Add the value, subtract its postition */
location16 =
(uint16_t *) (sechdrs[sechdrs[relsec].sh_info].
sh_addr + rel[i].r_offset - 2);
location32 = (uint32_t *) location16;
value -= (uint32_t) location32;
value >>= 1;
if ((value & 0xFF000000) != 0 &&
(value & 0xFF000000) != 0xFF000000) {
printk(KERN_ERR "module %s: relocation overflow\n",
mod->name);
return -ENOEXEC;
}
pr_debug("value is %x, before %x-%x after %x-%x\n", value,
*location16, *(location16 + 1),
(*location16 & 0xff00) | (value >> 16 & 0x00ff),
value & 0xffff);
*location16 =
(*location16 & 0xff00) | (value >> 16 & 0x00ff);
*(location16 + 1) = value & 0xffff;
break;
case R_BFIN_PCREL12_JUMP:
case R_BFIN_PCREL12_JUMP_S:
value -= (uint32_t) location32;
value >>= 1;
*location16 = (value & 0xfff);
break;
case R_BFIN_PCREL10:
value -= (uint32_t) location32;
value >>= 1;
*location16 = (value & 0x3ff);
pr_err("unsupported relocation: %u (no -mlong-calls?)\n",
mod->name, ELF32_R_TYPE(rel[i].r_info));
return -ENOEXEC;
default:
pr_err("unknown relocation: %u\n", mod->name,
ELF32_R_TYPE(rel[i].r_info));
return -ENOEXEC;
}
switch (bfin_mem_access_type(location, size)) {
case BFIN_MEM_ACCESS_CORE:
case BFIN_MEM_ACCESS_CORE_ONLY:
memcpy((void *)location, &value, size);
break;
case R_BFIN_LUIMM16:
pr_debug("before %x after %x\n", *location16,
(value & 0xffff));
tmp = (value & 0xffff);
if ((unsigned long)location16 >= L1_CODE_START) {
dma_memcpy(location16, &tmp, 2);
} else
*location16 = tmp;
case BFIN_MEM_ACCESS_DMA:
dma_memcpy((void *)location, &value, size);
break;
case R_BFIN_HUIMM16:
pr_debug("before %x after %x\n", *location16,
((value >> 16) & 0xffff));
tmp = ((value >> 16) & 0xffff);
if ((unsigned long)location16 >= L1_CODE_START) {
dma_memcpy(location16, &tmp, 2);
} else
*location16 = tmp;
break;
case R_BFIN_RIMM16:
*location16 = (value & 0xffff);
break;
case R_BFIN_BYTE4_DATA:
pr_debug("before %x after %x\n", *location32, value);
*location32 = value;
case BFIN_MEM_ACCESS_ITEST:
isram_memcpy((void *)location, &value, size);
break;
default:
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
mod->name, ELF32_R_TYPE(rel[i].r_info));
pr_err("invalid relocation for %#lx\n",
mod->name, location);
return -ENOEXEC;
}
}
return 0;
}
@ -332,22 +304,28 @@ module_finalize(const Elf_Ehdr * hdr,
for (i = 1; i < hdr->e_shnum; i++) {
const char *strtab = (char *)sechdrs[strindex].sh_addr;
unsigned int info = sechdrs[i].sh_info;
const char *shname = secstrings + sechdrs[i].sh_name;
/* Not a valid relocation section? */
if (info >= hdr->e_shnum)
continue;
if ((sechdrs[i].sh_type == SHT_RELA) &&
((strcmp(".rela.l2.text", secstrings + sechdrs[i].sh_name) == 0) ||
(strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
(hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) {
/* Only support RELA relocation types */
if (sechdrs[i].sh_type != SHT_RELA)
continue;
if (!strcmp(".rela.l2.text", shname) ||
!strcmp(".rela.l1.text", shname) ||
(!strcmp(".rela.text", shname) &&
(hdr->e_flags & (EF_BFIN_CODE_IN_L1 | EF_BFIN_CODE_IN_L2)))) {
err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
symindex, i, mod);
if (err < 0)
return -ENOEXEC;
}
}
return 0;
}

View file

@ -282,25 +282,19 @@ void finish_atomic_sections (struct pt_regs *regs)
{
int __user *up0 = (int __user *)regs->p0;
if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END)
return;
switch (regs->pc) {
case ATOMIC_XCHG32 + 2:
put_user(regs->r1, up0);
regs->pc += 2;
regs->pc = ATOMIC_XCHG32 + 4;
break;
case ATOMIC_CAS32 + 2:
case ATOMIC_CAS32 + 4:
if (regs->r0 == regs->r1)
case ATOMIC_CAS32 + 6:
put_user(regs->r2, up0);
regs->pc = ATOMIC_CAS32 + 8;
break;
case ATOMIC_CAS32 + 6:
put_user(regs->r2, up0);
regs->pc += 2;
break;
case ATOMIC_ADD32 + 2:
regs->r0 = regs->r1 + regs->r0;

View file

@ -206,6 +206,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
int ret;
unsigned long __user *datap = (unsigned long __user *)data;
void *paddr = (void *)addr;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
@ -215,42 +216,49 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_PEEKTEXT: /* read word at location addr. */
{
unsigned long tmp = 0;
int copied;
int copied = 0, to_copy = sizeof(tmp);
ret = -EIO;
pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %ld\n", addr, sizeof(data));
if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %i\n", addr, to_copy);
if (is_user_addr_valid(child, addr, to_copy) < 0)
break;
pr_debug("ptrace: user address is valid\n");
if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
&& addr + sizeof(tmp) <= get_l1_code_start() + L1_CODE_LENGTH) {
safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp));
copied = sizeof(tmp);
} else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START
&& addr + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
memcpy(&tmp, (const void *)(addr), sizeof(tmp));
copied = sizeof(tmp);
} else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START
&& addr + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
memcpy(&tmp, (const void *)(addr), sizeof(tmp));
copied = sizeof(tmp);
} else if (addr >= FIXED_CODE_START
&& addr + sizeof(tmp) <= FIXED_CODE_END) {
copy_from_user_page(0, 0, 0, &tmp, (const void *)(addr), sizeof(tmp));
copied = sizeof(tmp);
} else
switch (bfin_mem_access_type(addr, to_copy)) {
case BFIN_MEM_ACCESS_CORE:
case BFIN_MEM_ACCESS_CORE_ONLY:
copied = access_process_vm(child, addr, &tmp,
sizeof(tmp), 0);
to_copy, 0);
if (copied)
break;
/* hrm, why didn't that work ... maybe no mapping */
if (addr >= FIXED_CODE_START &&
addr + to_copy <= FIXED_CODE_END) {
copy_from_user_page(0, 0, 0, &tmp, paddr, to_copy);
copied = to_copy;
} else if (addr >= BOOT_ROM_START) {
memcpy(&tmp, paddr, to_copy);
copied = to_copy;
}
break;
case BFIN_MEM_ACCESS_DMA:
if (safe_dma_memcpy(&tmp, paddr, to_copy))
copied = to_copy;
break;
case BFIN_MEM_ACCESS_ITEST:
if (isram_memcpy(&tmp, paddr, to_copy))
copied = to_copy;
break;
default:
copied = 0;
break;
}
pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp);
if (copied != sizeof(tmp))
break;
ret = put_user(tmp, datap);
if (copied == to_copy)
ret = put_user(tmp, datap);
break;
}
@ -277,9 +285,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
tmp = child->mm->start_data;
#ifdef CONFIG_BINFMT_ELF_FDPIC
} else if (addr == (sizeof(struct pt_regs) + 12)) {
tmp = child->mm->context.exec_fdpic_loadmap;
goto case_PTRACE_GETFDPIC_EXEC;
} else if (addr == (sizeof(struct pt_regs) + 16)) {
tmp = child->mm->context.interp_fdpic_loadmap;
goto case_PTRACE_GETFDPIC_INTERP;
#endif
} else {
tmp = get_reg(child, addr);
@ -288,49 +296,78 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
#ifdef CONFIG_BINFMT_ELF_FDPIC
case PTRACE_GETFDPIC: {
unsigned long tmp = 0;
switch (addr) {
case_PTRACE_GETFDPIC_EXEC:
case PTRACE_GETFDPIC_EXEC:
tmp = child->mm->context.exec_fdpic_loadmap;
break;
case_PTRACE_GETFDPIC_INTERP:
case PTRACE_GETFDPIC_INTERP:
tmp = child->mm->context.interp_fdpic_loadmap;
break;
default:
break;
}
ret = put_user(tmp, datap);
break;
}
#endif
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKEDATA:
pr_debug("ptrace: PTRACE_PEEKDATA\n");
/* fall through */
case PTRACE_POKETEXT: /* write the word at location addr. */
{
int copied;
int copied = 0, to_copy = sizeof(data);
ret = -EIO;
pr_debug("ptrace: POKETEXT at addr 0x%08lx + %ld bytes %lx\n",
addr, sizeof(data), data);
if (is_user_addr_valid(child, addr, sizeof(data)) < 0)
pr_debug("ptrace: POKETEXT at addr 0x%08lx + %i bytes %lx\n",
addr, to_copy, data);
if (is_user_addr_valid(child, addr, to_copy) < 0)
break;
pr_debug("ptrace: user address is valid\n");
if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
&& addr + sizeof(data) <= get_l1_code_start() + L1_CODE_LENGTH) {
safe_dma_memcpy ((void *)(addr), &data, sizeof(data));
copied = sizeof(data);
} else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START
&& addr + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
memcpy((void *)(addr), &data, sizeof(data));
copied = sizeof(data);
} else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START
&& addr + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
memcpy((void *)(addr), &data, sizeof(data));
copied = sizeof(data);
} else if (addr >= FIXED_CODE_START
&& addr + sizeof(data) <= FIXED_CODE_END) {
copy_to_user_page(0, 0, 0, (void *)(addr), &data, sizeof(data));
copied = sizeof(data);
} else
switch (bfin_mem_access_type(addr, to_copy)) {
case BFIN_MEM_ACCESS_CORE:
case BFIN_MEM_ACCESS_CORE_ONLY:
copied = access_process_vm(child, addr, &data,
sizeof(data), 1);
to_copy, 0);
if (copied)
break;
/* hrm, why didn't that work ... maybe no mapping */
if (addr >= FIXED_CODE_START &&
addr + to_copy <= FIXED_CODE_END) {
copy_to_user_page(0, 0, 0, paddr, &data, to_copy);
copied = to_copy;
} else if (addr >= BOOT_ROM_START) {
memcpy(paddr, &data, to_copy);
copied = to_copy;
}
break;
case BFIN_MEM_ACCESS_DMA:
if (safe_dma_memcpy(paddr, &data, to_copy))
copied = to_copy;
break;
case BFIN_MEM_ACCESS_ITEST:
if (isram_memcpy(paddr, &data, to_copy))
copied = to_copy;
break;
default:
copied = 0;
break;
}
pr_debug("ptrace: copied size %d\n", copied);
if (copied != sizeof(data))
break;
ret = 0;
if (copied == to_copy)
ret = 0;
break;
}

View file

@ -112,7 +112,7 @@ void __cpuinit bfin_setup_caches(unsigned int cpu)
/*
* In cache coherence emulation mode, we need to have the
* D-cache enabled before running any atomic operation which
* might invove cache invalidation (i.e. spinlock, rwlock).
* might involve cache invalidation (i.e. spinlock, rwlock).
* So printk's are deferred until then.
*/
#ifdef CONFIG_BFIN_ICACHE
@ -187,6 +187,8 @@ void __init bfin_relocate_l1_mem(void)
unsigned long l1_data_b_length;
unsigned long l2_length;
early_shadow_stamp();
/*
* due to the ALIGN(4) in the arch/blackfin/kernel/vmlinux.lds.S
* we know that everything about l1 text/data is nice and aligned,
@ -511,6 +513,7 @@ static __init void memory_setup(void)
#ifdef CONFIG_MTD_UCLINUX
unsigned long mtd_phys = 0;
#endif
unsigned long max_mem;
_rambase = (unsigned long)_stext;
_ramstart = (unsigned long)_end;
@ -520,7 +523,22 @@ static __init void memory_setup(void)
panic("DMA region exceeds memory limit: %lu.",
_ramend - _ramstart);
}
memory_end = _ramend - DMA_UNCACHED_REGION;
max_mem = memory_end = _ramend - DMA_UNCACHED_REGION;
#if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
/* Due to a Hardware Anomaly we need to limit the size of usable
* instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
* 05000263 - Hardware loop corrupted when taking an ICPLB exception
*/
# if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
if (max_mem >= 56 * 1024 * 1024)
max_mem = 56 * 1024 * 1024;
# else
if (max_mem >= 60 * 1024 * 1024)
max_mem = 60 * 1024 * 1024;
# endif /* CONFIG_DEBUG_HUNT_FOR_ZERO */
#endif /* ANOMALY_05000263 */
#ifdef CONFIG_MPU
/* Round up to multiple of 4MB */
@ -549,22 +567,16 @@ static __init void memory_setup(void)
# if defined(CONFIG_ROMFS_FS)
if (((unsigned long *)mtd_phys)[0] == ROMSB_WORD0
&& ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1)
&& ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1) {
mtd_size =
PAGE_ALIGN(be32_to_cpu(((unsigned long *)mtd_phys)[2]));
# if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
/* Due to a Hardware Anomaly we need to limit the size of usable
* instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
* 05000263 - Hardware loop corrupted when taking an ICPLB exception
*/
# if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
if (memory_end >= 56 * 1024 * 1024)
memory_end = 56 * 1024 * 1024;
# else
if (memory_end >= 60 * 1024 * 1024)
memory_end = 60 * 1024 * 1024;
# endif /* CONFIG_DEBUG_HUNT_FOR_ZERO */
# endif /* ANOMALY_05000263 */
/* ROM_FS is XIP, so if we found it, we need to limit memory */
if (memory_end > max_mem) {
pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20);
memory_end = max_mem;
}
}
# endif /* CONFIG_ROMFS_FS */
/* Since the default MTD_UCLINUX has no magic number, we just blindly
@ -586,20 +598,14 @@ static __init void memory_setup(void)
}
#endif /* CONFIG_MTD_UCLINUX */
#if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
/* Due to a Hardware Anomaly we need to limit the size of usable
* instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
* 05000263 - Hardware loop corrupted when taking an ICPLB exception
/* We need lo limit memory, since everything could have a text section
* of userspace in it, and expose anomaly 05000263. If the anomaly
* doesn't exist, or we don't need to - then dont.
*/
#if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
if (memory_end >= 56 * 1024 * 1024)
memory_end = 56 * 1024 * 1024;
#else
if (memory_end >= 60 * 1024 * 1024)
memory_end = 60 * 1024 * 1024;
#endif /* CONFIG_DEBUG_HUNT_FOR_ZERO */
printk(KERN_NOTICE "Warning: limiting memory to %liMB due to hardware anomaly 05000263\n", memory_end >> 20);
#endif /* ANOMALY_05000263 */
if (memory_end > max_mem) {
pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20);
memory_end = max_mem;
}
#ifdef CONFIG_MPU
page_mask_nelts = ((_ramend >> PAGE_SHIFT) + 31) / 32;
@ -693,7 +699,7 @@ static __init void setup_bootmem_allocator(void)
sanitize_memmap(bfin_memmap.map, &bfin_memmap.nr_map);
print_memory_map("boot memmap");
/* intialize globals in linux/bootmem.h */
/* initialize globals in linux/bootmem.h */
find_min_max_pfn();
/* pfn of the last usable page frame */
if (max_pfn > memory_end >> PAGE_SHIFT)
@ -806,6 +812,8 @@ void __init setup_arch(char **cmdline_p)
{
unsigned long sclk, cclk;
enable_shadow_console();
/* Check to make sure we are running on the right processor */
if (unlikely(CPUID != bfin_cpuid()))
printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n",
@ -1230,57 +1238,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
#ifdef __ARCH_SYNC_CORE_ICACHE
seq_printf(m, "SMP Icache Flushes\t: %lu\n\n", cpudata->icache_invld_count);
#endif
#ifdef CONFIG_BFIN_ICACHE_LOCK
switch ((cpudata->imemctl >> 3) & WAYALL_L) {
case WAY0_L:
seq_printf(m, "Way0 Locked-Down\n");
break;
case WAY1_L:
seq_printf(m, "Way1 Locked-Down\n");
break;
case WAY01_L:
seq_printf(m, "Way0,Way1 Locked-Down\n");
break;
case WAY2_L:
seq_printf(m, "Way2 Locked-Down\n");
break;
case WAY02_L:
seq_printf(m, "Way0,Way2 Locked-Down\n");
break;
case WAY12_L:
seq_printf(m, "Way1,Way2 Locked-Down\n");
break;
case WAY012_L:
seq_printf(m, "Way0,Way1 & Way2 Locked-Down\n");
break;
case WAY3_L:
seq_printf(m, "Way3 Locked-Down\n");
break;
case WAY03_L:
seq_printf(m, "Way0,Way3 Locked-Down\n");
break;
case WAY13_L:
seq_printf(m, "Way1,Way3 Locked-Down\n");
break;
case WAY013_L:
seq_printf(m, "Way 0,Way1,Way3 Locked-Down\n");
break;
case WAY32_L:
seq_printf(m, "Way3,Way2 Locked-Down\n");
break;
case WAY320_L:
seq_printf(m, "Way3,Way2,Way0 Locked-Down\n");
break;
case WAY321_L:
seq_printf(m, "Way3,Way2,Way1 Locked-Down\n");
break;
case WAYALL_L:
seq_printf(m, "All Ways are locked\n");
break;
default:
seq_printf(m, "No Ways are locked\n");
}
#endif
if (cpu_num != num_possible_cpus() - 1)
return 0;
@ -1346,6 +1303,7 @@ const struct seq_operations cpuinfo_op = {
void __init cmdline_init(const char *r0)
{
early_shadow_stamp();
if (r0)
strncpy(command_line, r0, COMMAND_LINE_SIZE);
}

View 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);
}

View file

@ -66,7 +66,7 @@ static cycle_t bfin_read_cycles(struct clocksource *cs)
static struct clocksource bfin_cs_cycles = {
.name = "bfin_cs_cycles",
.rating = 350,
.rating = 400,
.read = bfin_read_cycles,
.mask = CLOCKSOURCE_MASK(64),
.shift = 22,
@ -115,7 +115,7 @@ static cycle_t bfin_read_gptimer0(void)
static struct clocksource bfin_cs_gptimer0 = {
.name = "bfin_cs_gptimer0",
.rating = 400,
.rating = 350,
.read = bfin_read_gptimer0,
.mask = CLOCKSOURCE_MASK(32),
.shift = 22,

View file

@ -100,7 +100,11 @@ static void decode_address(char *buf, unsigned long address)
char *modname;
char *delim = ":";
char namebuf[128];
#endif
buf += sprintf(buf, "<0x%08lx> ", address);
#ifdef CONFIG_KALLSYMS
/* look up the address and see if we are in kernel space */
symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
@ -108,23 +112,33 @@ static void decode_address(char *buf, unsigned long address)
/* yeah! kernel space! */
if (!modname)
modname = delim = "";
sprintf(buf, "<0x%p> { %s%s%s%s + 0x%lx }",
(void *)address, delim, modname, delim, symname,
(unsigned long)offset);
sprintf(buf, "{ %s%s%s%s + 0x%lx }",
delim, modname, delim, symname,
(unsigned long)offset);
return;
}
#endif
/* Problem in fixed code section? */
if (address >= FIXED_CODE_START && address < FIXED_CODE_END) {
sprintf(buf, "<0x%p> /* Maybe fixed code section */", (void *)address);
/* Problem in fixed code section? */
strcat(buf, "/* Maybe fixed code section */");
return;
}
/* Problem somewhere before the kernel start address */
if (address < CONFIG_BOOT_LOAD) {
sprintf(buf, "<0x%p> /* Maybe null pointer? */", (void *)address);
} else if (address < CONFIG_BOOT_LOAD) {
/* Problem somewhere before the kernel start address */
strcat(buf, "/* Maybe null pointer? */");
return;
} else if (address >= COREMMR_BASE) {
strcat(buf, "/* core mmrs */");
return;
} else if (address >= SYSMMR_BASE) {
strcat(buf, "/* system mmrs */");
return;
} else if (address >= L1_ROM_START && address < L1_ROM_START + L1_ROM_LENGTH) {
strcat(buf, "/* on-chip L1 ROM */");
return;
}
@ -172,18 +186,16 @@ static void decode_address(char *buf, unsigned long address)
offset = (address - vma->vm_start) +
(vma->vm_pgoff << PAGE_SHIFT);
sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
(void *)address, name, offset);
sprintf(buf, "[ %s + 0x%lx ]", name, offset);
} else
sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]",
(void *)address, name,
vma->vm_start, vma->vm_end);
sprintf(buf, "[ %s vma:0x%lx-0x%lx]",
name, vma->vm_start, vma->vm_end);
if (!in_atomic)
mmput(mm);
if (!strlen(buf))
sprintf(buf, "<0x%p> [ %s ] dynamic memory", (void *)address, name);
if (buf[0] == '\0')
sprintf(buf, "[ %s ] dynamic memory", name);
goto done;
}
@ -193,7 +205,7 @@ static void decode_address(char *buf, unsigned long address)
}
/* we were unable to find this address anywhere */
sprintf(buf, "<0x%p> /* kernel dynamic memory */", (void *)address);
sprintf(buf, "/* kernel dynamic memory */");
done:
write_unlock_irqrestore(&tasklist_lock, flags);
@ -215,14 +227,14 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
printk(KERN_EMERG "Double Fault\n");
#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) {
unsigned int cpu = smp_processor_id();
unsigned int cpu = raw_smp_processor_id();
char buf[150];
decode_address(buf, cpu_pda[cpu].retx);
decode_address(buf, cpu_pda[cpu].retx_doublefault);
printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
(unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf);
decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
(unsigned int)cpu_pda[cpu].seqstat_doublefault & SEQSTAT_EXCAUSE, buf);
decode_address(buf, cpu_pda[cpu].dcplb_doublefault_addr);
printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf);
decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
decode_address(buf, cpu_pda[cpu].icplb_doublefault_addr);
printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf);
decode_address(buf, fp->retx);
@ -245,13 +257,13 @@ static int kernel_mode_regs(struct pt_regs *regs)
return regs->ipend & 0xffc0;
}
asmlinkage void trap_c(struct pt_regs *fp)
asmlinkage notrace void trap_c(struct pt_regs *fp)
{
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
int j;
#endif
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
unsigned int cpu = smp_processor_id();
unsigned int cpu = raw_smp_processor_id();
#endif
const char *strerror = NULL;
int sig = 0;
@ -267,11 +279,6 @@ asmlinkage void trap_c(struct pt_regs *fp)
* double faults if the stack has become corrupt
*/
#ifndef CONFIG_KGDB
/* IPEND is skipped if KGDB isn't enabled (see entry code) */
fp->ipend = bfin_read_IPEND();
#endif
/* trap_c() will be called for exceptions. During exceptions
* processing, the pc value should be set with retx value.
* With this change we can cleanup some code in signal.c- TODO
@ -404,7 +411,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
/* 0x23 - Data CPLB protection violation, handled here */
case VEC_CPLB_VL:
info.si_code = ILL_CPLB_VI;
sig = SIGBUS;
sig = SIGSEGV;
strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE);
CHK_DEBUGGER_TRAP_MAYBE();
break;
@ -904,7 +911,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
frame_no = 0;
for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
addr <= endstack; addr++, i++) {
addr < endstack; addr++, i++) {
ret_addr = 0;
if (!j && i % 8 == 0)
@ -949,6 +956,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
}
#endif
}
EXPORT_SYMBOL(show_stack);
void dump_stack(void)
{
@ -1090,7 +1098,7 @@ void show_regs(struct pt_regs *fp)
struct irqaction *action;
unsigned int i;
unsigned long flags = 0;
unsigned int cpu = smp_processor_id();
unsigned int cpu = raw_smp_processor_id();
unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
verbose_printk(KERN_NOTICE "\n");
@ -1116,10 +1124,16 @@ void show_regs(struct pt_regs *fp)
verbose_printk(KERN_NOTICE "%s", linux_banner);
verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n",
print_tainted());
verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
(long)fp->seqstat, fp->ipend, fp->syscfg);
verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", print_tainted());
verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx IMASK: %04lx SYSCFG: %04lx\n",
(long)fp->seqstat, fp->ipend, cpu_pda[raw_smp_processor_id()].ex_imask, fp->syscfg);
if (fp->ipend & EVT_IRPTEN)
verbose_printk(KERN_NOTICE " Global Interrupts Disabled (IPEND[4])\n");
if (!(cpu_pda[raw_smp_processor_id()].ex_imask & (EVT_IVG13 | EVT_IVG12 | EVT_IVG11 |
EVT_IVG10 | EVT_IVG9 | EVT_IVG8 | EVT_IVG7 | EVT_IVTMR)))
verbose_printk(KERN_NOTICE " Peripheral interrupts masked off\n");
if (!(cpu_pda[raw_smp_processor_id()].ex_imask & (EVT_IVG15 | EVT_IVG14)))
verbose_printk(KERN_NOTICE " Kernel interrupts masked off\n");
if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n",
(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);

View file

@ -221,7 +221,7 @@ SECTIONS
. = ALIGN(4);
__ebss_l1 = .;
}
ASSERT (SIZEOF(.data_a_l1) <= L1_DATA_A_LENGTH, "L1 data A overflow!")
ASSERT (SIZEOF(.data_l1) <= L1_DATA_A_LENGTH, "L1 data A overflow!")
.data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1))
{
@ -262,7 +262,7 @@ SECTIONS
. = ALIGN(4);
__ebss_l2 = .;
}
ASSERT (SIZEOF(.text_data_l1) <= L2_LENGTH, "L2 overflow!")
ASSERT (SIZEOF(.text_data_l2) <= L2_LENGTH, "L2 overflow!")
/* Force trailing alignment of our init section so that when we
* free our init memory, we don't leave behind a partial page.
@ -277,8 +277,5 @@ SECTIONS
DWARF_DEBUG
/DISCARD/ :
{
*(.exitcall.exit)
}
DISCARDS
}

Some files were not shown because too many files have changed in this diff Show more