mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-21 00:42:16 +00:00
Merge branch 'upstream-fixes'
This commit is contained in:
commit
97309d1a0b
673
Documentation/drivers/edac/edac.txt
Normal file
673
Documentation/drivers/edac/edac.txt
Normal file
@ -0,0 +1,673 @@
|
||||
|
||||
|
||||
EDAC - Error Detection And Correction
|
||||
|
||||
Written by Doug Thompson <norsk5@xmission.com>
|
||||
7 Dec 2005
|
||||
|
||||
|
||||
EDAC was written by:
|
||||
Thayne Harbaugh,
|
||||
modified by Dave Peterson, Doug Thompson, et al,
|
||||
from the bluesmoke.sourceforge.net project.
|
||||
|
||||
|
||||
============================================================================
|
||||
EDAC PURPOSE
|
||||
|
||||
The 'edac' kernel module goal is to detect and report errors that occur
|
||||
within the computer system. In the initial release, memory Correctable Errors
|
||||
(CE) and Uncorrectable Errors (UE) are the primary errors being harvested.
|
||||
|
||||
Detecting CE events, then harvesting those events and reporting them,
|
||||
CAN be a predictor of future UE events. With CE events, the system can
|
||||
continue to operate, but with less safety. Preventive maintainence and
|
||||
proactive part replacement of memory DIMMs exhibiting CEs can reduce
|
||||
the likelihood of the dreaded UE events and system 'panics'.
|
||||
|
||||
|
||||
In addition, PCI Bus Parity and SERR Errors are scanned for on PCI devices
|
||||
in order to determine if errors are occurring on data transfers.
|
||||
The presence of PCI Parity errors must be examined with a grain of salt.
|
||||
There are several addin adapters that do NOT follow the PCI specification
|
||||
with regards to Parity generation and reporting. The specification says
|
||||
the vendor should tie the parity status bits to 0 if they do not intend
|
||||
to generate parity. Some vendors do not do this, and thus the parity bit
|
||||
can "float" giving false positives.
|
||||
|
||||
The PCI Parity EDAC device has the ability to "skip" known flakey
|
||||
cards during the parity scan. These are set by the parity "blacklist"
|
||||
interface in the sysfs for PCI Parity. (See the PCI section in the sysfs
|
||||
section below.) There is also a parity "whitelist" which is used as
|
||||
an explicit list of devices to scan, while the blacklist is a list
|
||||
of devices to skip.
|
||||
|
||||
EDAC will have future error detectors that will be added or integrated
|
||||
into EDAC in the following list:
|
||||
|
||||
MCE Machine Check Exception
|
||||
MCA Machine Check Architecture
|
||||
NMI NMI notification of ECC errors
|
||||
MSRs Machine Specific Register error cases
|
||||
and other mechanisms.
|
||||
|
||||
These errors are usually bus errors, ECC errors, thermal throttling
|
||||
and the like.
|
||||
|
||||
|
||||
============================================================================
|
||||
EDAC VERSIONING
|
||||
|
||||
EDAC is composed of a "core" module (edac_mc.ko) and several Memory
|
||||
Controller (MC) driver modules. On a given system, the CORE
|
||||
is loaded and one MC driver will be loaded. Both the CORE and
|
||||
the MC driver have individual versions that reflect current release
|
||||
level of their respective modules. Thus, to "report" on what version
|
||||
a system is running, one must report both the CORE's and the
|
||||
MC driver's versions.
|
||||
|
||||
|
||||
LOADING
|
||||
|
||||
If 'edac' was statically linked with the kernel then no loading is
|
||||
necessary. If 'edac' was built as modules then simply modprobe the
|
||||
'edac' pieces that you need. You should be able to modprobe
|
||||
hardware-specific modules and have the dependencies load the necessary core
|
||||
modules.
|
||||
|
||||
Example:
|
||||
|
||||
$> modprobe amd76x_edac
|
||||
|
||||
loads both the amd76x_edac.ko memory controller module and the edac_mc.ko
|
||||
core module.
|
||||
|
||||
|
||||
============================================================================
|
||||
EDAC sysfs INTERFACE
|
||||
|
||||
EDAC presents a 'sysfs' interface for control, reporting and attribute
|
||||
reporting purposes.
|
||||
|
||||
EDAC lives in the /sys/devices/system/edac directory. Within this directory
|
||||
there currently reside 2 'edac' components:
|
||||
|
||||
mc memory controller(s) system
|
||||
pci PCI status system
|
||||
|
||||
|
||||
============================================================================
|
||||
Memory Controller (mc) Model
|
||||
|
||||
First a background on the memory controller's model abstracted in EDAC.
|
||||
Each mc device controls a set of DIMM memory modules. These modules are
|
||||
layed out in a Chip-Select Row (csrowX) and Channel table (chX). There can
|
||||
be multiple csrows and two channels.
|
||||
|
||||
Memory controllers allow for several csrows, with 8 csrows being a typical value.
|
||||
Yet, the actual number of csrows depends on the electrical "loading"
|
||||
of a given motherboard, memory controller and DIMM characteristics.
|
||||
|
||||
Dual channels allows for 128 bit data transfers to the CPU from memory.
|
||||
|
||||
|
||||
Channel 0 Channel 1
|
||||
===================================
|
||||
csrow0 | DIMM_A0 | DIMM_B0 |
|
||||
csrow1 | DIMM_A0 | DIMM_B0 |
|
||||
===================================
|
||||
|
||||
===================================
|
||||
csrow2 | DIMM_A1 | DIMM_B1 |
|
||||
csrow3 | DIMM_A1 | DIMM_B1 |
|
||||
===================================
|
||||
|
||||
In the above example table there are 4 physical slots on the motherboard
|
||||
for memory DIMMs:
|
||||
|
||||
DIMM_A0
|
||||
DIMM_B0
|
||||
DIMM_A1
|
||||
DIMM_B1
|
||||
|
||||
Labels for these slots are usually silk screened on the motherboard. Slots
|
||||
labeled 'A' are channel 0 in this example. Slots labled 'B'
|
||||
are channel 1. Notice that there are two csrows possible on a
|
||||
physical DIMM. These csrows are allocated their csrow assignment
|
||||
based on the slot into which the memory DIMM is placed. Thus, when 1 DIMM
|
||||
is placed in each Channel, the csrows cross both DIMMs.
|
||||
|
||||
Memory DIMMs come single or dual "ranked". A rank is a populated csrow.
|
||||
Thus, 2 single ranked DIMMs, placed in slots DIMM_A0 and DIMM_B0 above
|
||||
will have 1 csrow, csrow0. csrow1 will be empty. On the other hand,
|
||||
when 2 dual ranked DIMMs are similiaryly placed, then both csrow0 and
|
||||
csrow1 will be populated. The pattern repeats itself for csrow2 and
|
||||
csrow3.
|
||||
|
||||
The representation of the above is reflected in the directory tree
|
||||
in EDAC's sysfs interface. Starting in directory
|
||||
/sys/devices/system/edac/mc each memory controller will be represented
|
||||
by its own 'mcX' directory, where 'X" is the index of the MC.
|
||||
|
||||
|
||||
..../edac/mc/
|
||||
|
|
||||
|->mc0
|
||||
|->mc1
|
||||
|->mc2
|
||||
....
|
||||
|
||||
Under each 'mcX' directory each 'csrowX' is again represented by a
|
||||
'csrowX', where 'X" is the csrow index:
|
||||
|
||||
|
||||
.../mc/mc0/
|
||||
|
|
||||
|->csrow0
|
||||
|->csrow2
|
||||
|->csrow3
|
||||
....
|
||||
|
||||
Notice that there is no csrow1, which indicates that csrow0 is
|
||||
composed of a single ranked DIMMs. This should also apply in both
|
||||
Channels, in order to have dual-channel mode be operational. Since
|
||||
both csrow2 and csrow3 are populated, this indicates a dual ranked
|
||||
set of DIMMs for channels 0 and 1.
|
||||
|
||||
|
||||
Within each of the 'mc','mcX' and 'csrowX' directories are several
|
||||
EDAC control and attribute files.
|
||||
|
||||
|
||||
============================================================================
|
||||
DIRECTORY 'mc'
|
||||
|
||||
In directory 'mc' are EDAC system overall control and attribute files:
|
||||
|
||||
|
||||
Panic on UE control file:
|
||||
|
||||
'panic_on_ue'
|
||||
|
||||
An uncorrectable error will cause a machine panic. This is usually
|
||||
desirable. It is a bad idea to continue when an uncorrectable error
|
||||
occurs - it is indeterminate what was uncorrected and the operating
|
||||
system context might be so mangled that continuing will lead to further
|
||||
corruption. If the kernel has MCE configured, then EDAC will never
|
||||
notice the UE.
|
||||
|
||||
LOAD TIME: module/kernel parameter: panic_on_ue=[0|1]
|
||||
|
||||
RUN TIME: echo "1" >/sys/devices/system/edac/mc/panic_on_ue
|
||||
|
||||
|
||||
Log UE control file:
|
||||
|
||||
'log_ue'
|
||||
|
||||
Generate kernel messages describing uncorrectable errors. These errors
|
||||
are reported through the system message log system. UE statistics
|
||||
will be accumulated even when UE logging is disabled.
|
||||
|
||||
LOAD TIME: module/kernel parameter: log_ue=[0|1]
|
||||
|
||||
RUN TIME: echo "1" >/sys/devices/system/edac/mc/log_ue
|
||||
|
||||
|
||||
Log CE control file:
|
||||
|
||||
'log_ce'
|
||||
|
||||
Generate kernel messages describing correctable errors. These
|
||||
errors are reported through the system message log system.
|
||||
CE statistics will be accumulated even when CE logging is disabled.
|
||||
|
||||
LOAD TIME: module/kernel parameter: log_ce=[0|1]
|
||||
|
||||
RUN TIME: echo "1" >/sys/devices/system/edac/mc/log_ce
|
||||
|
||||
|
||||
Polling period control file:
|
||||
|
||||
'poll_msec'
|
||||
|
||||
The time period, in milliseconds, for polling for error information.
|
||||
Too small a value wastes resources. Too large a value might delay
|
||||
necessary handling of errors and might loose valuable information for
|
||||
locating the error. 1000 milliseconds (once each second) is about
|
||||
right for most uses.
|
||||
|
||||
LOAD TIME: module/kernel parameter: poll_msec=[0|1]
|
||||
|
||||
RUN TIME: echo "1000" >/sys/devices/system/edac/mc/poll_msec
|
||||
|
||||
|
||||
Module Version read-only attribute file:
|
||||
|
||||
'mc_version'
|
||||
|
||||
The EDAC CORE modules's version and compile date are shown here to
|
||||
indicate what EDAC is running.
|
||||
|
||||
|
||||
|
||||
============================================================================
|
||||
'mcX' DIRECTORIES
|
||||
|
||||
|
||||
In 'mcX' directories are EDAC control and attribute files for
|
||||
this 'X" instance of the memory controllers:
|
||||
|
||||
|
||||
Counter reset control file:
|
||||
|
||||
'reset_counters'
|
||||
|
||||
This write-only control file will zero all the statistical counters
|
||||
for UE and CE errors. Zeroing the counters will also reset the timer
|
||||
indicating how long since the last counter zero. This is useful
|
||||
for computing errors/time. Since the counters are always reset at
|
||||
driver initialization time, no module/kernel parameter is available.
|
||||
|
||||
RUN TIME: echo "anything" >/sys/devices/system/edac/mc/mc0/counter_reset
|
||||
|
||||
This resets the counters on memory controller 0
|
||||
|
||||
|
||||
Seconds since last counter reset control file:
|
||||
|
||||
'seconds_since_reset'
|
||||
|
||||
This attribute file displays how many seconds have elapsed since the
|
||||
last counter reset. This can be used with the error counters to
|
||||
measure error rates.
|
||||
|
||||
|
||||
|
||||
DIMM capability attribute file:
|
||||
|
||||
'edac_capability'
|
||||
|
||||
The EDAC (Error Detection and Correction) capabilities/modes of
|
||||
the memory controller hardware.
|
||||
|
||||
|
||||
DIMM Current Capability attribute file:
|
||||
|
||||
'edac_current_capability'
|
||||
|
||||
The EDAC capabilities available with the hardware
|
||||
configuration. This may not be the same as "EDAC capability"
|
||||
if the correct memory is not used. If a memory controller is
|
||||
capable of EDAC, but DIMMs without check bits are in use, then
|
||||
Parity, SECDED, S4ECD4ED capabilities will not be available
|
||||
even though the memory controller might be capable of those
|
||||
modes with the proper memory loaded.
|
||||
|
||||
|
||||
Memory Type supported on this controller attribute file:
|
||||
|
||||
'supported_mem_type'
|
||||
|
||||
This attribute file displays the memory type, usually
|
||||
buffered and unbuffered DIMMs.
|
||||
|
||||
|
||||
Memory Controller name attribute file:
|
||||
|
||||
'mc_name'
|
||||
|
||||
This attribute file displays the type of memory controller
|
||||
that is being utilized.
|
||||
|
||||
|
||||
Memory Controller Module name attribute file:
|
||||
|
||||
'module_name'
|
||||
|
||||
This attribute file displays the memory controller module name,
|
||||
version and date built. The name of the memory controller
|
||||
hardware - some drivers work with multiple controllers and
|
||||
this field shows which hardware is present.
|
||||
|
||||
|
||||
Total memory managed by this memory controller attribute file:
|
||||
|
||||
'size_mb'
|
||||
|
||||
This attribute file displays, in count of megabytes, of memory
|
||||
that this instance of memory controller manages.
|
||||
|
||||
|
||||
Total Uncorrectable Errors count attribute file:
|
||||
|
||||
'ue_count'
|
||||
|
||||
This attribute file displays the total count of uncorrectable
|
||||
errors that have occurred on this memory controller. If panic_on_ue
|
||||
is set this counter will not have a chance to increment,
|
||||
since EDAC will panic the system.
|
||||
|
||||
|
||||
Total UE count that had no information attribute fileY:
|
||||
|
||||
'ue_noinfo_count'
|
||||
|
||||
This attribute file displays the number of UEs that
|
||||
have occurred have occurred with no informations as to which DIMM
|
||||
slot is having errors.
|
||||
|
||||
|
||||
Total Correctable Errors count attribute file:
|
||||
|
||||
'ce_count'
|
||||
|
||||
This attribute file displays the total count of correctable
|
||||
errors that have occurred on this memory controller. This
|
||||
count is very important to examine. CEs provide early
|
||||
indications that a DIMM is beginning to fail. This count
|
||||
field should be monitored for non-zero values and report
|
||||
such information to the system administrator.
|
||||
|
||||
|
||||
Total Correctable Errors count attribute file:
|
||||
|
||||
'ce_noinfo_count'
|
||||
|
||||
This attribute file displays the number of CEs that
|
||||
have occurred wherewith no informations as to which DIMM slot
|
||||
is having errors. Memory is handicapped, but operational,
|
||||
yet no information is available to indicate which slot
|
||||
the failing memory is in. This count field should be also
|
||||
be monitored for non-zero values.
|
||||
|
||||
Device Symlink:
|
||||
|
||||
'device'
|
||||
|
||||
Symlink to the memory controller device
|
||||
|
||||
|
||||
|
||||
============================================================================
|
||||
'csrowX' DIRECTORIES
|
||||
|
||||
In the 'csrowX' directories are EDAC control and attribute files for
|
||||
this 'X" instance of csrow:
|
||||
|
||||
|
||||
Total Uncorrectable Errors count attribute file:
|
||||
|
||||
'ue_count'
|
||||
|
||||
This attribute file displays the total count of uncorrectable
|
||||
errors that have occurred on this csrow. If panic_on_ue is set
|
||||
this counter will not have a chance to increment, since EDAC
|
||||
will panic the system.
|
||||
|
||||
|
||||
Total Correctable Errors count attribute file:
|
||||
|
||||
'ce_count'
|
||||
|
||||
This attribute file displays the total count of correctable
|
||||
errors that have occurred on this csrow. This
|
||||
count is very important to examine. CEs provide early
|
||||
indications that a DIMM is beginning to fail. This count
|
||||
field should be monitored for non-zero values and report
|
||||
such information to the system administrator.
|
||||
|
||||
|
||||
Total memory managed by this csrow attribute file:
|
||||
|
||||
'size_mb'
|
||||
|
||||
This attribute file displays, in count of megabytes, of memory
|
||||
that this csrow contatins.
|
||||
|
||||
|
||||
Memory Type attribute file:
|
||||
|
||||
'mem_type'
|
||||
|
||||
This attribute file will display what type of memory is currently
|
||||
on this csrow. Normally, either buffered or unbuffered memory.
|
||||
|
||||
|
||||
EDAC Mode of operation attribute file:
|
||||
|
||||
'edac_mode'
|
||||
|
||||
This attribute file will display what type of Error detection
|
||||
and correction is being utilized.
|
||||
|
||||
|
||||
Device type attribute file:
|
||||
|
||||
'dev_type'
|
||||
|
||||
This attribute file will display what type of DIMM device is
|
||||
being utilized. Example: x4
|
||||
|
||||
|
||||
Channel 0 CE Count attribute file:
|
||||
|
||||
'ch0_ce_count'
|
||||
|
||||
This attribute file will display the count of CEs on this
|
||||
DIMM located in channel 0.
|
||||
|
||||
|
||||
Channel 0 UE Count attribute file:
|
||||
|
||||
'ch0_ue_count'
|
||||
|
||||
This attribute file will display the count of UEs on this
|
||||
DIMM located in channel 0.
|
||||
|
||||
|
||||
Channel 0 DIMM Label control file:
|
||||
|
||||
'ch0_dimm_label'
|
||||
|
||||
This control file allows this DIMM to have a label assigned
|
||||
to it. With this label in the module, when errors occur
|
||||
the output can provide the DIMM label in the system log.
|
||||
This becomes vital for panic events to isolate the
|
||||
cause of the UE event.
|
||||
|
||||
DIMM Labels must be assigned after booting, with information
|
||||
that correctly identifies the physical slot with its
|
||||
silk screen label. This information is currently very
|
||||
motherboard specific and determination of this information
|
||||
must occur in userland at this time.
|
||||
|
||||
|
||||
Channel 1 CE Count attribute file:
|
||||
|
||||
'ch1_ce_count'
|
||||
|
||||
This attribute file will display the count of CEs on this
|
||||
DIMM located in channel 1.
|
||||
|
||||
|
||||
Channel 1 UE Count attribute file:
|
||||
|
||||
'ch1_ue_count'
|
||||
|
||||
This attribute file will display the count of UEs on this
|
||||
DIMM located in channel 0.
|
||||
|
||||
|
||||
Channel 1 DIMM Label control file:
|
||||
|
||||
'ch1_dimm_label'
|
||||
|
||||
This control file allows this DIMM to have a label assigned
|
||||
to it. With this label in the module, when errors occur
|
||||
the output can provide the DIMM label in the system log.
|
||||
This becomes vital for panic events to isolate the
|
||||
cause of the UE event.
|
||||
|
||||
DIMM Labels must be assigned after booting, with information
|
||||
that correctly identifies the physical slot with its
|
||||
silk screen label. This information is currently very
|
||||
motherboard specific and determination of this information
|
||||
must occur in userland at this time.
|
||||
|
||||
|
||||
============================================================================
|
||||
SYSTEM LOGGING
|
||||
|
||||
If logging for UEs and CEs are enabled then system logs will have
|
||||
error notices indicating errors that have been detected:
|
||||
|
||||
MC0: CE page 0x283, offset 0xce0, grain 8, syndrome 0x6ec3, row 0,
|
||||
channel 1 "DIMM_B1": amd76x_edac
|
||||
|
||||
MC0: CE page 0x1e5, offset 0xfb0, grain 8, syndrome 0xb741, row 0,
|
||||
channel 1 "DIMM_B1": amd76x_edac
|
||||
|
||||
|
||||
The structure of the message is:
|
||||
the memory controller (MC0)
|
||||
Error type (CE)
|
||||
memory page (0x283)
|
||||
offset in the page (0xce0)
|
||||
the byte granularity (grain 8)
|
||||
or resolution of the error
|
||||
the error syndrome (0xb741)
|
||||
memory row (row 0)
|
||||
memory channel (channel 1)
|
||||
DIMM label, if set prior (DIMM B1
|
||||
and then an optional, driver-specific message that may
|
||||
have additional information.
|
||||
|
||||
Both UEs and CEs with no info will lack all but memory controller,
|
||||
error type, a notice of "no info" and then an optional,
|
||||
driver-specific error message.
|
||||
|
||||
|
||||
|
||||
============================================================================
|
||||
PCI Bus Parity Detection
|
||||
|
||||
|
||||
On Header Type 00 devices the primary status is looked at
|
||||
for any parity error regardless of whether Parity is enabled on the
|
||||
device. (The spec indicates parity is generated in some cases).
|
||||
On Header Type 01 bridges, the secondary status register is also
|
||||
looked at to see if parity ocurred on the bus on the other side of
|
||||
the bridge.
|
||||
|
||||
|
||||
SYSFS CONFIGURATION
|
||||
|
||||
Under /sys/devices/system/edac/pci are control and attribute files as follows:
|
||||
|
||||
|
||||
Enable/Disable PCI Parity checking control file:
|
||||
|
||||
'check_pci_parity'
|
||||
|
||||
|
||||
This control file enables or disables the PCI Bus Parity scanning
|
||||
operation. Writing a 1 to this file enables the scanning. Writing
|
||||
a 0 to this file disables the scanning.
|
||||
|
||||
Enable:
|
||||
echo "1" >/sys/devices/system/edac/pci/check_pci_parity
|
||||
|
||||
Disable:
|
||||
echo "0" >/sys/devices/system/edac/pci/check_pci_parity
|
||||
|
||||
|
||||
|
||||
Panic on PCI PARITY Error:
|
||||
|
||||
'panic_on_pci_parity'
|
||||
|
||||
|
||||
This control files enables or disables panic'ing when a parity
|
||||
error has been detected.
|
||||
|
||||
|
||||
module/kernel parameter: panic_on_pci_parity=[0|1]
|
||||
|
||||
Enable:
|
||||
echo "1" >/sys/devices/system/edac/pci/panic_on_pci_parity
|
||||
|
||||
Disable:
|
||||
echo "0" >/sys/devices/system/edac/pci/panic_on_pci_parity
|
||||
|
||||
|
||||
Parity Count:
|
||||
|
||||
'pci_parity_count'
|
||||
|
||||
This attribute file will display the number of parity errors that
|
||||
have been detected.
|
||||
|
||||
|
||||
|
||||
PCI Device Whitelist:
|
||||
|
||||
'pci_parity_whitelist'
|
||||
|
||||
This control file allows for an explicit list of PCI devices to be
|
||||
scanned for parity errors. Only devices found on this list will
|
||||
be examined. The list is a line of hexadecimel VENDOR and DEVICE
|
||||
ID tuples:
|
||||
|
||||
1022:7450,1434:16a6
|
||||
|
||||
One or more can be inserted, seperated by a comma.
|
||||
|
||||
To write the above list doing the following as one command line:
|
||||
|
||||
echo "1022:7450,1434:16a6"
|
||||
> /sys/devices/system/edac/pci/pci_parity_whitelist
|
||||
|
||||
|
||||
|
||||
To display what the whitelist is, simply 'cat' the same file.
|
||||
|
||||
|
||||
PCI Device Blacklist:
|
||||
|
||||
'pci_parity_blacklist'
|
||||
|
||||
This control file allows for a list of PCI devices to be
|
||||
skipped for scanning.
|
||||
The list is a line of hexadecimel VENDOR and DEVICE ID tuples:
|
||||
|
||||
1022:7450,1434:16a6
|
||||
|
||||
One or more can be inserted, seperated by a comma.
|
||||
|
||||
To write the above list doing the following as one command line:
|
||||
|
||||
echo "1022:7450,1434:16a6"
|
||||
> /sys/devices/system/edac/pci/pci_parity_blacklist
|
||||
|
||||
|
||||
To display what the whitelist current contatins,
|
||||
simply 'cat' the same file.
|
||||
|
||||
=======================================================================
|
||||
|
||||
PCI Vendor and Devices IDs can be obtained with the lspci command. Using
|
||||
the -n option lspci will display the vendor and device IDs. The system
|
||||
adminstrator will have to determine which devices should be scanned or
|
||||
skipped.
|
||||
|
||||
|
||||
|
||||
The two lists (white and black) are prioritized. blacklist is the lower
|
||||
priority and will NOT be utilized when a whitelist has been set.
|
||||
Turn OFF a whitelist by an empty echo command:
|
||||
|
||||
echo > /sys/devices/system/edac/pci/pci_parity_whitelist
|
||||
|
||||
and any previous blacklist will be utililzed.
|
||||
|
@ -27,6 +27,7 @@ Currently, these files are in /proc/sys/vm:
|
||||
- laptop_mode
|
||||
- block_dump
|
||||
- drop-caches
|
||||
- zone_reclaim_mode
|
||||
|
||||
==============================================================
|
||||
|
||||
@ -120,3 +121,20 @@ set to pcp->high/4. The upper limit of batch is (PAGE_SHIFT * 8)
|
||||
|
||||
The initial value is zero. Kernel does not use this value at boot time to set
|
||||
the high water marks for each per cpu page list.
|
||||
|
||||
===============================================================
|
||||
|
||||
zone_reclaim_mode:
|
||||
|
||||
This is set during bootup to 1 if it is determined that pages from
|
||||
remote zones will cause a significant performance reduction. The
|
||||
page allocator will then reclaim easily reusable pages (those page
|
||||
cache pages that are currently not used) before going off node.
|
||||
|
||||
The user can override this setting. It may be beneficial to switch
|
||||
off zone reclaim if the system is used for a file server and all
|
||||
of memory should be used for caching files from disk.
|
||||
|
||||
It may be beneficial to switch this on if one wants to do zone
|
||||
reclaim regardless of the numa distances in the system.
|
||||
|
||||
|
26
MAINTAINERS
26
MAINTAINERS
@ -867,6 +867,15 @@ L: ebtables-devel@lists.sourceforge.net
|
||||
W: http://ebtables.sourceforge.net/
|
||||
S: Maintained
|
||||
|
||||
EDAC-CORE
|
||||
P: Doug Thompson
|
||||
M: norsk5@xmission.com, dthompson@linuxnetworx.com
|
||||
P: Dave Peterson
|
||||
M: dsp@llnl.gov, dave_peterson@pobox.com
|
||||
L: bluesmoke-devel@lists.sourceforge.net
|
||||
W: bluesmoke.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
EEPRO100 NETWORK DRIVER
|
||||
P: Andrey V. Savochkin
|
||||
M: saw@saw.sw.com.sg
|
||||
@ -1398,7 +1407,7 @@ IRDA SUBSYSTEM
|
||||
P: Jean Tourrilhes
|
||||
L: irda-users@lists.sourceforge.net (subscribers-only)
|
||||
W: http://irda.sourceforge.net/
|
||||
S: Maintained
|
||||
S: Odd Fixes
|
||||
|
||||
ISAPNP
|
||||
P: Jaroslav Kysela
|
||||
@ -1843,7 +1852,14 @@ M: yoshfuji@linux-ipv6.org
|
||||
P: Patrick McHardy
|
||||
M: kaber@coreworks.de
|
||||
L: netdev@vger.kernel.org
|
||||
T: git kernel.org:/pub/scm/linux/kernel/davem/net-2.6.git
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git
|
||||
S: Maintained
|
||||
|
||||
NETWORKING [WIRELESS]
|
||||
P: John W. Linville
|
||||
M: linville@tuxdriver.com
|
||||
L: netdev@vger.kernel.org
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
|
||||
S: Maintained
|
||||
|
||||
IPVS
|
||||
@ -2536,11 +2552,11 @@ S: Maintained
|
||||
|
||||
TIPC NETWORK LAYER
|
||||
P: Per Liden
|
||||
M: per.liden@nospam.ericsson.com
|
||||
M: per.liden@ericsson.com
|
||||
P: Jon Maloy
|
||||
M: jon.maloy@nospam.ericsson.com
|
||||
M: jon.maloy@ericsson.com
|
||||
P: Allan Stephens
|
||||
M: allan.stephens@nospam.windriver.com
|
||||
M: allan.stephens@windriver.com
|
||||
L: tipc-discussion@lists.sourceforge.net
|
||||
W: http://tipc.sourceforge.net/
|
||||
W: http://tipc.cslab.ericsson.net/
|
||||
|
@ -960,7 +960,7 @@ osf_utimes(char __user *filename, struct timeval32 __user *tvs)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return do_utimes(filename, tvs ? ktvs : NULL);
|
||||
return do_utimes(AT_FDCWD, filename, tvs ? ktvs : NULL);
|
||||
}
|
||||
|
||||
#define MAX_SELECT_SECONDS \
|
||||
|
@ -334,7 +334,7 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size
|
||||
mov r1, #0x12
|
||||
orr r1, r1, #3 << 10
|
||||
add r2, r3, #16384
|
||||
1: cmp r1, r8 @ if virt > start of RAM
|
||||
1: cmp r1, r9 @ if virt > start of RAM
|
||||
orrhs r1, r1, #0x0c @ set cacheable, bufferable
|
||||
cmp r1, r10 @ if virt > end of RAM
|
||||
bichs r1, r1, #0x0c @ clear cacheable, bufferable
|
||||
|
@ -735,8 +735,11 @@ __kuser_cmpxchg: @ 0xffff0fc0
|
||||
* The kernel itself must perform the operation.
|
||||
* A special ghost syscall is used for that (see traps.c).
|
||||
*/
|
||||
stmfd sp!, {r7, lr}
|
||||
mov r7, #0xff00 @ 0xfff0 into r7 for EABI
|
||||
orr r7, r7, #0xf0
|
||||
swi #0x9ffff0
|
||||
mov pc, lr
|
||||
ldmfd sp!, {r7, pc}
|
||||
|
||||
#elif __LINUX_ARM_ARCH__ < 6
|
||||
|
||||
|
@ -29,6 +29,12 @@
|
||||
#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn))
|
||||
#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn))
|
||||
|
||||
/*
|
||||
* With EABI, the syscall number has to be loaded into r7.
|
||||
*/
|
||||
#define MOV_R7_NR_SIGRETURN (0xe3a07000 | (__NR_sigreturn - __NR_SYSCALL_BASE))
|
||||
#define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
|
||||
|
||||
/*
|
||||
* For Thumb syscalls, we pass the syscall number via r7. We therefore
|
||||
* need two 16-bit instructions.
|
||||
@ -36,9 +42,9 @@
|
||||
#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
|
||||
#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
|
||||
|
||||
const unsigned long sigreturn_codes[4] = {
|
||||
SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
|
||||
SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
|
||||
const unsigned long sigreturn_codes[7] = {
|
||||
MOV_R7_NR_SIGRETURN, SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
|
||||
MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
|
||||
};
|
||||
|
||||
static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
|
||||
@ -189,7 +195,7 @@ struct aux_sigframe {
|
||||
struct sigframe {
|
||||
struct sigcontext sc;
|
||||
unsigned long extramask[_NSIG_WORDS-1];
|
||||
unsigned long retcode;
|
||||
unsigned long retcode[2];
|
||||
struct aux_sigframe aux __attribute__((aligned(8)));
|
||||
};
|
||||
|
||||
@ -198,7 +204,7 @@ struct rt_sigframe {
|
||||
void __user *puc;
|
||||
struct siginfo info;
|
||||
struct ucontext uc;
|
||||
unsigned long retcode;
|
||||
unsigned long retcode[2];
|
||||
struct aux_sigframe aux __attribute__((aligned(8)));
|
||||
};
|
||||
|
||||
@ -436,12 +442,13 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
retcode = (unsigned long)ka->sa.sa_restorer;
|
||||
} else {
|
||||
unsigned int idx = thumb;
|
||||
unsigned int idx = thumb << 1;
|
||||
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
idx += 2;
|
||||
idx += 3;
|
||||
|
||||
if (__put_user(sigreturn_codes[idx], rc))
|
||||
if (__put_user(sigreturn_codes[idx], rc) ||
|
||||
__put_user(sigreturn_codes[idx+1], rc+1))
|
||||
return 1;
|
||||
|
||||
if (cpsr & MODE32_BIT) {
|
||||
@ -456,7 +463,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
|
||||
* the return code written onto the stack.
|
||||
*/
|
||||
flush_icache_range((unsigned long)rc,
|
||||
(unsigned long)(rc + 1));
|
||||
(unsigned long)(rc + 2));
|
||||
|
||||
retcode = ((unsigned long)rc) + thumb;
|
||||
}
|
||||
@ -488,7 +495,7 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg
|
||||
}
|
||||
|
||||
if (err == 0)
|
||||
err = setup_return(regs, ka, &frame->retcode, frame, usig);
|
||||
err = setup_return(regs, ka, frame->retcode, frame, usig);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -522,7 +529,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
|
||||
if (err == 0)
|
||||
err = setup_return(regs, ka, &frame->retcode, frame, usig);
|
||||
err = setup_return(regs, ka, frame->retcode, frame, usig);
|
||||
|
||||
if (err == 0) {
|
||||
/*
|
||||
|
@ -9,4 +9,4 @@
|
||||
*/
|
||||
#define KERN_SIGRETURN_CODE 0xffff0500
|
||||
|
||||
extern const unsigned long sigreturn_codes[4];
|
||||
extern const unsigned long sigreturn_codes[7];
|
||||
|
@ -333,6 +333,7 @@ static struct platform_device *ixp46x_devices[] __initdata = {
|
||||
};
|
||||
|
||||
unsigned long ixp4xx_exp_bus_size;
|
||||
EXPORT_SYMBOL(ixp4xx_exp_bus_size);
|
||||
|
||||
void __init ixp4xx_sys_init(void)
|
||||
{
|
||||
@ -352,7 +353,7 @@ void __init ixp4xx_sys_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
printk("IXP4xx: Using %uMiB expansion bus window size\n",
|
||||
printk("IXP4xx: Using %luMiB expansion bus window size\n",
|
||||
ixp4xx_exp_bus_size >> 20);
|
||||
}
|
||||
|
||||
|
@ -50,10 +50,10 @@ static int omap1_clk_enable_dsp_domain(struct clk *clk)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = omap1_clk_use(&api_ck.clk);
|
||||
retval = omap1_clk_enable(&api_ck.clk);
|
||||
if (!retval) {
|
||||
retval = omap1_clk_enable(clk);
|
||||
omap1_clk_unuse(&api_ck.clk);
|
||||
retval = omap1_clk_enable_generic(clk);
|
||||
omap1_clk_disable(&api_ck.clk);
|
||||
}
|
||||
|
||||
return retval;
|
||||
@ -61,9 +61,9 @@ static int omap1_clk_enable_dsp_domain(struct clk *clk)
|
||||
|
||||
static void omap1_clk_disable_dsp_domain(struct clk *clk)
|
||||
{
|
||||
if (omap1_clk_use(&api_ck.clk) == 0) {
|
||||
omap1_clk_disable(clk);
|
||||
omap1_clk_unuse(&api_ck.clk);
|
||||
if (omap1_clk_enable(&api_ck.clk) == 0) {
|
||||
omap1_clk_disable_generic(clk);
|
||||
omap1_clk_disable(&api_ck.clk);
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ static int omap1_clk_enable_uart_functional(struct clk *clk)
|
||||
int ret;
|
||||
struct uart_clk *uclk;
|
||||
|
||||
ret = omap1_clk_enable(clk);
|
||||
ret = omap1_clk_enable_generic(clk);
|
||||
if (ret == 0) {
|
||||
/* Set smart idle acknowledgement mode */
|
||||
uclk = (struct uart_clk *)clk;
|
||||
@ -91,7 +91,7 @@ static void omap1_clk_disable_uart_functional(struct clk *clk)
|
||||
uclk = (struct uart_clk *)clk;
|
||||
omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr);
|
||||
|
||||
omap1_clk_disable(clk);
|
||||
omap1_clk_disable_generic(clk);
|
||||
}
|
||||
|
||||
static void omap1_clk_allow_idle(struct clk *clk)
|
||||
@ -230,9 +230,9 @@ static void omap1_ckctl_recalc_dsp_domain(struct clk * clk)
|
||||
* Note that DSP_CKCTL virt addr = phys addr, so
|
||||
* we must use __raw_readw() instead of omap_readw().
|
||||
*/
|
||||
omap1_clk_use(&api_ck.clk);
|
||||
omap1_clk_enable(&api_ck.clk);
|
||||
dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
|
||||
omap1_clk_unuse(&api_ck.clk);
|
||||
omap1_clk_disable(&api_ck.clk);
|
||||
|
||||
if (unlikely(clk->rate == clk->parent->rate / dsor))
|
||||
return; /* No change, quick exit */
|
||||
@ -412,12 +412,12 @@ static void omap1_init_ext_clk(struct clk * clk)
|
||||
clk-> rate = 96000000 / dsor;
|
||||
}
|
||||
|
||||
static int omap1_clk_use(struct clk *clk)
|
||||
static int omap1_clk_enable(struct clk *clk)
|
||||
{
|
||||
int ret = 0;
|
||||
if (clk->usecount++ == 0) {
|
||||
if (likely(clk->parent)) {
|
||||
ret = omap1_clk_use(clk->parent);
|
||||
ret = omap1_clk_enable(clk->parent);
|
||||
|
||||
if (unlikely(ret != 0)) {
|
||||
clk->usecount--;
|
||||
@ -432,7 +432,7 @@ static int omap1_clk_use(struct clk *clk)
|
||||
ret = clk->enable(clk);
|
||||
|
||||
if (unlikely(ret != 0) && clk->parent) {
|
||||
omap1_clk_unuse(clk->parent);
|
||||
omap1_clk_disable(clk->parent);
|
||||
clk->usecount--;
|
||||
}
|
||||
}
|
||||
@ -440,12 +440,12 @@ static int omap1_clk_use(struct clk *clk)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void omap1_clk_unuse(struct clk *clk)
|
||||
static void omap1_clk_disable(struct clk *clk)
|
||||
{
|
||||
if (clk->usecount > 0 && !(--clk->usecount)) {
|
||||
clk->disable(clk);
|
||||
if (likely(clk->parent)) {
|
||||
omap1_clk_unuse(clk->parent);
|
||||
omap1_clk_disable(clk->parent);
|
||||
if (clk->flags & CLOCK_NO_IDLE_PARENT)
|
||||
if (!cpu_is_omap24xx())
|
||||
omap1_clk_allow_idle(clk->parent);
|
||||
@ -453,7 +453,7 @@ static void omap1_clk_unuse(struct clk *clk)
|
||||
}
|
||||
}
|
||||
|
||||
static int omap1_clk_enable(struct clk *clk)
|
||||
static int omap1_clk_enable_generic(struct clk *clk)
|
||||
{
|
||||
__u16 regval16;
|
||||
__u32 regval32;
|
||||
@ -492,7 +492,7 @@ static int omap1_clk_enable(struct clk *clk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap1_clk_disable(struct clk *clk)
|
||||
static void omap1_clk_disable_generic(struct clk *clk)
|
||||
{
|
||||
__u16 regval16;
|
||||
__u32 regval32;
|
||||
@ -654,8 +654,8 @@ late_initcall(omap1_late_clk_reset);
|
||||
#endif
|
||||
|
||||
static struct clk_functions omap1_clk_functions = {
|
||||
.clk_use = omap1_clk_use,
|
||||
.clk_unuse = omap1_clk_unuse,
|
||||
.clk_enable = omap1_clk_enable,
|
||||
.clk_disable = omap1_clk_disable,
|
||||
.clk_round_rate = omap1_clk_round_rate,
|
||||
.clk_set_rate = omap1_clk_set_rate,
|
||||
};
|
||||
@ -780,9 +780,9 @@ int __init omap1_clk_init(void)
|
||||
* Only enable those clocks we will need, let the drivers
|
||||
* enable other clocks as necessary
|
||||
*/
|
||||
clk_use(&armper_ck.clk);
|
||||
clk_use(&armxor_ck.clk);
|
||||
clk_use(&armtim_ck.clk); /* This should be done by timer code */
|
||||
clk_enable(&armper_ck.clk);
|
||||
clk_enable(&armxor_ck.clk);
|
||||
clk_enable(&armtim_ck.clk); /* This should be done by timer code */
|
||||
|
||||
if (cpu_is_omap1510())
|
||||
clk_enable(&arm_gpio_ck);
|
||||
|
@ -13,8 +13,8 @@
|
||||
#ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H
|
||||
#define __ARCH_ARM_MACH_OMAP1_CLOCK_H
|
||||
|
||||
static int omap1_clk_enable(struct clk * clk);
|
||||
static void omap1_clk_disable(struct clk * clk);
|
||||
static int omap1_clk_enable_generic(struct clk * clk);
|
||||
static void omap1_clk_disable_generic(struct clk * clk);
|
||||
static void omap1_ckctl_recalc(struct clk * clk);
|
||||
static void omap1_watchdog_recalc(struct clk * clk);
|
||||
static void omap1_ckctl_recalc_dsp_domain(struct clk * clk);
|
||||
@ -30,8 +30,8 @@ static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate);
|
||||
static void omap1_init_ext_clk(struct clk * clk);
|
||||
static int omap1_select_table_rate(struct clk * clk, unsigned long rate);
|
||||
static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate);
|
||||
static int omap1_clk_use(struct clk *clk);
|
||||
static void omap1_clk_unuse(struct clk *clk);
|
||||
static int omap1_clk_enable(struct clk *clk);
|
||||
static void omap1_clk_disable(struct clk *clk);
|
||||
|
||||
struct mpu_rate {
|
||||
unsigned long rate;
|
||||
@ -152,8 +152,8 @@ static struct clk ck_ref = {
|
||||
.rate = 12000000,
|
||||
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
|
||||
ALWAYS_ENABLED,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk ck_dpll1 = {
|
||||
@ -161,8 +161,8 @@ static struct clk ck_dpll1 = {
|
||||
.parent = &ck_ref,
|
||||
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
|
||||
RATE_PROPAGATES | ALWAYS_ENABLED,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct arm_idlect1_clk ck_dpll1out = {
|
||||
@ -173,8 +173,8 @@ static struct arm_idlect1_clk ck_dpll1out = {
|
||||
.enable_reg = (void __iomem *)ARM_IDLECT2,
|
||||
.enable_bit = EN_CKOUT_ARM,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
},
|
||||
.idlect_shift = 12,
|
||||
};
|
||||
@ -186,8 +186,8 @@ static struct clk arm_ck = {
|
||||
RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
|
||||
.rate_offset = CKCTL_ARMDIV_OFFSET,
|
||||
.recalc = &omap1_ckctl_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct arm_idlect1_clk armper_ck = {
|
||||
@ -200,8 +200,8 @@ static struct arm_idlect1_clk armper_ck = {
|
||||
.enable_bit = EN_PERCK,
|
||||
.rate_offset = CKCTL_PERDIV_OFFSET,
|
||||
.recalc = &omap1_ckctl_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
},
|
||||
.idlect_shift = 2,
|
||||
};
|
||||
@ -213,8 +213,8 @@ static struct clk arm_gpio_ck = {
|
||||
.enable_reg = (void __iomem *)ARM_IDLECT2,
|
||||
.enable_bit = EN_GPIOCK,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct arm_idlect1_clk armxor_ck = {
|
||||
@ -226,8 +226,8 @@ static struct arm_idlect1_clk armxor_ck = {
|
||||
.enable_reg = (void __iomem *)ARM_IDLECT2,
|
||||
.enable_bit = EN_XORPCK,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
},
|
||||
.idlect_shift = 1,
|
||||
};
|
||||
@ -241,8 +241,8 @@ static struct arm_idlect1_clk armtim_ck = {
|
||||
.enable_reg = (void __iomem *)ARM_IDLECT2,
|
||||
.enable_bit = EN_TIMCK,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
},
|
||||
.idlect_shift = 9,
|
||||
};
|
||||
@ -256,8 +256,8 @@ static struct arm_idlect1_clk armwdt_ck = {
|
||||
.enable_reg = (void __iomem *)ARM_IDLECT2,
|
||||
.enable_bit = EN_WDTCK,
|
||||
.recalc = &omap1_watchdog_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
},
|
||||
.idlect_shift = 0,
|
||||
};
|
||||
@ -272,8 +272,8 @@ static struct clk arminth_ck16xx = {
|
||||
*
|
||||
* 1510 version is in TC clocks.
|
||||
*/
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk dsp_ck = {
|
||||
@ -285,8 +285,8 @@ static struct clk dsp_ck = {
|
||||
.enable_bit = EN_DSPCK,
|
||||
.rate_offset = CKCTL_DSPDIV_OFFSET,
|
||||
.recalc = &omap1_ckctl_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk dspmmu_ck = {
|
||||
@ -296,8 +296,8 @@ static struct clk dspmmu_ck = {
|
||||
RATE_CKCTL | ALWAYS_ENABLED,
|
||||
.rate_offset = CKCTL_DSPMMUDIV_OFFSET,
|
||||
.recalc = &omap1_ckctl_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk dspper_ck = {
|
||||
@ -349,8 +349,8 @@ static struct arm_idlect1_clk tc_ck = {
|
||||
CLOCK_IDLE_CONTROL,
|
||||
.rate_offset = CKCTL_TCDIV_OFFSET,
|
||||
.recalc = &omap1_ckctl_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
},
|
||||
.idlect_shift = 6,
|
||||
};
|
||||
@ -364,8 +364,8 @@ static struct clk arminth_ck1510 = {
|
||||
*
|
||||
* 16xx version is in MPU clocks.
|
||||
*/
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk tipb_ck = {
|
||||
@ -374,8 +374,8 @@ static struct clk tipb_ck = {
|
||||
.parent = &tc_ck.clk,
|
||||
.flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk l3_ocpi_ck = {
|
||||
@ -386,8 +386,8 @@ static struct clk l3_ocpi_ck = {
|
||||
.enable_reg = (void __iomem *)ARM_IDLECT3,
|
||||
.enable_bit = EN_OCPI_CK,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk tc1_ck = {
|
||||
@ -397,8 +397,8 @@ static struct clk tc1_ck = {
|
||||
.enable_reg = (void __iomem *)ARM_IDLECT3,
|
||||
.enable_bit = EN_TC1_CK,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk tc2_ck = {
|
||||
@ -408,8 +408,8 @@ static struct clk tc2_ck = {
|
||||
.enable_reg = (void __iomem *)ARM_IDLECT3,
|
||||
.enable_bit = EN_TC2_CK,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk dma_ck = {
|
||||
@ -419,8 +419,8 @@ static struct clk dma_ck = {
|
||||
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
|
||||
ALWAYS_ENABLED,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk dma_lcdfree_ck = {
|
||||
@ -428,8 +428,8 @@ static struct clk dma_lcdfree_ck = {
|
||||
.parent = &tc_ck.clk,
|
||||
.flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct arm_idlect1_clk api_ck = {
|
||||
@ -441,8 +441,8 @@ static struct arm_idlect1_clk api_ck = {
|
||||
.enable_reg = (void __iomem *)ARM_IDLECT2,
|
||||
.enable_bit = EN_APICK,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
},
|
||||
.idlect_shift = 8,
|
||||
};
|
||||
@ -455,8 +455,8 @@ static struct arm_idlect1_clk lb_ck = {
|
||||
.enable_reg = (void __iomem *)ARM_IDLECT2,
|
||||
.enable_bit = EN_LBCK,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
},
|
||||
.idlect_shift = 4,
|
||||
};
|
||||
@ -466,8 +466,8 @@ static struct clk rhea1_ck = {
|
||||
.parent = &tc_ck.clk,
|
||||
.flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk rhea2_ck = {
|
||||
@ -475,8 +475,8 @@ static struct clk rhea2_ck = {
|
||||
.parent = &tc_ck.clk,
|
||||
.flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
|
||||
.recalc = &followparent_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk lcd_ck_16xx = {
|
||||
@ -487,8 +487,8 @@ static struct clk lcd_ck_16xx = {
|
||||
.enable_bit = EN_LCDCK,
|
||||
.rate_offset = CKCTL_LCDDIV_OFFSET,
|
||||
.recalc = &omap1_ckctl_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct arm_idlect1_clk lcd_ck_1510 = {
|
||||
@ -501,8 +501,8 @@ static struct arm_idlect1_clk lcd_ck_1510 = {
|
||||
.enable_bit = EN_LCDCK,
|
||||
.rate_offset = CKCTL_LCDDIV_OFFSET,
|
||||
.recalc = &omap1_ckctl_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
},
|
||||
.idlect_shift = 3,
|
||||
};
|
||||
@ -518,8 +518,8 @@ static struct clk uart1_1510 = {
|
||||
.enable_bit = 29, /* Chooses between 12MHz and 48MHz */
|
||||
.set_rate = &omap1_set_uart_rate,
|
||||
.recalc = &omap1_uart_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct uart_clk uart1_16xx = {
|
||||
@ -550,8 +550,8 @@ static struct clk uart2_ck = {
|
||||
.enable_bit = 30, /* Chooses between 12MHz and 48MHz */
|
||||
.set_rate = &omap1_set_uart_rate,
|
||||
.recalc = &omap1_uart_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk uart3_1510 = {
|
||||
@ -565,8 +565,8 @@ static struct clk uart3_1510 = {
|
||||
.enable_bit = 31, /* Chooses between 12MHz and 48MHz */
|
||||
.set_rate = &omap1_set_uart_rate,
|
||||
.recalc = &omap1_uart_recalc,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct uart_clk uart3_16xx = {
|
||||
@ -593,8 +593,8 @@ static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
|
||||
RATE_FIXED | ENABLE_REG_32BIT,
|
||||
.enable_reg = (void __iomem *)ULPD_CLOCK_CTRL,
|
||||
.enable_bit = USB_MCLK_EN_BIT,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk usb_hhc_ck1510 = {
|
||||
@ -605,8 +605,8 @@ static struct clk usb_hhc_ck1510 = {
|
||||
RATE_FIXED | ENABLE_REG_32BIT,
|
||||
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
|
||||
.enable_bit = USB_HOST_HHC_UHOST_EN,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk usb_hhc_ck16xx = {
|
||||
@ -618,8 +618,8 @@ static struct clk usb_hhc_ck16xx = {
|
||||
RATE_FIXED | ENABLE_REG_32BIT,
|
||||
.enable_reg = (void __iomem *)OTG_BASE + 0x08 /* OTG_SYSCON_2 */,
|
||||
.enable_bit = 8 /* UHOST_EN */,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk usb_dc_ck = {
|
||||
@ -629,8 +629,8 @@ static struct clk usb_dc_ck = {
|
||||
.flags = CLOCK_IN_OMAP16XX | RATE_FIXED,
|
||||
.enable_reg = (void __iomem *)SOFT_REQ_REG,
|
||||
.enable_bit = 4,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk mclk_1510 = {
|
||||
@ -638,8 +638,8 @@ static struct clk mclk_1510 = {
|
||||
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
|
||||
.rate = 12000000,
|
||||
.flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk mclk_16xx = {
|
||||
@ -651,8 +651,8 @@ static struct clk mclk_16xx = {
|
||||
.set_rate = &omap1_set_ext_clk_rate,
|
||||
.round_rate = &omap1_round_ext_clk_rate,
|
||||
.init = &omap1_init_ext_clk,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk bclk_1510 = {
|
||||
@ -660,8 +660,8 @@ static struct clk bclk_1510 = {
|
||||
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
|
||||
.rate = 12000000,
|
||||
.flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk bclk_16xx = {
|
||||
@ -673,8 +673,8 @@ static struct clk bclk_16xx = {
|
||||
.set_rate = &omap1_set_ext_clk_rate,
|
||||
.round_rate = &omap1_round_ext_clk_rate,
|
||||
.init = &omap1_init_ext_clk,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk mmc1_ck = {
|
||||
@ -686,8 +686,8 @@ static struct clk mmc1_ck = {
|
||||
RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
|
||||
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
|
||||
.enable_bit = 23,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk mmc2_ck = {
|
||||
@ -699,8 +699,8 @@ static struct clk mmc2_ck = {
|
||||
RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
|
||||
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
|
||||
.enable_bit = 20,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk virtual_ck_mpu = {
|
||||
@ -711,8 +711,8 @@ static struct clk virtual_ck_mpu = {
|
||||
.recalc = &followparent_recalc,
|
||||
.set_rate = &omap1_select_table_rate,
|
||||
.round_rate = &omap1_round_to_table_rate,
|
||||
.enable = &omap1_clk_enable,
|
||||
.disable = &omap1_clk_disable,
|
||||
.enable = &omap1_clk_enable_generic,
|
||||
.disable = &omap1_clk_disable_generic,
|
||||
};
|
||||
|
||||
static struct clk * onchip_clks[] = {
|
||||
|
@ -146,7 +146,7 @@ void __init omap_serial_init(void)
|
||||
if (IS_ERR(uart1_ck))
|
||||
printk("Could not get uart1_ck\n");
|
||||
else {
|
||||
clk_use(uart1_ck);
|
||||
clk_enable(uart1_ck);
|
||||
if (cpu_is_omap1510())
|
||||
clk_set_rate(uart1_ck, 12000000);
|
||||
}
|
||||
@ -166,7 +166,7 @@ void __init omap_serial_init(void)
|
||||
if (IS_ERR(uart2_ck))
|
||||
printk("Could not get uart2_ck\n");
|
||||
else {
|
||||
clk_use(uart2_ck);
|
||||
clk_enable(uart2_ck);
|
||||
if (cpu_is_omap1510())
|
||||
clk_set_rate(uart2_ck, 12000000);
|
||||
else
|
||||
@ -188,7 +188,7 @@ void __init omap_serial_init(void)
|
||||
if (IS_ERR(uart3_ck))
|
||||
printk("Could not get uart3_ck\n");
|
||||
else {
|
||||
clk_use(uart3_ck);
|
||||
clk_enable(uart3_ck);
|
||||
if (cpu_is_omap1510())
|
||||
clk_set_rate(uart3_ck, 12000000);
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ static void omap2_clk_fixed_enable(struct clk *clk)
|
||||
/* Enables clock without considering parent dependencies or use count
|
||||
* REVISIT: Maybe change this to use clk->enable like on omap1?
|
||||
*/
|
||||
static int omap2_clk_enable(struct clk * clk)
|
||||
static int _omap2_clk_enable(struct clk * clk)
|
||||
{
|
||||
u32 regval32;
|
||||
|
||||
@ -150,7 +150,7 @@ static void omap2_clk_fixed_disable(struct clk *clk)
|
||||
}
|
||||
|
||||
/* Disables clock without considering parent dependencies or use count */
|
||||
static void omap2_clk_disable(struct clk *clk)
|
||||
static void _omap2_clk_disable(struct clk *clk)
|
||||
{
|
||||
u32 regval32;
|
||||
|
||||
@ -167,23 +167,23 @@ static void omap2_clk_disable(struct clk *clk)
|
||||
__raw_writel(regval32, clk->enable_reg);
|
||||
}
|
||||
|
||||
static int omap2_clk_use(struct clk *clk)
|
||||
static int omap2_clk_enable(struct clk *clk)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (clk->usecount++ == 0) {
|
||||
if (likely((u32)clk->parent))
|
||||
ret = omap2_clk_use(clk->parent);
|
||||
ret = omap2_clk_enable(clk->parent);
|
||||
|
||||
if (unlikely(ret != 0)) {
|
||||
clk->usecount--;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = omap2_clk_enable(clk);
|
||||
ret = _omap2_clk_enable(clk);
|
||||
|
||||
if (unlikely(ret != 0) && clk->parent) {
|
||||
omap2_clk_unuse(clk->parent);
|
||||
omap2_clk_disable(clk->parent);
|
||||
clk->usecount--;
|
||||
}
|
||||
}
|
||||
@ -191,12 +191,12 @@ static int omap2_clk_use(struct clk *clk)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void omap2_clk_unuse(struct clk *clk)
|
||||
static void omap2_clk_disable(struct clk *clk)
|
||||
{
|
||||
if (clk->usecount > 0 && !(--clk->usecount)) {
|
||||
omap2_clk_disable(clk);
|
||||
_omap2_clk_disable(clk);
|
||||
if (likely((u32)clk->parent))
|
||||
omap2_clk_unuse(clk->parent);
|
||||
omap2_clk_disable(clk->parent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -873,7 +873,7 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
|
||||
reg = (void __iomem *)src_sel;
|
||||
|
||||
if (clk->usecount > 0)
|
||||
omap2_clk_disable(clk);
|
||||
_omap2_clk_disable(clk);
|
||||
|
||||
/* Set new source value (previous dividers if any in effect) */
|
||||
reg_val = __raw_readl(reg) & ~(field_mask << src_off);
|
||||
@ -884,7 +884,7 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
|
||||
__raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
|
||||
|
||||
if (clk->usecount > 0)
|
||||
omap2_clk_enable(clk);
|
||||
_omap2_clk_enable(clk);
|
||||
|
||||
clk->parent = new_parent;
|
||||
|
||||
@ -999,8 +999,6 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
|
||||
static struct clk_functions omap2_clk_functions = {
|
||||
.clk_enable = omap2_clk_enable,
|
||||
.clk_disable = omap2_clk_disable,
|
||||
.clk_use = omap2_clk_use,
|
||||
.clk_unuse = omap2_clk_unuse,
|
||||
.clk_round_rate = omap2_clk_round_rate,
|
||||
.clk_set_rate = omap2_clk_set_rate,
|
||||
.clk_set_parent = omap2_clk_set_parent,
|
||||
@ -1045,7 +1043,7 @@ static void __init omap2_disable_unused_clocks(void)
|
||||
continue;
|
||||
|
||||
printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name);
|
||||
omap2_clk_disable(ck);
|
||||
_omap2_clk_disable(ck);
|
||||
}
|
||||
}
|
||||
late_initcall(omap2_disable_unused_clocks);
|
||||
@ -1120,10 +1118,10 @@ int __init omap2_clk_init(void)
|
||||
* Only enable those clocks we will need, let the drivers
|
||||
* enable other clocks as necessary
|
||||
*/
|
||||
clk_use(&sync_32k_ick);
|
||||
clk_use(&omapctrl_ick);
|
||||
clk_enable(&sync_32k_ick);
|
||||
clk_enable(&omapctrl_ick);
|
||||
if (cpu_is_omap2430())
|
||||
clk_use(&sdrc_ick);
|
||||
clk_enable(&sdrc_ick);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ static void omap2_propagate_rate(struct clk * clk);
|
||||
static void omap2_mpu_recalc(struct clk * clk);
|
||||
static int omap2_select_table_rate(struct clk * clk, unsigned long rate);
|
||||
static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate);
|
||||
static void omap2_clk_unuse(struct clk *clk);
|
||||
static void omap2_clk_disable(struct clk *clk);
|
||||
static void omap2_sys_clk_recalc(struct clk * clk);
|
||||
static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val);
|
||||
static u32 omap2_clksel_get_divisor(struct clk *clk);
|
||||
@ -859,7 +859,7 @@ static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */
|
||||
|
||||
static struct clk usb_l4_ick = { /* FS-USB interface clock */
|
||||
.name = "usb_l4_ick",
|
||||
.parent = &core_ck,
|
||||
.parent = &core_l3_ck,
|
||||
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
|
||||
RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP |
|
||||
CONFIG_PARTICIPANT,
|
||||
@ -1045,7 +1045,7 @@ static struct clk gpt1_ick = {
|
||||
.name = "gpt1_ick",
|
||||
.parent = &l4_ck,
|
||||
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
|
||||
.enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, /* Bit4 */
|
||||
.enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, /* Bit0 */
|
||||
.enable_bit = 0,
|
||||
.recalc = &omap2_followparent_recalc,
|
||||
};
|
||||
@ -1055,7 +1055,7 @@ static struct clk gpt1_fck = {
|
||||
.parent = &func_32k_ck,
|
||||
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
|
||||
CM_WKUP_SEL1,
|
||||
.enable_reg = (void __iomem *)&CM_FCLKEN_WKUP,
|
||||
.enable_reg = (void __iomem *)&CM_FCLKEN_WKUP, /* Bit0 */
|
||||
.enable_bit = 0,
|
||||
.src_offset = 0,
|
||||
.recalc = &omap2_followparent_recalc,
|
||||
@ -1065,7 +1065,7 @@ static struct clk gpt2_ick = {
|
||||
.name = "gpt2_ick",
|
||||
.parent = &l4_ck,
|
||||
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
|
||||
.enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit4 */
|
||||
.enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit4 */
|
||||
.enable_bit = 0,
|
||||
.recalc = &omap2_followparent_recalc,
|
||||
};
|
||||
@ -1839,7 +1839,7 @@ static struct clk usb_fck = {
|
||||
|
||||
static struct clk usbhs_ick = {
|
||||
.name = "usbhs_ick",
|
||||
.parent = &l4_ck,
|
||||
.parent = &core_l3_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
|
||||
.enable_bit = 6,
|
||||
|
@ -119,14 +119,14 @@ void __init omap_serial_init()
|
||||
if (IS_ERR(uart1_ick))
|
||||
printk("Could not get uart1_ick\n");
|
||||
else {
|
||||
clk_use(uart1_ick);
|
||||
clk_enable(uart1_ick);
|
||||
}
|
||||
|
||||
uart1_fck = clk_get(NULL, "uart1_fck");
|
||||
if (IS_ERR(uart1_fck))
|
||||
printk("Could not get uart1_fck\n");
|
||||
else {
|
||||
clk_use(uart1_fck);
|
||||
clk_enable(uart1_fck);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
@ -134,14 +134,14 @@ void __init omap_serial_init()
|
||||
if (IS_ERR(uart2_ick))
|
||||
printk("Could not get uart2_ick\n");
|
||||
else {
|
||||
clk_use(uart2_ick);
|
||||
clk_enable(uart2_ick);
|
||||
}
|
||||
|
||||
uart2_fck = clk_get(NULL, "uart2_fck");
|
||||
if (IS_ERR(uart2_fck))
|
||||
printk("Could not get uart2_fck\n");
|
||||
else {
|
||||
clk_use(uart2_fck);
|
||||
clk_enable(uart2_fck);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
@ -149,14 +149,14 @@ void __init omap_serial_init()
|
||||
if (IS_ERR(uart3_ick))
|
||||
printk("Could not get uart3_ick\n");
|
||||
else {
|
||||
clk_use(uart3_ick);
|
||||
clk_enable(uart3_ick);
|
||||
}
|
||||
|
||||
uart3_fck = clk_get(NULL, "uart3_fck");
|
||||
if (IS_ERR(uart3_fck))
|
||||
printk("Could not get uart3_fck\n");
|
||||
else {
|
||||
clk_use(uart3_fck);
|
||||
clk_enable(uart3_fck);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ static void __init omap2_gp_timer_init(void)
|
||||
if (IS_ERR(sys_ck))
|
||||
printk(KERN_ERR "Could not get sys_ck\n");
|
||||
else {
|
||||
clk_use(sys_ck);
|
||||
clk_enable(sys_ck);
|
||||
tick_period = clk_get_rate(sys_ck) / 100;
|
||||
clk_put(sys_ck);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ DEFINE_SPINLOCK(clockfw_lock);
|
||||
static struct clk_functions *arch_clock;
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Standard clock functions defined in asm/hardware/clock.h
|
||||
* Standard clock functions defined in include/linux/clk.h
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
struct clk * clk_get(struct device *dev, const char *id)
|
||||
@ -60,12 +60,8 @@ int clk_enable(struct clk *clk)
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&clockfw_lock, flags);
|
||||
if (clk->enable)
|
||||
ret = clk->enable(clk);
|
||||
else if (arch_clock->clk_enable)
|
||||
if (arch_clock->clk_enable)
|
||||
ret = arch_clock->clk_enable(clk);
|
||||
else
|
||||
printk(KERN_ERR "Could not enable clock %s\n", clk->name);
|
||||
spin_unlock_irqrestore(&clockfw_lock, flags);
|
||||
|
||||
return ret;
|
||||
@ -77,41 +73,12 @@ void clk_disable(struct clk *clk)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&clockfw_lock, flags);
|
||||
if (clk->disable)
|
||||
clk->disable(clk);
|
||||
else if (arch_clock->clk_disable)
|
||||
if (arch_clock->clk_disable)
|
||||
arch_clock->clk_disable(clk);
|
||||
else
|
||||
printk(KERN_ERR "Could not disable clock %s\n", clk->name);
|
||||
spin_unlock_irqrestore(&clockfw_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_disable);
|
||||
|
||||
int clk_use(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&clockfw_lock, flags);
|
||||
if (arch_clock->clk_use)
|
||||
ret = arch_clock->clk_use(clk);
|
||||
spin_unlock_irqrestore(&clockfw_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_use);
|
||||
|
||||
void clk_unuse(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&clockfw_lock, flags);
|
||||
if (arch_clock->clk_unuse)
|
||||
arch_clock->clk_unuse(clk);
|
||||
spin_unlock_irqrestore(&clockfw_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_unuse);
|
||||
|
||||
int clk_get_usecount(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
@ -146,7 +113,7 @@ void clk_put(struct clk *clk)
|
||||
EXPORT_SYMBOL(clk_put);
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Optional clock functions defined in asm/hardware/clock.h
|
||||
* Optional clock functions defined in include/linux/clk.h
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
long clk_round_rate(struct clk *clk, unsigned long rate)
|
||||
|
@ -853,19 +853,19 @@ static int __init _omap_gpio_init(void)
|
||||
if (IS_ERR(gpio_ick))
|
||||
printk("Could not get arm_gpio_ck\n");
|
||||
else
|
||||
clk_use(gpio_ick);
|
||||
clk_enable(gpio_ick);
|
||||
}
|
||||
if (cpu_is_omap24xx()) {
|
||||
gpio_ick = clk_get(NULL, "gpios_ick");
|
||||
if (IS_ERR(gpio_ick))
|
||||
printk("Could not get gpios_ick\n");
|
||||
else
|
||||
clk_use(gpio_ick);
|
||||
clk_enable(gpio_ick);
|
||||
gpio_fck = clk_get(NULL, "gpios_fck");
|
||||
if (IS_ERR(gpio_ick))
|
||||
printk("Could not get gpios_fck\n");
|
||||
else
|
||||
clk_use(gpio_fck);
|
||||
clk_enable(gpio_fck);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP15XX
|
||||
|
@ -190,11 +190,11 @@ static int omap_mcbsp_check(unsigned int id)
|
||||
static void omap_mcbsp_dsp_request(void)
|
||||
{
|
||||
if (cpu_is_omap1510() || cpu_is_omap16xx()) {
|
||||
clk_use(mcbsp_dsp_ck);
|
||||
clk_use(mcbsp_api_ck);
|
||||
clk_enable(mcbsp_dsp_ck);
|
||||
clk_enable(mcbsp_api_ck);
|
||||
|
||||
/* enable 12MHz clock to mcbsp 1 & 3 */
|
||||
clk_use(mcbsp_dspxor_ck);
|
||||
clk_enable(mcbsp_dspxor_ck);
|
||||
|
||||
/*
|
||||
* DSP external peripheral reset
|
||||
@ -208,9 +208,9 @@ static void omap_mcbsp_dsp_request(void)
|
||||
static void omap_mcbsp_dsp_free(void)
|
||||
{
|
||||
if (cpu_is_omap1510() || cpu_is_omap16xx()) {
|
||||
clk_unuse(mcbsp_dspxor_ck);
|
||||
clk_unuse(mcbsp_dsp_ck);
|
||||
clk_unuse(mcbsp_api_ck);
|
||||
clk_disable(mcbsp_dspxor_ck);
|
||||
clk_disable(mcbsp_dsp_ck);
|
||||
clk_disable(mcbsp_api_ck);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ static int __init omap_ocpi_init(void)
|
||||
if (IS_ERR(ocpi_ck))
|
||||
return PTR_ERR(ocpi_ck);
|
||||
|
||||
clk_use(ocpi_ck);
|
||||
clk_enable(ocpi_ck);
|
||||
ocpi_enable();
|
||||
printk("OMAP OCPI interconnect driver loaded\n");
|
||||
|
||||
@ -102,7 +102,7 @@ static void __exit omap_ocpi_exit(void)
|
||||
if (!cpu_is_omap16xx())
|
||||
return;
|
||||
|
||||
clk_unuse(ocpi_ck);
|
||||
clk_disable(ocpi_ck);
|
||||
clk_put(ocpi_ck);
|
||||
}
|
||||
|
||||
|
@ -35,74 +35,22 @@ struct fdpic_func_descriptor {
|
||||
unsigned long GOT;
|
||||
};
|
||||
|
||||
static int do_signal(sigset_t *oldset);
|
||||
|
||||
/*
|
||||
* Atomically swap in the new signal mask, and wait for a signal.
|
||||
*/
|
||||
asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||
{
|
||||
sigset_t saveset;
|
||||
|
||||
mask &= _BLOCKABLE;
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->saved_sigmask = current->blocked;
|
||||
siginitset(¤t->blocked, mask);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
__frame->gr8 = -EINTR;
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(&saveset))
|
||||
/* return the signal number as the return value of this function
|
||||
* - this is an utterly evil hack. syscalls should not invoke do_signal()
|
||||
* as entry.S sets regs->gr8 to the return value of the system call
|
||||
* - we can't just use sigpending() as we'd have to discard SIG_IGN signals
|
||||
* and call waitpid() if SIGCHLD needed discarding
|
||||
* - this only works on the i386 because it passes arguments to the signal
|
||||
* handler on the stack, and the return value in EAX is effectively
|
||||
* discarded
|
||||
*/
|
||||
return __frame->gr8;
|
||||
}
|
||||
}
|
||||
|
||||
asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
|
||||
{
|
||||
sigset_t saveset, newset;
|
||||
|
||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
||||
return -EFAULT;
|
||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->blocked = newset;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
__frame->gr8 = -EINTR;
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(&saveset))
|
||||
/* return the signal number as the return value of this function
|
||||
* - this is an utterly evil hack. syscalls should not invoke do_signal()
|
||||
* as entry.S sets regs->gr8 to the return value of the system call
|
||||
* - we can't just use sigpending() as we'd have to discard SIG_IGN signals
|
||||
* and call waitpid() if SIGCHLD needed discarding
|
||||
* - this only works on the i386 because it passes arguments to the signal
|
||||
* handler on the stack, and the return value in EAX is effectively
|
||||
* discarded
|
||||
*/
|
||||
return __frame->gr8;
|
||||
}
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
asmlinkage int sys_sigaction(int sig,
|
||||
@ -372,11 +320,11 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
|
||||
frame->pretcode);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
return -EFAULT;
|
||||
|
||||
} /* end setup_frame() */
|
||||
|
||||
@ -471,11 +419,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
frame->pretcode);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
return -EFAULT;
|
||||
|
||||
} /* end setup_rt_frame() */
|
||||
|
||||
@ -516,7 +464,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset);
|
||||
|
||||
if (ret) {
|
||||
if (ret == 0) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked,
|
||||
&ka->sa.sa_mask);
|
||||
@ -536,10 +484,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
||||
* mistake.
|
||||
*/
|
||||
static int do_signal(sigset_t *oldset)
|
||||
static void do_signal(void)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
sigset_t *oldset;
|
||||
int signr;
|
||||
|
||||
/*
|
||||
@ -549,43 +498,62 @@ static int do_signal(sigset_t *oldset)
|
||||
* if so.
|
||||
*/
|
||||
if (!user_mode(__frame))
|
||||
return 1;
|
||||
return;
|
||||
|
||||
if (try_to_freeze())
|
||||
goto no_signal;
|
||||
|
||||
if (!oldset)
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
|
||||
if (signr > 0)
|
||||
return handle_signal(signr, &info, &ka, oldset);
|
||||
if (signr > 0) {
|
||||
if (handle_signal(signr, &info, &ka, oldset) == 0) {
|
||||
/* a signal was successfully delivered; the saved
|
||||
* sigmask will have been stored in the signal frame,
|
||||
* and will be restored by sigreturn, so we can simply
|
||||
* clear the TIF_RESTORE_SIGMASK flag */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
no_signal:
|
||||
/* Did we come from a system call? */
|
||||
if (__frame->syscallno >= 0) {
|
||||
/* Restart the system call - no handlers present */
|
||||
if (__frame->gr8 == -ERESTARTNOHAND ||
|
||||
__frame->gr8 == -ERESTARTSYS ||
|
||||
__frame->gr8 == -ERESTARTNOINTR) {
|
||||
switch (__frame->gr8) {
|
||||
case -ERESTARTNOHAND:
|
||||
case -ERESTARTSYS:
|
||||
case -ERESTARTNOINTR:
|
||||
__frame->gr8 = __frame->orig_gr8;
|
||||
__frame->pc -= 4;
|
||||
}
|
||||
break;
|
||||
|
||||
if (__frame->gr8 == -ERESTART_RESTARTBLOCK){
|
||||
case -ERESTART_RESTARTBLOCK:
|
||||
__frame->gr8 = __NR_restart_syscall;
|
||||
__frame->pc -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* if there's no signal to deliver, we just put the saved sigmask
|
||||
* back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
|
||||
} /* end do_signal() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* notification of userspace execution resumption
|
||||
* - triggered by current->work.notify_resume
|
||||
* - triggered by the TIF_WORK_MASK flags
|
||||
*/
|
||||
asmlinkage void do_notify_resume(__u32 thread_info_flags)
|
||||
{
|
||||
@ -594,7 +562,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags)
|
||||
clear_thread_flag(TIF_SINGLESTEP);
|
||||
|
||||
/* deal with pending signal delivery */
|
||||
if (thread_info_flags & _TIF_SIGPENDING)
|
||||
do_signal(NULL);
|
||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
||||
do_signal();
|
||||
|
||||
} /* end do_notify_resume() */
|
||||
|
@ -25,8 +25,7 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
|
||||
|
||||
/* enable access to config space*/
|
||||
pci_read_config_byte(dev, 0xf4, &config);
|
||||
config |= 0x2;
|
||||
pci_write_config_byte(dev, 0xf4, config);
|
||||
pci_write_config_byte(dev, 0xf4, config|0x2);
|
||||
|
||||
/* read xTPR register */
|
||||
raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
|
||||
@ -42,9 +41,9 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
|
||||
#endif
|
||||
}
|
||||
|
||||
config &= ~0x2;
|
||||
/* disable access to config space*/
|
||||
pci_write_config_byte(dev, 0xf4, config);
|
||||
/* put back the original value for config space*/
|
||||
if (!(config & 0x2))
|
||||
pci_write_config_byte(dev, 0xf4, config);
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance);
|
||||
|
@ -37,51 +37,17 @@
|
||||
asmlinkage int
|
||||
sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||
{
|
||||
struct pt_regs * regs = (struct pt_regs *) &history0;
|
||||
sigset_t saveset;
|
||||
|
||||
mask &= _BLOCKABLE;
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->saved_sigmask = current->blocked;
|
||||
siginitset(¤t->blocked, mask);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
regs->eax = -EINTR;
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(regs, &saveset))
|
||||
return -EINTR;
|
||||
}
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
sys_rt_sigsuspend(struct pt_regs regs)
|
||||
{
|
||||
sigset_t saveset, newset;
|
||||
|
||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||
if (regs.ecx != sizeof(sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&newset, (sigset_t __user *)regs.ebx, sizeof(newset)))
|
||||
return -EFAULT;
|
||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->blocked = newset;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
regs.eax = -EINTR;
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(®s, &saveset))
|
||||
return -EINTR;
|
||||
}
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
@ -433,11 +399,11 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
current->comm, current->pid, frame, regs->eip, frame->pretcode);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return 0;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
@ -527,11 +493,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
current->comm, current->pid, frame, regs->eip, frame->pretcode);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return 0;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -581,7 +547,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
if (ret) {
|
||||
if (ret == 0) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
@ -598,11 +564,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
||||
* mistake.
|
||||
*/
|
||||
int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||
static void fastcall do_signal(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* We want the common case to go fast, which
|
||||
@ -613,12 +580,14 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||
* CS suffices.
|
||||
*/
|
||||
if (!user_mode(regs))
|
||||
return 1;
|
||||
return;
|
||||
|
||||
if (try_to_freeze())
|
||||
goto no_signal;
|
||||
|
||||
if (!oldset)
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
@ -628,38 +597,55 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||
* have been cleared if the watchpoint triggered
|
||||
* inside the kernel.
|
||||
*/
|
||||
if (unlikely(current->thread.debugreg[7])) {
|
||||
if (unlikely(current->thread.debugreg[7]))
|
||||
set_debugreg(current->thread.debugreg[7], 7);
|
||||
}
|
||||
|
||||
/* Whee! Actually deliver the signal. */
|
||||
return handle_signal(signr, &info, &ka, oldset, regs);
|
||||
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
|
||||
/* a signal was successfully delivered; the saved
|
||||
* sigmask will have been stored in the signal frame,
|
||||
* and will be restored by sigreturn, so we can simply
|
||||
* clear the TIF_RESTORE_SIGMASK flag */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
no_signal:
|
||||
no_signal:
|
||||
/* Did we come from a system call? */
|
||||
if (regs->orig_eax >= 0) {
|
||||
/* Restart the system call - no handlers present */
|
||||
if (regs->eax == -ERESTARTNOHAND ||
|
||||
regs->eax == -ERESTARTSYS ||
|
||||
regs->eax == -ERESTARTNOINTR) {
|
||||
switch (regs->eax) {
|
||||
case -ERESTARTNOHAND:
|
||||
case -ERESTARTSYS:
|
||||
case -ERESTARTNOINTR:
|
||||
regs->eax = regs->orig_eax;
|
||||
regs->eip -= 2;
|
||||
}
|
||||
if (regs->eax == -ERESTART_RESTARTBLOCK){
|
||||
break;
|
||||
|
||||
case -ERESTART_RESTARTBLOCK:
|
||||
regs->eax = __NR_restart_syscall;
|
||||
regs->eip -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* if there's no signal to deliver, we just put the saved sigmask
|
||||
* back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* notification of userspace execution resumption
|
||||
* - triggered by current->work.notify_resume
|
||||
* - triggered by the TIF_WORK_MASK flags
|
||||
*/
|
||||
__attribute__((regparm(3)))
|
||||
void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
|
||||
void do_notify_resume(struct pt_regs *regs, void *_unused,
|
||||
__u32 thread_info_flags)
|
||||
{
|
||||
/* Pending single-step? */
|
||||
@ -667,9 +653,10 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
|
||||
regs->eflags |= TF_MASK;
|
||||
clear_thread_flag(TIF_SINGLESTEP);
|
||||
}
|
||||
|
||||
/* deal with pending signal delivery */
|
||||
if (thread_info_flags & _TIF_SIGPENDING)
|
||||
do_signal(regs,oldset);
|
||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
||||
do_signal(regs);
|
||||
|
||||
clear_thread_flag(TIF_IRET);
|
||||
}
|
||||
|
@ -294,3 +294,18 @@ ENTRY(sys_call_table)
|
||||
.long sys_inotify_add_watch
|
||||
.long sys_inotify_rm_watch
|
||||
.long sys_migrate_pages
|
||||
.long sys_openat /* 295 */
|
||||
.long sys_mkdirat
|
||||
.long sys_mknodat
|
||||
.long sys_fchownat
|
||||
.long sys_futimesat
|
||||
.long sys_newfstatat /* 300 */
|
||||
.long sys_unlinkat
|
||||
.long sys_renameat
|
||||
.long sys_linkat
|
||||
.long sys_symlinkat
|
||||
.long sys_readlinkat /* 305 */
|
||||
.long sys_fchmodat
|
||||
.long sys_faccessat
|
||||
.long sys_pselect6
|
||||
.long sys_ppoll
|
||||
|
@ -52,9 +52,9 @@
|
||||
#include <linux/compat.h>
|
||||
#include <linux/vfs.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/intrinsics.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/unistd.h>
|
||||
@ -86,7 +86,7 @@
|
||||
* while doing so.
|
||||
*/
|
||||
/* XXX make per-mm: */
|
||||
static DECLARE_MUTEX(ia32_mmap_sem);
|
||||
static DEFINE_MUTEX(ia32_mmap_mutex);
|
||||
|
||||
asmlinkage long
|
||||
sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp,
|
||||
@ -895,11 +895,11 @@ ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot
|
||||
prot = get_prot32(prot);
|
||||
|
||||
#if PAGE_SHIFT > IA32_PAGE_SHIFT
|
||||
down(&ia32_mmap_sem);
|
||||
mutex_lock(&ia32_mmap_mutex);
|
||||
{
|
||||
addr = emulate_mmap(file, addr, len, prot, flags, offset);
|
||||
}
|
||||
up(&ia32_mmap_sem);
|
||||
mutex_unlock(&ia32_mmap_mutex);
|
||||
#else
|
||||
down_write(¤t->mm->mmap_sem);
|
||||
{
|
||||
@ -1000,11 +1000,9 @@ sys32_munmap (unsigned int start, unsigned int len)
|
||||
if (start >= end)
|
||||
return 0;
|
||||
|
||||
down(&ia32_mmap_sem);
|
||||
{
|
||||
ret = sys_munmap(start, end - start);
|
||||
}
|
||||
up(&ia32_mmap_sem);
|
||||
mutex_lock(&ia32_mmap_mutex);
|
||||
ret = sys_munmap(start, end - start);
|
||||
mutex_unlock(&ia32_mmap_mutex);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
@ -1056,7 +1054,7 @@ sys32_mprotect (unsigned int start, unsigned int len, int prot)
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
down(&ia32_mmap_sem);
|
||||
mutex_lock(&ia32_mmap_mutex);
|
||||
{
|
||||
if (offset_in_page(start)) {
|
||||
/* start address is 4KB aligned but not page aligned. */
|
||||
@ -1080,7 +1078,7 @@ sys32_mprotect (unsigned int start, unsigned int len, int prot)
|
||||
retval = sys_mprotect(start, end - start, prot);
|
||||
}
|
||||
out:
|
||||
up(&ia32_mmap_sem);
|
||||
mutex_unlock(&ia32_mmap_mutex);
|
||||
return retval;
|
||||
#endif
|
||||
}
|
||||
@ -1124,11 +1122,9 @@ sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len,
|
||||
old_len = PAGE_ALIGN(old_end) - addr;
|
||||
new_len = PAGE_ALIGN(new_end) - addr;
|
||||
|
||||
down(&ia32_mmap_sem);
|
||||
{
|
||||
ret = sys_mremap(addr, old_len, new_len, flags, new_addr);
|
||||
}
|
||||
up(&ia32_mmap_sem);
|
||||
mutex_lock(&ia32_mmap_mutex);
|
||||
ret = sys_mremap(addr, old_len, new_len, flags, new_addr);
|
||||
mutex_unlock(&ia32_mmap_mutex);
|
||||
|
||||
if ((ret >= 0) && (old_len < new_len)) {
|
||||
/* mremap expanded successfully */
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include <asm/errno.h>
|
||||
#include <asm/intrinsics.h>
|
||||
@ -286,7 +287,7 @@ typedef struct pfm_context {
|
||||
|
||||
unsigned long ctx_ovfl_regs[4]; /* which registers overflowed (notification) */
|
||||
|
||||
struct semaphore ctx_restart_sem; /* use for blocking notification mode */
|
||||
struct completion ctx_restart_done; /* use for blocking notification mode */
|
||||
|
||||
unsigned long ctx_used_pmds[4]; /* bitmask of PMD used */
|
||||
unsigned long ctx_all_pmds[4]; /* bitmask of all accessible PMDs */
|
||||
@ -1991,7 +1992,7 @@ pfm_close(struct inode *inode, struct file *filp)
|
||||
/*
|
||||
* force task to wake up from MASKED state
|
||||
*/
|
||||
up(&ctx->ctx_restart_sem);
|
||||
complete(&ctx->ctx_restart_done);
|
||||
|
||||
DPRINT(("waking up ctx_state=%d\n", state));
|
||||
|
||||
@ -2706,7 +2707,7 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
|
||||
/*
|
||||
* init restart semaphore to locked
|
||||
*/
|
||||
sema_init(&ctx->ctx_restart_sem, 0);
|
||||
init_completion(&ctx->ctx_restart_done);
|
||||
|
||||
/*
|
||||
* activation is used in SMP only
|
||||
@ -3687,7 +3688,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
|
||||
*/
|
||||
if (CTX_OVFL_NOBLOCK(ctx) == 0 && state == PFM_CTX_MASKED) {
|
||||
DPRINT(("unblocking [%d] \n", task->pid));
|
||||
up(&ctx->ctx_restart_sem);
|
||||
complete(&ctx->ctx_restart_done);
|
||||
} else {
|
||||
DPRINT(("[%d] armed exit trap\n", task->pid));
|
||||
|
||||
@ -5089,7 +5090,7 @@ pfm_handle_work(void)
|
||||
* may go through without blocking on SMP systems
|
||||
* if restart has been received already by the time we call down()
|
||||
*/
|
||||
ret = down_interruptible(&ctx->ctx_restart_sem);
|
||||
ret = wait_for_completion_interruptible(&ctx->ctx_restart_done);
|
||||
|
||||
DPRINT(("after block sleeping ret=%d\n", ret));
|
||||
|
||||
|
@ -210,6 +210,7 @@ uncached_build_memmap(unsigned long start, unsigned long end, void *arg)
|
||||
|
||||
dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
|
||||
|
||||
touch_softlockup_watchdog();
|
||||
memset((char *)start, 0, length);
|
||||
|
||||
node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET);
|
||||
|
@ -51,6 +51,15 @@ struct sn_flush_device_kernel {
|
||||
struct sn_flush_device_common *common;
|
||||
};
|
||||
|
||||
/* 01/16/06 This struct is the old PROM/kernel struct and needs to be included
|
||||
* for older official PROMs to function on the new kernel base. This struct
|
||||
* will be removed when the next official PROM release occurs. */
|
||||
|
||||
struct sn_flush_device_war {
|
||||
struct sn_flush_device_common common;
|
||||
u32 filler; /* older PROMs expect the default size of a spinlock_t */
|
||||
};
|
||||
|
||||
/*
|
||||
* **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel.
|
||||
*/
|
||||
|
@ -165,8 +165,45 @@ sn_pcidev_info_get(struct pci_dev *dev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Older PROM flush WAR
|
||||
*
|
||||
* 01/16/06 -- This war will be in place until a new official PROM is released.
|
||||
* Additionally note that the struct sn_flush_device_war also has to be
|
||||
* removed from arch/ia64/sn/include/xtalk/hubdev.h
|
||||
*/
|
||||
static u8 war_implemented = 0;
|
||||
|
||||
static void sn_device_fixup_war(u64 nasid, u64 widget, int device,
|
||||
struct sn_flush_device_common *common)
|
||||
{
|
||||
struct sn_flush_device_war *war_list;
|
||||
struct sn_flush_device_war *dev_entry;
|
||||
struct ia64_sal_retval isrv = {0,0,0,0};
|
||||
|
||||
if (!war_implemented) {
|
||||
printk(KERN_WARNING "PROM version < 4.50 -- implementing old "
|
||||
"PROM flush WAR\n");
|
||||
war_implemented = 1;
|
||||
}
|
||||
|
||||
war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
|
||||
if (!war_list)
|
||||
BUG();
|
||||
|
||||
SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
|
||||
nasid, widget, __pa(war_list), 0, 0, 0 ,0);
|
||||
if (isrv.status)
|
||||
panic("sn_device_fixup_war failed: %s\n",
|
||||
ia64_sal_strerror(isrv.status));
|
||||
|
||||
dev_entry = war_list + device;
|
||||
memcpy(common,dev_entry, sizeof(*common));
|
||||
|
||||
kfree(war_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* sn_fixup_ionodes() - This routine initializes the HUB data strcuture for
|
||||
* sn_fixup_ionodes() - This routine initializes the HUB data strcuture for
|
||||
* each node in the system.
|
||||
*/
|
||||
static void sn_fixup_ionodes(void)
|
||||
@ -246,8 +283,19 @@ static void sn_fixup_ionodes(void)
|
||||
widget,
|
||||
device,
|
||||
(u64)(dev_entry->common));
|
||||
if (status)
|
||||
BUG();
|
||||
if (status) {
|
||||
if (sn_sal_rev() < 0x0450) {
|
||||
/* shortlived WAR for older
|
||||
* PROM images
|
||||
*/
|
||||
sn_device_fixup_war(nasid,
|
||||
widget,
|
||||
device,
|
||||
dev_entry->common);
|
||||
}
|
||||
else
|
||||
BUG();
|
||||
}
|
||||
|
||||
spin_lock_init(&dev_entry->sfdl_flush_lock);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/mca.h>
|
||||
#include <asm/sal.h>
|
||||
#include <asm/sn/sn_sal.h>
|
||||
@ -27,7 +28,7 @@ void sn_init_cpei_timer(void);
|
||||
/* Printing oemdata from mca uses data that is not passed through SAL, it is
|
||||
* global. Only one user at a time.
|
||||
*/
|
||||
static DECLARE_MUTEX(sn_oemdata_mutex);
|
||||
static DEFINE_MUTEX(sn_oemdata_mutex);
|
||||
static u8 **sn_oemdata;
|
||||
static u64 *sn_oemdata_size, sn_oemdata_bufsize;
|
||||
|
||||
@ -89,7 +90,7 @@ static int
|
||||
sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata,
|
||||
u64 * oemdata_size)
|
||||
{
|
||||
down(&sn_oemdata_mutex);
|
||||
mutex_lock(&sn_oemdata_mutex);
|
||||
sn_oemdata = oemdata;
|
||||
sn_oemdata_size = oemdata_size;
|
||||
sn_oemdata_bufsize = 0;
|
||||
@ -107,7 +108,7 @@ sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata,
|
||||
*sn_oemdata_size = 0;
|
||||
ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
|
||||
}
|
||||
up(&sn_oemdata_mutex);
|
||||
mutex_unlock(&sn_oemdata_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/sn/intr.h>
|
||||
#include <asm/sn/sn_sal.h>
|
||||
#include <asm/sn/xp.h>
|
||||
@ -136,13 +137,13 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
|
||||
|
||||
registration = &xpc_registrations[ch_number];
|
||||
|
||||
if (down_interruptible(®istration->sema) != 0) {
|
||||
if (mutex_lock_interruptible(®istration->mutex) != 0) {
|
||||
return xpcInterrupted;
|
||||
}
|
||||
|
||||
/* if XPC_CHANNEL_REGISTERED(ch_number) */
|
||||
if (registration->func != NULL) {
|
||||
up(®istration->sema);
|
||||
mutex_unlock(®istration->mutex);
|
||||
return xpcAlreadyRegistered;
|
||||
}
|
||||
|
||||
@ -154,7 +155,7 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
|
||||
registration->key = key;
|
||||
registration->func = func;
|
||||
|
||||
up(®istration->sema);
|
||||
mutex_unlock(®istration->mutex);
|
||||
|
||||
xpc_interface.connect(ch_number);
|
||||
|
||||
@ -190,11 +191,11 @@ xpc_disconnect(int ch_number)
|
||||
* figured XPC's users will just turn around and call xpc_disconnect()
|
||||
* again anyways, so we might as well wait, if need be.
|
||||
*/
|
||||
down(®istration->sema);
|
||||
mutex_lock(®istration->mutex);
|
||||
|
||||
/* if !XPC_CHANNEL_REGISTERED(ch_number) */
|
||||
if (registration->func == NULL) {
|
||||
up(®istration->sema);
|
||||
mutex_unlock(®istration->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -208,7 +209,7 @@ xpc_disconnect(int ch_number)
|
||||
|
||||
xpc_interface.disconnect(ch_number);
|
||||
|
||||
up(®istration->sema);
|
||||
mutex_unlock(®istration->mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -250,9 +251,9 @@ xp_init(void)
|
||||
xp_nofault_PIOR_target = SH1_IPI_ACCESS;
|
||||
}
|
||||
|
||||
/* initialize the connection registration semaphores */
|
||||
/* initialize the connection registration mutex */
|
||||
for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
|
||||
sema_init(&xpc_registrations[ch_number].sema, 1); /* mutex */
|
||||
mutex_init(&xpc_registrations[ch_number].mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <linux/cache.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/completion.h>
|
||||
#include <asm/sn/bte.h>
|
||||
#include <asm/sn/sn_sal.h>
|
||||
#include <asm/sn/xpc.h>
|
||||
@ -56,8 +58,8 @@ xpc_initialize_channels(struct xpc_partition *part, partid_t partid)
|
||||
atomic_set(&ch->n_to_notify, 0);
|
||||
|
||||
spin_lock_init(&ch->lock);
|
||||
sema_init(&ch->msg_to_pull_sema, 1); /* mutex */
|
||||
sema_init(&ch->wdisconnect_sema, 0); /* event wait */
|
||||
mutex_init(&ch->msg_to_pull_mutex);
|
||||
init_completion(&ch->wdisconnect_wait);
|
||||
|
||||
atomic_set(&ch->n_on_msg_allocate_wq, 0);
|
||||
init_waitqueue_head(&ch->msg_allocate_wq);
|
||||
@ -534,7 +536,6 @@ static enum xpc_retval
|
||||
xpc_allocate_msgqueues(struct xpc_channel *ch)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
int i;
|
||||
enum xpc_retval ret;
|
||||
|
||||
|
||||
@ -552,11 +553,6 @@ xpc_allocate_msgqueues(struct xpc_channel *ch)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ch->local_nentries; i++) {
|
||||
/* use a semaphore as an event wait queue */
|
||||
sema_init(&ch->notify_queue[i].sema, 0);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ch->lock, irq_flags);
|
||||
ch->flags |= XPC_C_SETUP;
|
||||
spin_unlock_irqrestore(&ch->lock, irq_flags);
|
||||
@ -799,10 +795,8 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
|
||||
}
|
||||
|
||||
if (ch->flags & XPC_C_WDISCONNECT) {
|
||||
spin_unlock_irqrestore(&ch->lock, *irq_flags);
|
||||
up(&ch->wdisconnect_sema);
|
||||
spin_lock_irqsave(&ch->lock, *irq_flags);
|
||||
|
||||
/* we won't lose the CPU since we're holding ch->lock */
|
||||
complete(&ch->wdisconnect_wait);
|
||||
} else if (ch->delayed_IPI_flags) {
|
||||
if (part->act_state != XPC_P_DEACTIVATING) {
|
||||
/* time to take action on any delayed IPI flags */
|
||||
@ -1092,12 +1086,12 @@ xpc_connect_channel(struct xpc_channel *ch)
|
||||
struct xpc_registration *registration = &xpc_registrations[ch->number];
|
||||
|
||||
|
||||
if (down_trylock(®istration->sema) != 0) {
|
||||
if (mutex_trylock(®istration->mutex) == 0) {
|
||||
return xpcRetry;
|
||||
}
|
||||
|
||||
if (!XPC_CHANNEL_REGISTERED(ch->number)) {
|
||||
up(®istration->sema);
|
||||
mutex_unlock(®istration->mutex);
|
||||
return xpcUnregistered;
|
||||
}
|
||||
|
||||
@ -1108,7 +1102,7 @@ xpc_connect_channel(struct xpc_channel *ch)
|
||||
|
||||
if (ch->flags & XPC_C_DISCONNECTING) {
|
||||
spin_unlock_irqrestore(&ch->lock, irq_flags);
|
||||
up(®istration->sema);
|
||||
mutex_unlock(®istration->mutex);
|
||||
return ch->reason;
|
||||
}
|
||||
|
||||
@ -1140,7 +1134,7 @@ xpc_connect_channel(struct xpc_channel *ch)
|
||||
* channel lock be locked and will unlock and relock
|
||||
* the channel lock as needed.
|
||||
*/
|
||||
up(®istration->sema);
|
||||
mutex_unlock(®istration->mutex);
|
||||
XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
|
||||
&irq_flags);
|
||||
spin_unlock_irqrestore(&ch->lock, irq_flags);
|
||||
@ -1155,7 +1149,7 @@ xpc_connect_channel(struct xpc_channel *ch)
|
||||
atomic_inc(&xpc_partitions[ch->partid].nchannels_active);
|
||||
}
|
||||
|
||||
up(®istration->sema);
|
||||
mutex_unlock(®istration->mutex);
|
||||
|
||||
|
||||
/* initiate the connection */
|
||||
@ -2089,7 +2083,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
|
||||
enum xpc_retval ret;
|
||||
|
||||
|
||||
if (down_interruptible(&ch->msg_to_pull_sema) != 0) {
|
||||
if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) {
|
||||
/* we were interrupted by a signal */
|
||||
return NULL;
|
||||
}
|
||||
@ -2125,7 +2119,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
|
||||
|
||||
XPC_DEACTIVATE_PARTITION(part, ret);
|
||||
|
||||
up(&ch->msg_to_pull_sema);
|
||||
mutex_unlock(&ch->msg_to_pull_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -2134,7 +2128,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
|
||||
ch->next_msg_to_pull += nmsgs;
|
||||
}
|
||||
|
||||
up(&ch->msg_to_pull_sema);
|
||||
mutex_unlock(&ch->msg_to_pull_mutex);
|
||||
|
||||
/* return the message we were looking for */
|
||||
msg_offset = (get % ch->remote_nentries) * ch->msg_size;
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/completion.h>
|
||||
#include <asm/sn/intr.h>
|
||||
#include <asm/sn/sn_sal.h>
|
||||
#include <asm/kdebug.h>
|
||||
@ -177,10 +178,10 @@ static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq);
|
||||
static unsigned long xpc_hb_check_timeout;
|
||||
|
||||
/* notification that the xpc_hb_checker thread has exited */
|
||||
static DECLARE_MUTEX_LOCKED(xpc_hb_checker_exited);
|
||||
static DECLARE_COMPLETION(xpc_hb_checker_exited);
|
||||
|
||||
/* notification that the xpc_discovery thread has exited */
|
||||
static DECLARE_MUTEX_LOCKED(xpc_discovery_exited);
|
||||
static DECLARE_COMPLETION(xpc_discovery_exited);
|
||||
|
||||
|
||||
static struct timer_list xpc_hb_timer;
|
||||
@ -321,7 +322,7 @@ xpc_hb_checker(void *ignore)
|
||||
|
||||
|
||||
/* mark this thread as having exited */
|
||||
up(&xpc_hb_checker_exited);
|
||||
complete(&xpc_hb_checker_exited);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -341,7 +342,7 @@ xpc_initiate_discovery(void *ignore)
|
||||
dev_dbg(xpc_part, "discovery thread is exiting\n");
|
||||
|
||||
/* mark this thread as having exited */
|
||||
up(&xpc_discovery_exited);
|
||||
complete(&xpc_discovery_exited);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -893,7 +894,7 @@ xpc_disconnect_wait(int ch_number)
|
||||
continue;
|
||||
}
|
||||
|
||||
(void) down(&ch->wdisconnect_sema);
|
||||
wait_for_completion(&ch->wdisconnect_wait);
|
||||
|
||||
spin_lock_irqsave(&ch->lock, irq_flags);
|
||||
DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
|
||||
@ -946,10 +947,10 @@ xpc_do_exit(enum xpc_retval reason)
|
||||
free_irq(SGI_XPC_ACTIVATE, NULL);
|
||||
|
||||
/* wait for the discovery thread to exit */
|
||||
down(&xpc_discovery_exited);
|
||||
wait_for_completion(&xpc_discovery_exited);
|
||||
|
||||
/* wait for the heartbeat checker thread to exit */
|
||||
down(&xpc_hb_checker_exited);
|
||||
wait_for_completion(&xpc_hb_checker_exited);
|
||||
|
||||
|
||||
/* sleep for a 1/3 of a second or so */
|
||||
@ -1367,7 +1368,7 @@ xpc_init(void)
|
||||
dev_err(xpc_part, "failed while forking discovery thread\n");
|
||||
|
||||
/* mark this new thread as a non-starter */
|
||||
up(&xpc_discovery_exited);
|
||||
complete(&xpc_discovery_exited);
|
||||
|
||||
xpc_do_exit(xpcUnloading);
|
||||
return -EBUSY;
|
||||
|
@ -24,13 +24,15 @@ sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp)
|
||||
{
|
||||
struct ia64_sal_retval ret_stuff;
|
||||
u64 busnum;
|
||||
u64 segment;
|
||||
|
||||
ret_stuff.status = 0;
|
||||
ret_stuff.v0 = 0;
|
||||
|
||||
segment = soft->pbi_buscommon.bs_persist_segment;
|
||||
busnum = soft->pbi_buscommon.bs_persist_busnum;
|
||||
SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, (u64) busnum,
|
||||
(u64) device, (u64) resp, 0, 0, 0, 0);
|
||||
SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment,
|
||||
busnum, (u64) device, (u64) resp, 0, 0, 0);
|
||||
|
||||
return (int)ret_stuff.v0;
|
||||
}
|
||||
@ -41,14 +43,16 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action,
|
||||
{
|
||||
struct ia64_sal_retval ret_stuff;
|
||||
u64 busnum;
|
||||
u64 segment;
|
||||
|
||||
ret_stuff.status = 0;
|
||||
ret_stuff.v0 = 0;
|
||||
|
||||
segment = soft->pbi_buscommon.bs_persist_segment;
|
||||
busnum = soft->pbi_buscommon.bs_persist_busnum;
|
||||
SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_DISABLE,
|
||||
(u64) busnum, (u64) device, (u64) action,
|
||||
(u64) resp, 0, 0, 0);
|
||||
segment, busnum, (u64) device, (u64) action,
|
||||
(u64) resp, 0, 0);
|
||||
|
||||
return (int)ret_stuff.v0;
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ ret_from_syscall:
|
||||
MTMSRD(r10)
|
||||
lwz r9,TI_FLAGS(r12)
|
||||
li r8,-_LAST_ERRNO
|
||||
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
|
||||
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK)
|
||||
bne- syscall_exit_work
|
||||
cmplw 0,r3,r8
|
||||
blt+ syscall_exit_cont
|
||||
@ -357,7 +357,7 @@ save_user_nvgprs_cont:
|
||||
lwz r5,_MSR(r1)
|
||||
andi. r5,r5,MSR_PR
|
||||
beq ret_from_except
|
||||
andi. r0,r9,_TIF_SIGPENDING
|
||||
andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
|
||||
beq ret_from_except
|
||||
b do_user_signal
|
||||
8:
|
||||
@ -683,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */
|
||||
/* Check current_thread_info()->flags */
|
||||
rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
|
||||
lwz r9,TI_FLAGS(r9)
|
||||
andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
|
||||
andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK)
|
||||
bne do_work
|
||||
|
||||
restore_user:
|
||||
@ -917,7 +917,7 @@ recheck:
|
||||
lwz r9,TI_FLAGS(r9)
|
||||
andi. r0,r9,_TIF_NEED_RESCHED
|
||||
bne- do_resched
|
||||
andi. r0,r9,_TIF_SIGPENDING
|
||||
andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
|
||||
beq restore_user
|
||||
do_user_signal: /* r10 contains MSR_KERNEL here */
|
||||
ori r10,r10,MSR_EE
|
||||
|
@ -160,7 +160,7 @@ syscall_exit:
|
||||
mtmsrd r10,1
|
||||
ld r9,TI_FLAGS(r12)
|
||||
li r11,-_LAST_ERRNO
|
||||
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR)
|
||||
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR|_TIF_RESTORE_SIGMASK)
|
||||
bne- syscall_exit_work
|
||||
cmpld r3,r11
|
||||
ld r5,_CCR(r1)
|
||||
|
@ -252,8 +252,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs);
|
||||
/*
|
||||
* Atomically swap in the new signal mask, and wait for a signal.
|
||||
*/
|
||||
long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
|
||||
struct pt_regs *regs)
|
||||
long sys_sigsuspend(old_sigset_t mask)
|
||||
{
|
||||
sigset_t saveset;
|
||||
|
||||
@ -264,55 +263,10 @@ long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
regs->result = -EINTR;
|
||||
regs->gpr[3] = EINTR;
|
||||
regs->ccr |= 0x10000000;
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(&saveset, regs)) {
|
||||
set_thread_flag(TIF_RESTOREALL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long sys_rt_sigsuspend(
|
||||
#ifdef CONFIG_PPC64
|
||||
compat_sigset_t __user *unewset,
|
||||
#else
|
||||
sigset_t __user *unewset,
|
||||
#endif
|
||||
size_t sigsetsize, int p3, int p4,
|
||||
int p6, int p7, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t saveset, newset;
|
||||
|
||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
if (get_sigset_t(&newset, unewset))
|
||||
return -EFAULT;
|
||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->blocked = newset;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
regs->result = -EINTR;
|
||||
regs->gpr[3] = EINTR;
|
||||
regs->ccr |= 0x10000000;
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(&saveset, regs)) {
|
||||
set_thread_flag(TIF_RESTOREALL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
@ -1174,7 +1128,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
struct k_sigaction ka;
|
||||
unsigned int frame, newsp;
|
||||
unsigned int newsp;
|
||||
int signr, ret;
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
@ -1185,11 +1139,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!oldset)
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else if (!oldset)
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
newsp = frame = 0;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
#ifdef CONFIG_PPC32
|
||||
no_signal:
|
||||
@ -1219,8 +1173,14 @@ no_signal:
|
||||
}
|
||||
}
|
||||
|
||||
if (signr == 0)
|
||||
if (signr == 0) {
|
||||
/* No signal to deliver -- put the saved sigmask back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
return 0; /* no signals delivered */
|
||||
}
|
||||
|
||||
if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
|
||||
&& !on_sig_stack(regs->gpr[1]))
|
||||
@ -1253,6 +1213,10 @@ no_signal:
|
||||
sigaddset(¤t->blocked, signr);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
/* A signal was successfully delivered; the saved sigmask is in
|
||||
its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -67,42 +67,6 @@ struct rt_sigframe {
|
||||
char abigap[288];
|
||||
} __attribute__ ((aligned (16)));
|
||||
|
||||
|
||||
/*
|
||||
* Atomically swap in the new signal mask, and wait for a signal.
|
||||
*/
|
||||
long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4,
|
||||
int p6, int p7, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t saveset, newset;
|
||||
|
||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
||||
return -EFAULT;
|
||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->blocked = newset;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
regs->result = -EINTR;
|
||||
regs->gpr[3] = EINTR;
|
||||
regs->ccr |= 0x10000000;
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(&saveset, regs)) {
|
||||
set_thread_flag(TIF_RESTOREALL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
|
||||
unsigned long r6, unsigned long r7, unsigned long r8,
|
||||
struct pt_regs *regs)
|
||||
@ -556,11 +520,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
||||
if (test_thread_flag(TIF_32BIT))
|
||||
return do_signal32(oldset, regs);
|
||||
|
||||
if (!oldset)
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else if (!oldset)
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
int ret;
|
||||
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (TRAP(regs) == 0x0C00)
|
||||
syscall_restart(regs, &ka);
|
||||
@ -573,7 +541,14 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
||||
if (current->thread.dabr)
|
||||
set_dabr(current->thread.dabr);
|
||||
|
||||
return handle_signal(signr, &ka, &info, oldset, regs);
|
||||
ret = handle_signal(signr, &ka, &info, oldset, regs);
|
||||
|
||||
/* If a signal was successfully delivered, the saved sigmask is in
|
||||
its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
|
||||
if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (TRAP(regs) == 0x0C00) { /* System Call! */
|
||||
@ -589,6 +564,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
||||
regs->result = 0;
|
||||
}
|
||||
}
|
||||
/* No signal to deliver -- put the saved sigmask back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -321,3 +321,5 @@ SYSCALL(inotify_add_watch)
|
||||
SYSCALL(inotify_rm_watch)
|
||||
SYSCALL(spu_run)
|
||||
SYSCALL(spu_create)
|
||||
COMPAT_SYS(pselect6)
|
||||
COMPAT_SYS(ppoll)
|
||||
|
@ -1276,62 +1276,6 @@ sys_sigstack:
|
||||
call do_sys_sigstack
|
||||
mov %l5, %o7
|
||||
|
||||
.align 4
|
||||
.globl sys_sigpause
|
||||
sys_sigpause:
|
||||
/* Note: %o0 already has correct value... */
|
||||
call do_sigpause
|
||||
add %sp, STACKFRAME_SZ, %o1
|
||||
|
||||
ld [%curptr + TI_FLAGS], %l5
|
||||
andcc %l5, _TIF_SYSCALL_TRACE, %g0
|
||||
be 1f
|
||||
nop
|
||||
|
||||
call syscall_trace
|
||||
nop
|
||||
|
||||
1:
|
||||
/* We are returning to a signal handler. */
|
||||
RESTORE_ALL
|
||||
|
||||
.align 4
|
||||
.globl sys_sigsuspend
|
||||
sys_sigsuspend:
|
||||
call do_sigsuspend
|
||||
add %sp, STACKFRAME_SZ, %o0
|
||||
|
||||
ld [%curptr + TI_FLAGS], %l5
|
||||
andcc %l5, _TIF_SYSCALL_TRACE, %g0
|
||||
be 1f
|
||||
nop
|
||||
|
||||
call syscall_trace
|
||||
nop
|
||||
|
||||
1:
|
||||
/* We are returning to a signal handler. */
|
||||
RESTORE_ALL
|
||||
|
||||
.align 4
|
||||
.globl sys_rt_sigsuspend
|
||||
sys_rt_sigsuspend:
|
||||
/* Note: %o0, %o1 already have correct value... */
|
||||
call do_rt_sigsuspend
|
||||
add %sp, STACKFRAME_SZ, %o2
|
||||
|
||||
ld [%curptr + TI_FLAGS], %l5
|
||||
andcc %l5, _TIF_SYSCALL_TRACE, %g0
|
||||
be 1f
|
||||
nop
|
||||
|
||||
call syscall_trace
|
||||
nop
|
||||
|
||||
1:
|
||||
/* We are returning to a signal handler. */
|
||||
RESTORE_ALL
|
||||
|
||||
.align 4
|
||||
.globl sys_sigreturn
|
||||
sys_sigreturn:
|
||||
|
@ -68,15 +68,14 @@ ret_trap_lockless_ipi:
|
||||
|
||||
ld [%curptr + TI_FLAGS], %g2
|
||||
signal_p:
|
||||
andcc %g2, (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING), %g0
|
||||
andcc %g2, (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %g0
|
||||
bz,a ret_trap_continue
|
||||
ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
|
||||
|
||||
clr %o0
|
||||
mov %l5, %o2
|
||||
mov %l6, %o3
|
||||
mov %l5, %o1
|
||||
mov %l6, %o2
|
||||
call do_signal
|
||||
add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr
|
||||
add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr
|
||||
|
||||
/* Fall through. */
|
||||
ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
|
||||
|
@ -35,9 +35,6 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
|
||||
void *fpqueue, unsigned long *fpqdepth);
|
||||
extern void fpload(unsigned long *fpregs, unsigned long *fsr);
|
||||
|
||||
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
|
||||
unsigned long orig_o0, int restart_syscall);
|
||||
|
||||
/* Signal frames: the original one (compatible with SunOS):
|
||||
*
|
||||
* Set up a signal frame... Make the stack look the way SunOS
|
||||
@ -95,98 +92,30 @@ struct rt_signal_frame {
|
||||
#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7)))
|
||||
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
|
||||
|
||||
/*
|
||||
* atomically swap in the new signal mask, and wait for a signal.
|
||||
* This is really tricky on the Sparc, watch out...
|
||||
*/
|
||||
asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs)
|
||||
static int _sigpause_common(old_sigset_t set)
|
||||
{
|
||||
sigset_t saveset;
|
||||
|
||||
set &= _BLOCKABLE;
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->saved_sigmask = current->blocked;
|
||||
siginitset(¤t->blocked, set);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
regs->pc = regs->npc;
|
||||
regs->npc += 4;
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
|
||||
/* Condition codes and return value where set here for sigpause,
|
||||
* and so got used by setup_frame, which again causes sigreturn()
|
||||
* to return -EINTR.
|
||||
*/
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
/*
|
||||
* Return -EINTR and set condition code here,
|
||||
* so the interrupted system call actually returns
|
||||
* these.
|
||||
*/
|
||||
regs->psr |= PSR_C;
|
||||
regs->u_regs[UREG_I0] = EINTR;
|
||||
if (do_signal(&saveset, regs, 0, 0))
|
||||
return;
|
||||
}
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
|
||||
asmlinkage int sys_sigpause(unsigned int set)
|
||||
{
|
||||
_sigpause_common(set, regs);
|
||||
return _sigpause_common(set);
|
||||
}
|
||||
|
||||
asmlinkage void do_sigsuspend (struct pt_regs *regs)
|
||||
asmlinkage int sys_sigsuspend(old_sigset_t set)
|
||||
{
|
||||
_sigpause_common(regs->u_regs[UREG_I0], regs);
|
||||
}
|
||||
|
||||
asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
sigset_t oldset, set;
|
||||
|
||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||
if (sigsetsize != sizeof(sigset_t)) {
|
||||
regs->psr |= PSR_C;
|
||||
regs->u_regs[UREG_I0] = EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (copy_from_user(&set, uset, sizeof(set))) {
|
||||
regs->psr |= PSR_C;
|
||||
regs->u_regs[UREG_I0] = EFAULT;
|
||||
return;
|
||||
}
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
oldset = current->blocked;
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
regs->pc = regs->npc;
|
||||
regs->npc += 4;
|
||||
|
||||
/* Condition codes and return value where set here for sigpause,
|
||||
* and so got used by setup_frame, which again causes sigreturn()
|
||||
* to return -EINTR.
|
||||
*/
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
/*
|
||||
* Return -EINTR and set condition code here,
|
||||
* so the interrupted system call actually returns
|
||||
* these.
|
||||
*/
|
||||
regs->psr |= PSR_C;
|
||||
regs->u_regs[UREG_I0] = EINTR;
|
||||
if (do_signal(&oldset, regs, 0, 0))
|
||||
return;
|
||||
}
|
||||
return _sigpause_common(set);
|
||||
}
|
||||
|
||||
static inline int
|
||||
@ -1067,13 +996,13 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
|
||||
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
||||
* mistake.
|
||||
*/
|
||||
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
|
||||
unsigned long orig_i0, int restart_syscall)
|
||||
asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall)
|
||||
{
|
||||
siginfo_t info;
|
||||
struct sparc_deliver_cookie cookie;
|
||||
struct k_sigaction ka;
|
||||
int signr;
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* XXX Disable svr4 signal handling until solaris emulation works.
|
||||
@ -1089,7 +1018,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
|
||||
cookie.restart_syscall = restart_syscall;
|
||||
cookie.orig_i0 = orig_i0;
|
||||
|
||||
if (!oldset)
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
|
||||
@ -1098,7 +1029,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
|
||||
syscall_restart(cookie.orig_i0, regs, &ka.sa);
|
||||
handle_signal(signr, &ka, &info, oldset,
|
||||
regs, svr4_signal);
|
||||
return 1;
|
||||
/* a signal was successfully delivered; the saved
|
||||
* sigmask will have been stored in the signal frame,
|
||||
* and will be restored by sigreturn, so we can simply
|
||||
* clear the TIF_RESTORE_SIGMASK flag.
|
||||
*/
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return;
|
||||
}
|
||||
if (cookie.restart_syscall &&
|
||||
(regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
|
||||
@ -1115,7 +1053,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
|
||||
regs->pc -= 4;
|
||||
regs->npc -= 4;
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* if there's no signal to deliver, we just put the saved sigmask
|
||||
* back
|
||||
*/
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
|
@ -66,7 +66,6 @@ struct poll {
|
||||
|
||||
extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *);
|
||||
extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *);
|
||||
void _sigpause_common (unsigned int set, struct pt_regs *);
|
||||
extern void (*__copy_1page)(void *, const void *);
|
||||
extern void __memmove(void *, const void *, __kernel_size_t);
|
||||
extern void (*bzero_1page)(void *);
|
||||
@ -227,7 +226,6 @@ EXPORT_SYMBOL(kunmap_atomic);
|
||||
/* Solaris/SunOS binary compatibility */
|
||||
EXPORT_SYMBOL(svr4_setcontext);
|
||||
EXPORT_SYMBOL(svr4_getcontext);
|
||||
EXPORT_SYMBOL(_sigpause_common);
|
||||
|
||||
EXPORT_SYMBOL(dump_thread);
|
||||
|
||||
|
@ -75,7 +75,10 @@ sys_call_table:
|
||||
/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
|
||||
/*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
|
||||
/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
|
||||
/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
|
||||
/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
|
||||
/*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_newfstatat
|
||||
/*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll
|
||||
|
||||
#ifdef CONFIG_SUNOS_EMUL
|
||||
/* Now the SunOS syscall table. */
|
||||
@ -181,6 +184,11 @@ sunos_sys_table:
|
||||
.long sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.long sunos_nosys
|
||||
/*280*/ .long sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.long sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.long sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.long sunos_nosys
|
||||
/*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.long sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.long sunos_nosys, sunos_nosys, sunos_nosys
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.15
|
||||
# Mon Jan 9 14:36:29 2006
|
||||
# Linux kernel version: 2.6.16-rc1
|
||||
# Wed Jan 18 13:41:02 2006
|
||||
#
|
||||
CONFIG_SPARC=y
|
||||
CONFIG_SPARC64=y
|
||||
@ -233,6 +233,11 @@ CONFIG_VLAN_8021Q=m
|
||||
# CONFIG_ATALK is not set
|
||||
# CONFIG_X25 is not set
|
||||
# CONFIG_LAPB is not set
|
||||
|
||||
#
|
||||
# TIPC Configuration (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_TIPC is not set
|
||||
# CONFIG_NET_DIVERT is not set
|
||||
# CONFIG_ECONET is not set
|
||||
# CONFIG_WAN_ROUTER is not set
|
||||
@ -420,8 +425,7 @@ CONFIG_ISCSI_TCP=m
|
||||
# CONFIG_SCSI_QLOGIC_FC is not set
|
||||
# CONFIG_SCSI_QLOGIC_1280 is not set
|
||||
# CONFIG_SCSI_QLOGICPTI is not set
|
||||
CONFIG_SCSI_QLA2XXX=y
|
||||
# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set
|
||||
# CONFIG_SCSI_QLA_FC is not set
|
||||
# CONFIG_SCSI_LPFC is not set
|
||||
# CONFIG_SCSI_DC395x is not set
|
||||
# CONFIG_SCSI_DC390T is not set
|
||||
@ -653,7 +657,6 @@ CONFIG_SERIAL_SUNSU_CONSOLE=y
|
||||
CONFIG_SERIAL_SUNSAB=m
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
# CONFIG_SERIAL_JSM is not set
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
|
||||
@ -738,6 +741,12 @@ CONFIG_I2C_ALGOBIT=y
|
||||
# CONFIG_I2C_DEBUG_BUS is not set
|
||||
# CONFIG_I2C_DEBUG_CHIP is not set
|
||||
|
||||
#
|
||||
# SPI support
|
||||
#
|
||||
# CONFIG_SPI is not set
|
||||
# CONFIG_SPI_MASTER is not set
|
||||
|
||||
#
|
||||
# Dallas's 1-wire bus
|
||||
#
|
||||
@ -1015,6 +1024,7 @@ CONFIG_USB_UHCI_HCD=m
|
||||
#
|
||||
CONFIG_USB_HID=y
|
||||
CONFIG_USB_HIDINPUT=y
|
||||
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
|
||||
# CONFIG_HID_FF is not set
|
||||
CONFIG_USB_HIDDEV=y
|
||||
# CONFIG_USB_AIPTEK is not set
|
||||
@ -1269,12 +1279,13 @@ CONFIG_KPROBES=y
|
||||
# Kernel hacking
|
||||
#
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_LOG_BUF_SHIFT=18
|
||||
CONFIG_DETECT_SOFTLOCKUP=y
|
||||
CONFIG_SCHEDSTATS=y
|
||||
# CONFIG_DEBUG_SLAB is not set
|
||||
# CONFIG_DEBUG_MUTEXES is not set
|
||||
# CONFIG_DEBUG_SPINLOCK is not set
|
||||
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
|
||||
# CONFIG_DEBUG_KOBJECT is not set
|
||||
@ -1282,6 +1293,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
|
||||
# CONFIG_DEBUG_INFO is not set
|
||||
CONFIG_DEBUG_FS=y
|
||||
# CONFIG_DEBUG_VM is not set
|
||||
CONFIG_FORCED_INLINING=y
|
||||
# CONFIG_RCU_TORTURE_TEST is not set
|
||||
# CONFIG_DEBUG_STACK_USAGE is not set
|
||||
# CONFIG_DEBUG_DCFLUSH is not set
|
||||
|
@ -1416,7 +1416,6 @@ execve_merge:
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
|
||||
.globl sys_pipe, sys_sigpause, sys_nis_syscall
|
||||
.globl sys_sigsuspend, sys_rt_sigsuspend
|
||||
.globl sys_rt_sigreturn
|
||||
.globl sys_ptrace
|
||||
.globl sys_sigaltstack
|
||||
@ -1440,28 +1439,6 @@ sys32_sigaltstack:
|
||||
mov %i6, %o2
|
||||
#endif
|
||||
.align 32
|
||||
sys_sigsuspend: add %sp, PTREGS_OFF, %o0
|
||||
call do_sigsuspend
|
||||
add %o7, 1f-.-4, %o7
|
||||
nop
|
||||
sys_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
|
||||
add %sp, PTREGS_OFF, %o2
|
||||
call do_rt_sigsuspend
|
||||
add %o7, 1f-.-4, %o7
|
||||
nop
|
||||
#ifdef CONFIG_COMPAT
|
||||
.globl sys32_rt_sigsuspend
|
||||
sys32_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
|
||||
srl %o0, 0, %o0
|
||||
add %sp, PTREGS_OFF, %o2
|
||||
call do_rt_sigsuspend32
|
||||
add %o7, 1f-.-4, %o7
|
||||
#endif
|
||||
/* NOTE: %o0 has a correct value already */
|
||||
sys_sigpause: add %sp, PTREGS_OFF, %o1
|
||||
call do_sigpause
|
||||
add %o7, 1f-.-4, %o7
|
||||
nop
|
||||
#ifdef CONFIG_COMPAT
|
||||
.globl sys32_sigreturn
|
||||
sys32_sigreturn:
|
||||
|
@ -164,6 +164,7 @@ void machine_restart(char * cmd)
|
||||
panic("Reboot failed!");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static void show_regwindow32(struct pt_regs *regs)
|
||||
{
|
||||
struct reg_window32 __user *rw;
|
||||
@ -189,6 +190,9 @@ static void show_regwindow32(struct pt_regs *regs)
|
||||
r_w.ins[0], r_w.ins[1], r_w.ins[2], r_w.ins[3],
|
||||
r_w.ins[4], r_w.ins[5], r_w.ins[6], r_w.ins[7]);
|
||||
}
|
||||
#else
|
||||
#define show_regwindow32(regs) do { } while (0)
|
||||
#endif
|
||||
|
||||
static void show_regwindow(struct pt_regs *regs)
|
||||
{
|
||||
|
@ -53,14 +53,13 @@ __handle_user_windows:
|
||||
wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
|
||||
ldx [%g6 + TI_FLAGS], %l0
|
||||
|
||||
1: andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
|
||||
1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
|
||||
be,pt %xcc, __handle_user_windows_continue
|
||||
nop
|
||||
clr %o0
|
||||
mov %l5, %o2
|
||||
mov %l6, %o3
|
||||
add %sp, PTREGS_OFF, %o1
|
||||
mov %l0, %o4
|
||||
mov %l5, %o1
|
||||
mov %l6, %o2
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
mov %l0, %o3
|
||||
|
||||
call do_notify_resume
|
||||
wrpr %g0, RTRAP_PSTATE, %pstate
|
||||
@ -96,15 +95,14 @@ __handle_perfctrs:
|
||||
wrpr %g0, RTRAP_PSTATE, %pstate
|
||||
wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
|
||||
ldx [%g6 + TI_FLAGS], %l0
|
||||
1: andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
|
||||
1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
|
||||
|
||||
be,pt %xcc, __handle_perfctrs_continue
|
||||
sethi %hi(TSTATE_PEF), %o0
|
||||
clr %o0
|
||||
mov %l5, %o2
|
||||
mov %l6, %o3
|
||||
add %sp, PTREGS_OFF, %o1
|
||||
mov %l0, %o4
|
||||
mov %l5, %o1
|
||||
mov %l6, %o2
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
mov %l0, %o3
|
||||
call do_notify_resume
|
||||
|
||||
wrpr %g0, RTRAP_PSTATE, %pstate
|
||||
@ -129,11 +127,10 @@ __handle_userfpu:
|
||||
ba,a,pt %xcc, __handle_userfpu_continue
|
||||
|
||||
__handle_signal:
|
||||
clr %o0
|
||||
mov %l5, %o2
|
||||
mov %l6, %o3
|
||||
add %sp, PTREGS_OFF, %o1
|
||||
mov %l0, %o4
|
||||
mov %l5, %o1
|
||||
mov %l6, %o2
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
mov %l0, %o3
|
||||
call do_notify_resume
|
||||
wrpr %g0, RTRAP_PSTATE, %pstate
|
||||
wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
|
||||
@ -200,7 +197,7 @@ __handle_preemption_continue:
|
||||
andcc %l1, %o0, %g0
|
||||
andcc %l0, _TIF_NEED_RESCHED, %g0
|
||||
bne,pn %xcc, __handle_preemption
|
||||
andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
|
||||
andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
|
||||
bne,pn %xcc, __handle_signal
|
||||
__handle_signal_continue:
|
||||
ldub [%g6 + TI_WSAVED], %o2
|
||||
|
@ -561,6 +561,8 @@ static int __init set_preferred_console(void)
|
||||
serial_console = 1;
|
||||
} else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
|
||||
serial_console = 2;
|
||||
} else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) {
|
||||
serial_console = 3;
|
||||
} else {
|
||||
prom_printf("Inconsistent console: "
|
||||
"input %d, output %d\n",
|
||||
|
@ -36,9 +36,6 @@
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
static int do_signal(sigset_t *oldset, struct pt_regs * regs,
|
||||
unsigned long orig_o0, int ret_from_syscall);
|
||||
|
||||
/* {set, get}context() needed for 64-bit SparcLinux userland. */
|
||||
asmlinkage void sparc64_set_context(struct pt_regs *regs)
|
||||
{
|
||||
@ -242,114 +239,29 @@ struct rt_signal_frame {
|
||||
/* Align macros */
|
||||
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
|
||||
|
||||
/*
|
||||
* atomically swap in the new signal mask, and wait for a signal.
|
||||
* This is really tricky on the Sparc, watch out...
|
||||
*/
|
||||
asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs)
|
||||
static long _sigpause_common(old_sigset_t set)
|
||||
{
|
||||
sigset_t saveset;
|
||||
|
||||
#ifdef CONFIG_SPARC32_COMPAT
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
extern asmlinkage void _sigpause32_common(compat_old_sigset_t,
|
||||
struct pt_regs *);
|
||||
_sigpause32_common(set, regs);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
set &= _BLOCKABLE;
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->saved_sigmask = current->blocked;
|
||||
siginitset(¤t->blocked, set);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
regs->tpc = (regs->tnpc & 0xffffffff);
|
||||
regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
|
||||
} else {
|
||||
regs->tpc = regs->tnpc;
|
||||
regs->tnpc += 4;
|
||||
}
|
||||
|
||||
/* Condition codes and return value where set here for sigpause,
|
||||
* and so got used by setup_frame, which again causes sigreturn()
|
||||
* to return -EINTR.
|
||||
*/
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
/*
|
||||
* Return -EINTR and set condition code here,
|
||||
* so the interrupted system call actually returns
|
||||
* these.
|
||||
*/
|
||||
regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
|
||||
regs->u_regs[UREG_I0] = EINTR;
|
||||
if (do_signal(&saveset, regs, 0, 0))
|
||||
return;
|
||||
}
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
|
||||
asmlinkage long sys_sigpause(unsigned int set)
|
||||
{
|
||||
_sigpause_common(set, regs);
|
||||
return _sigpause_common(set);
|
||||
}
|
||||
|
||||
asmlinkage void do_sigsuspend(struct pt_regs *regs)
|
||||
asmlinkage long sys_sigsuspend(old_sigset_t set)
|
||||
{
|
||||
_sigpause_common(regs->u_regs[UREG_I0], regs);
|
||||
}
|
||||
|
||||
asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t oldset, set;
|
||||
|
||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||
if (sigsetsize != sizeof(sigset_t)) {
|
||||
regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
|
||||
regs->u_regs[UREG_I0] = EINVAL;
|
||||
return;
|
||||
}
|
||||
if (copy_from_user(&set, uset, sizeof(set))) {
|
||||
regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
|
||||
regs->u_regs[UREG_I0] = EFAULT;
|
||||
return;
|
||||
}
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
oldset = current->blocked;
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
regs->tpc = (regs->tnpc & 0xffffffff);
|
||||
regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
|
||||
} else {
|
||||
regs->tpc = regs->tnpc;
|
||||
regs->tnpc += 4;
|
||||
}
|
||||
|
||||
/* Condition codes and return value where set here for sigpause,
|
||||
* and so got used by setup_frame, which again causes sigreturn()
|
||||
* to return -EINTR.
|
||||
*/
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
/*
|
||||
* Return -EINTR and set condition code here,
|
||||
* so the interrupted system call actually returns
|
||||
* these.
|
||||
*/
|
||||
regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
|
||||
regs->u_regs[UREG_I0] = EINTR;
|
||||
if (do_signal(&oldset, regs, 0, 0))
|
||||
return;
|
||||
}
|
||||
return _sigpause_common(set);
|
||||
}
|
||||
|
||||
static inline int
|
||||
@ -607,26 +519,29 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
|
||||
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
||||
* mistake.
|
||||
*/
|
||||
static int do_signal(sigset_t *oldset, struct pt_regs * regs,
|
||||
unsigned long orig_i0, int restart_syscall)
|
||||
static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall)
|
||||
{
|
||||
siginfo_t info;
|
||||
struct signal_deliver_cookie cookie;
|
||||
struct k_sigaction ka;
|
||||
int signr;
|
||||
sigset_t *oldset;
|
||||
|
||||
cookie.restart_syscall = restart_syscall;
|
||||
cookie.orig_i0 = orig_i0;
|
||||
|
||||
if (!oldset)
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
#ifdef CONFIG_SPARC32_COMPAT
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
extern int do_signal32(sigset_t *, struct pt_regs *,
|
||||
unsigned long, int);
|
||||
return do_signal32(oldset, regs, orig_i0,
|
||||
cookie.restart_syscall);
|
||||
extern void do_signal32(sigset_t *, struct pt_regs *,
|
||||
unsigned long, int);
|
||||
do_signal32(oldset, regs, orig_i0,
|
||||
cookie.restart_syscall);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -635,7 +550,15 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
|
||||
if (cookie.restart_syscall)
|
||||
syscall_restart(orig_i0, regs, &ka.sa);
|
||||
handle_signal(signr, &ka, &info, oldset, regs);
|
||||
return 1;
|
||||
|
||||
/* a signal was successfully delivered; the saved
|
||||
* sigmask will have been stored in the signal frame,
|
||||
* and will be restored by sigreturn, so we can simply
|
||||
* clear the TIF_RESTORE_SIGMASK flag.
|
||||
*/
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return;
|
||||
}
|
||||
if (cookie.restart_syscall &&
|
||||
(regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
|
||||
@ -652,15 +575,21 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
|
||||
regs->tpc -= 4;
|
||||
regs->tnpc -= 4;
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* if there's no signal to deliver, we just put the saved sigmask
|
||||
* back
|
||||
*/
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void do_notify_resume(sigset_t *oldset, struct pt_regs *regs,
|
||||
unsigned long orig_i0, int restart_syscall,
|
||||
void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall,
|
||||
unsigned long thread_info_flags)
|
||||
{
|
||||
if (thread_info_flags & _TIF_SIGPENDING)
|
||||
do_signal(oldset, regs, orig_i0, restart_syscall);
|
||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
||||
do_signal(regs, orig_i0, restart_syscall);
|
||||
}
|
||||
|
||||
void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
|
||||
|
@ -32,9 +32,6 @@
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
int do_signal32(sigset_t *oldset, struct pt_regs *regs,
|
||||
unsigned long orig_o0, int ret_from_syscall);
|
||||
|
||||
/* Signal frames: the original one (compatible with SunOS):
|
||||
*
|
||||
* Set up a signal frame... Make the stack look the way SunOS
|
||||
@ -226,102 +223,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* atomically swap in the new signal mask, and wait for a signal.
|
||||
* This is really tricky on the Sparc, watch out...
|
||||
*/
|
||||
asmlinkage void _sigpause32_common(compat_old_sigset_t set, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t saveset;
|
||||
|
||||
set &= _BLOCKABLE;
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
siginitset(¤t->blocked, set);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
regs->tpc = regs->tnpc;
|
||||
regs->tnpc += 4;
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
|
||||
/* Condition codes and return value where set here for sigpause,
|
||||
* and so got used by setup_frame, which again causes sigreturn()
|
||||
* to return -EINTR.
|
||||
*/
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
/*
|
||||
* Return -EINTR and set condition code here,
|
||||
* so the interrupted system call actually returns
|
||||
* these.
|
||||
*/
|
||||
regs->tstate |= TSTATE_ICARRY;
|
||||
regs->u_regs[UREG_I0] = EINTR;
|
||||
if (do_signal32(&saveset, regs, 0, 0))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t oldset, set;
|
||||
compat_sigset_t set32;
|
||||
|
||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||
if (((compat_size_t)sigsetsize) != sizeof(sigset_t)) {
|
||||
regs->tstate |= TSTATE_ICARRY;
|
||||
regs->u_regs[UREG_I0] = EINVAL;
|
||||
return;
|
||||
}
|
||||
if (copy_from_user(&set32, compat_ptr(uset), sizeof(set32))) {
|
||||
regs->tstate |= TSTATE_ICARRY;
|
||||
regs->u_regs[UREG_I0] = EFAULT;
|
||||
return;
|
||||
}
|
||||
switch (_NSIG_WORDS) {
|
||||
case 4: set.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);
|
||||
case 3: set.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);
|
||||
case 2: set.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);
|
||||
case 1: set.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);
|
||||
}
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
oldset = current->blocked;
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
regs->tpc = regs->tnpc;
|
||||
regs->tnpc += 4;
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
|
||||
/* Condition codes and return value where set here for sigpause,
|
||||
* and so got used by setup_frame, which again causes sigreturn()
|
||||
* to return -EINTR.
|
||||
*/
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
/*
|
||||
* Return -EINTR and set condition code here,
|
||||
* so the interrupted system call actually returns
|
||||
* these.
|
||||
*/
|
||||
regs->tstate |= TSTATE_ICARRY;
|
||||
regs->u_regs[UREG_I0] = EINTR;
|
||||
if (do_signal32(&oldset, regs, 0, 0))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
|
||||
{
|
||||
unsigned long *fpregs = current_thread_info()->fpregs;
|
||||
@ -1362,8 +1263,8 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
|
||||
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
||||
* mistake.
|
||||
*/
|
||||
int do_signal32(sigset_t *oldset, struct pt_regs * regs,
|
||||
unsigned long orig_i0, int restart_syscall)
|
||||
void do_signal32(sigset_t *oldset, struct pt_regs * regs,
|
||||
unsigned long orig_i0, int restart_syscall)
|
||||
{
|
||||
siginfo_t info;
|
||||
struct signal_deliver_cookie cookie;
|
||||
@ -1380,7 +1281,15 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs,
|
||||
syscall_restart32(orig_i0, regs, &ka.sa);
|
||||
handle_signal32(signr, &ka, &info, oldset,
|
||||
regs, svr4_signal);
|
||||
return 1;
|
||||
|
||||
/* a signal was successfully delivered; the saved
|
||||
* sigmask will have been stored in the signal frame,
|
||||
* and will be restored by sigreturn, so we can simply
|
||||
* clear the TIF_RESTORE_SIGMASK flag.
|
||||
*/
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return;
|
||||
}
|
||||
if (cookie.restart_syscall &&
|
||||
(regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
|
||||
@ -1397,7 +1306,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs,
|
||||
regs->tpc -= 4;
|
||||
regs->tnpc -= 4;
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* if there's no signal to deliver, we just put the saved sigmask
|
||||
* back
|
||||
*/
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
struct sigstack32 {
|
||||
|
@ -69,7 +69,6 @@ struct poll {
|
||||
|
||||
extern void die_if_kernel(char *str, struct pt_regs *regs);
|
||||
extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
|
||||
void _sigpause_common (unsigned int set, struct pt_regs *);
|
||||
extern void *__bzero(void *, size_t);
|
||||
extern void *__memscan_zero(void *, size_t);
|
||||
extern void *__memscan_generic(void *, int, size_t);
|
||||
@ -236,9 +235,10 @@ EXPORT_SYMBOL(pci_dma_supported);
|
||||
/* I/O device mmaping on Sparc64. */
|
||||
EXPORT_SYMBOL(io_remap_pfn_range);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
/* Solaris/SunOS binary compatibility */
|
||||
EXPORT_SYMBOL(_sigpause_common);
|
||||
EXPORT_SYMBOL(verify_compat_iovec);
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(dump_fpu);
|
||||
EXPORT_SYMBOL(pte_alloc_one_kernel);
|
||||
|
@ -821,7 +821,7 @@ asmlinkage long sys32_utimes(char __user *filename,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return do_utimes(filename, (tvs ? &ktvs[0] : NULL));
|
||||
return do_utimes(AT_FDCWD, filename, (tvs ? &ktvs[0] : NULL));
|
||||
}
|
||||
|
||||
/* These are here just in case some old sparc32 binary calls it. */
|
||||
@ -1003,7 +1003,7 @@ asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
|
||||
asmlinkage long sparc32_open(const char __user *filename,
|
||||
int flags, int mode)
|
||||
{
|
||||
return do_sys_open(filename, flags, mode);
|
||||
return do_sys_open(AT_FDCWD, filename, flags, mode);
|
||||
}
|
||||
|
||||
extern unsigned long do_mremap(unsigned long addr,
|
||||
|
@ -41,7 +41,7 @@ sys_call_table32:
|
||||
/*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid
|
||||
.word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
|
||||
/*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
|
||||
.word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
|
||||
.word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid
|
||||
/*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
|
||||
.word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
|
||||
/*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
|
||||
@ -76,7 +76,10 @@ sys_call_table32:
|
||||
.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
|
||||
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
|
||||
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
|
||||
/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
|
||||
/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
|
||||
.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_newfstatat
|
||||
/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
@ -142,7 +145,10 @@ sys_call_table:
|
||||
.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
|
||||
/*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
|
||||
.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
|
||||
/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl
|
||||
/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
|
||||
.word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, compat_sys_newfstatat
|
||||
/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll
|
||||
|
||||
#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
|
||||
defined(CONFIG_SOLARIS_EMUL_MODULE)
|
||||
@ -239,13 +245,20 @@ sunos_sys_table:
|
||||
/*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys
|
||||
/*260*/ .word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys
|
||||
/*270*/ .word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys
|
||||
/*280*/ .word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys
|
||||
/*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
.word sunos_nosys, sunos_nosys, sunos_nosys
|
||||
#endif
|
||||
|
@ -99,8 +99,12 @@ prom_query_input_device(void)
|
||||
if (!strncmp(propb, "keyboard", 8))
|
||||
return PROMDEV_ITTYA;
|
||||
|
||||
if (!strncmp (propb, "rsc", 3))
|
||||
return PROMDEV_IRSC;
|
||||
|
||||
if (strncmp (propb, "tty", 3) || !propb[3])
|
||||
return PROMDEV_I_UNK;
|
||||
|
||||
switch (propb[3]) {
|
||||
case 'a': return PROMDEV_ITTYA;
|
||||
case 'b': return PROMDEV_ITTYB;
|
||||
@ -136,8 +140,12 @@ prom_query_output_device(void)
|
||||
if (!strncmp(propb, "screen", 6))
|
||||
return PROMDEV_OTTYA;
|
||||
|
||||
if (!strncmp (propb, "rsc", 3))
|
||||
return PROMDEV_ORSC;
|
||||
|
||||
if (strncmp (propb, "tty", 3) || !propb[3])
|
||||
return PROMDEV_O_UNK;
|
||||
|
||||
switch (propb[3]) {
|
||||
case 'a': return PROMDEV_OTTYA;
|
||||
case 'b': return PROMDEV_OTTYB;
|
||||
|
@ -180,6 +180,8 @@ solaris_sigsuspend:
|
||||
nop
|
||||
call sys_sigsuspend
|
||||
stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
|
||||
b,pt %xcc, ret_from_solaris
|
||||
nop
|
||||
|
||||
.globl solaris_getpid
|
||||
solaris_getpid:
|
||||
|
@ -143,6 +143,7 @@ config HOSTFS
|
||||
|
||||
config HPPFS
|
||||
tristate "HoneyPot ProcFS (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
|
||||
entries to be overridden, removed, or fabricated from the host.
|
||||
@ -155,10 +156,6 @@ config HPPFS
|
||||
You only need this if you are setting up a UML honeypot. Otherwise,
|
||||
it is safe to say 'N' here.
|
||||
|
||||
If you are actively using it, please report any problems, since it's
|
||||
getting fixed. In this moment, it is experimental on 2.6 (it works on
|
||||
2.4).
|
||||
|
||||
config MCONSOLE
|
||||
bool "Management console"
|
||||
default y
|
||||
@ -243,8 +240,16 @@ config NEST_LEVEL
|
||||
Only change this if you are running nested UMLs.
|
||||
|
||||
config HIGHMEM
|
||||
bool "Highmem support"
|
||||
depends on !64BIT
|
||||
bool "Highmem support (EXPERIMENTAL)"
|
||||
depends on !64BIT && EXPERIMENTAL
|
||||
default n
|
||||
help
|
||||
This was used to allow UML to run with big amounts of memory.
|
||||
Currently it is unstable, so if unsure say N.
|
||||
|
||||
To use big amounts of memory, it is recommended to disable TT mode (i.e.
|
||||
CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) -
|
||||
this should allow the guest to use up to 2.75G of memory.
|
||||
|
||||
config KERNEL_STACK_ORDER
|
||||
int "Kernel stack size order"
|
||||
@ -269,17 +274,13 @@ endmenu
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
source "net/Kconfig"
|
||||
|
||||
source "drivers/base/Kconfig"
|
||||
source "drivers/block/Kconfig"
|
||||
|
||||
source "arch/um/Kconfig.char"
|
||||
|
||||
source "drivers/block/Kconfig"
|
||||
source "drivers/base/Kconfig"
|
||||
|
||||
config NETDEVICES
|
||||
bool
|
||||
default NET
|
||||
source "net/Kconfig"
|
||||
|
||||
source "arch/um/Kconfig.net"
|
||||
|
||||
|
@ -22,13 +22,17 @@ config TOP_ADDR
|
||||
default 0x80000000 if HOST_2G_2G
|
||||
|
||||
config 3_LEVEL_PGTABLES
|
||||
bool "Three-level pagetables"
|
||||
bool "Three-level pagetables (EXPERIMENTAL)"
|
||||
default n
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
Three-level pagetables will let UML have more than 4G of physical
|
||||
memory. All the memory that can't be mapped directly will be treated
|
||||
as high memory.
|
||||
|
||||
However, this it experimental on 32-bit architectures, so if unsure say
|
||||
N (on x86-64 it's automatically enabled, instead, as it's safe there).
|
||||
|
||||
config STUB_CODE
|
||||
hex
|
||||
default 0xbfffe000
|
||||
|
@ -32,7 +32,7 @@ um-modes-$(CONFIG_MODE_TT) += tt
|
||||
um-modes-$(CONFIG_MODE_SKAS) += skas
|
||||
|
||||
MODE_INCLUDE += $(foreach mode,$(um-modes-y),\
|
||||
-I$(srctree)/$(ARCH_DIR)/kernel/$(mode)/include)
|
||||
-I$(srctree)/$(ARCH_DIR)/include/$(mode))
|
||||
|
||||
MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\
|
||||
$(srctree)/$(ARCH_DIR)/Makefile-$(mode))
|
||||
|
@ -31,6 +31,10 @@ void daemon_init(struct net_device *dev, void *data)
|
||||
dpri->fd = -1;
|
||||
dpri->control = -1;
|
||||
dpri->dev = dev;
|
||||
/* We will free this pointer. If it contains crap we're burned. */
|
||||
dpri->ctl_addr = NULL;
|
||||
dpri->data_addr = NULL;
|
||||
dpri->local_addr = NULL;
|
||||
|
||||
printk("daemon backend (uml_switch version %d) - %s:%s",
|
||||
SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock);
|
||||
|
@ -158,10 +158,16 @@ static void daemon_remove(void *data)
|
||||
struct daemon_data *pri = data;
|
||||
|
||||
os_close_file(pri->fd);
|
||||
pri->fd = -1;
|
||||
os_close_file(pri->control);
|
||||
pri->control = -1;
|
||||
|
||||
kfree(pri->data_addr);
|
||||
pri->data_addr = NULL;
|
||||
kfree(pri->ctl_addr);
|
||||
pri->ctl_addr = NULL;
|
||||
kfree(pri->local_addr);
|
||||
pri->local_addr = NULL;
|
||||
}
|
||||
|
||||
int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "user.h"
|
||||
#include "user_util.h"
|
||||
#include "chan_user.h"
|
||||
#include "os.h"
|
||||
|
||||
struct fd_chan {
|
||||
int fd;
|
||||
|
@ -68,6 +68,11 @@ static int uml_net_rx(struct net_device *dev)
|
||||
return pkt_len;
|
||||
}
|
||||
|
||||
static void uml_dev_close(void* dev)
|
||||
{
|
||||
dev_close( (struct net_device *) dev);
|
||||
}
|
||||
|
||||
irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
@ -80,15 +85,21 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
spin_lock(&lp->lock);
|
||||
while((err = uml_net_rx(dev)) > 0) ;
|
||||
if(err < 0) {
|
||||
DECLARE_WORK(close_work, uml_dev_close, dev);
|
||||
printk(KERN_ERR
|
||||
"Device '%s' read returned %d, shutting it down\n",
|
||||
dev->name, err);
|
||||
dev_close(dev);
|
||||
/* dev_close can't be called in interrupt context, and takes
|
||||
* again lp->lock.
|
||||
* And dev_close() can be safely called multiple times on the
|
||||
* same device, since it tests for (dev->flags & IFF_UP). So
|
||||
* there's no harm in delaying the device shutdown. */
|
||||
schedule_work(&close_work);
|
||||
goto out;
|
||||
}
|
||||
reactivate_fd(lp->fd, UM_ETH_IRQ);
|
||||
|
||||
out:
|
||||
out:
|
||||
spin_unlock(&lp->lock);
|
||||
return(IRQ_HANDLED);
|
||||
}
|
||||
@ -317,6 +328,11 @@ static int eth_configure(int n, void *init, char *mac,
|
||||
return 1;
|
||||
}
|
||||
|
||||
lp = dev->priv;
|
||||
/* This points to the transport private data. It's still clear, but we
|
||||
* must memset it to 0 *now*. Let's help the drivers. */
|
||||
memset(lp, 0, size);
|
||||
|
||||
/* sysfs register */
|
||||
if (!driver_registered) {
|
||||
platform_driver_register(¨_net_driver);
|
||||
@ -358,7 +374,6 @@ static int eth_configure(int n, void *init, char *mac,
|
||||
free_netdev(dev);
|
||||
return 1;
|
||||
}
|
||||
lp = dev->priv;
|
||||
|
||||
/* lp.user is the first four bytes of the transport data, which
|
||||
* has already been initialized. This structure assignment will
|
||||
|
@ -1103,31 +1103,33 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
|
||||
return(-EINVAL);
|
||||
}
|
||||
|
||||
static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
|
||||
static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
|
||||
{
|
||||
struct uml_stat buf1, buf2;
|
||||
int err;
|
||||
|
||||
if(from_cmdline == NULL) return(1);
|
||||
if(!strcmp(from_cmdline, from_cow)) return(1);
|
||||
if(from_cmdline == NULL)
|
||||
return 0;
|
||||
if(!strcmp(from_cmdline, from_cow))
|
||||
return 0;
|
||||
|
||||
err = os_stat_file(from_cmdline, &buf1);
|
||||
if(err < 0){
|
||||
printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
|
||||
return(1);
|
||||
return 0;
|
||||
}
|
||||
err = os_stat_file(from_cow, &buf2);
|
||||
if(err < 0){
|
||||
printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
|
||||
return(1);
|
||||
return 0;
|
||||
|
||||
printk("Backing file mismatch - \"%s\" requested,\n"
|
||||
"\"%s\" specified in COW header of \"%s\"\n",
|
||||
from_cmdline, from_cow, cow);
|
||||
return(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
|
||||
@ -1189,18 +1191,19 @@ int open_ubd_file(char *file, struct openflags *openflags,
|
||||
unsigned long long size;
|
||||
__u32 version, align;
|
||||
char *backing_file;
|
||||
int fd, err, sectorsize, same, mode = 0644;
|
||||
int fd, err, sectorsize, asked_switch, mode = 0644;
|
||||
|
||||
fd = os_open_file(file, *openflags, mode);
|
||||
if(fd < 0){
|
||||
if((fd == -ENOENT) && (create_cow_out != NULL))
|
||||
if (fd < 0) {
|
||||
if ((fd == -ENOENT) && (create_cow_out != NULL))
|
||||
*create_cow_out = 1;
|
||||
if(!openflags->w ||
|
||||
((fd != -EROFS) && (fd != -EACCES))) return(fd);
|
||||
if (!openflags->w ||
|
||||
((fd != -EROFS) && (fd != -EACCES)))
|
||||
return fd;
|
||||
openflags->w = 0;
|
||||
fd = os_open_file(file, *openflags, mode);
|
||||
if(fd < 0)
|
||||
return(fd);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
}
|
||||
|
||||
err = os_lock_file(fd, openflags->w);
|
||||
@ -1209,7 +1212,9 @@ int open_ubd_file(char *file, struct openflags *openflags,
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
if(backing_file_out == NULL) return(fd);
|
||||
/* Succesful return case! */
|
||||
if(backing_file_out == NULL)
|
||||
return(fd);
|
||||
|
||||
err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
|
||||
&size, §orsize, &align, bitmap_offset_out);
|
||||
@ -1218,34 +1223,34 @@ int open_ubd_file(char *file, struct openflags *openflags,
|
||||
"errno = %d\n", file, -err);
|
||||
goto out_close;
|
||||
}
|
||||
if(err) return(fd);
|
||||
if(err)
|
||||
return(fd);
|
||||
|
||||
if(backing_file_out == NULL) return(fd);
|
||||
asked_switch = path_requires_switch(*backing_file_out, backing_file, file);
|
||||
|
||||
same = same_backing_files(*backing_file_out, backing_file, file);
|
||||
|
||||
if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
|
||||
/* Allow switching only if no mismatch. */
|
||||
if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) {
|
||||
printk("Switching backing file to '%s'\n", *backing_file_out);
|
||||
err = write_cow_header(file, fd, *backing_file_out,
|
||||
sectorsize, align, &size);
|
||||
if(err){
|
||||
if (err) {
|
||||
printk("Switch failed, errno = %d\n", -err);
|
||||
return(err);
|
||||
goto out_close;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
*backing_file_out = backing_file;
|
||||
err = backing_file_mismatch(*backing_file_out, size, mtime);
|
||||
if(err) goto out_close;
|
||||
if (err)
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
|
||||
bitmap_len_out, data_offset_out);
|
||||
|
||||
return(fd);
|
||||
return fd;
|
||||
out_close:
|
||||
os_close_file(fd);
|
||||
return(err);
|
||||
return err;
|
||||
}
|
||||
|
||||
int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
|
||||
|
@ -120,8 +120,10 @@ extern void machine_halt(void);
|
||||
extern int is_syscall(unsigned long addr);
|
||||
extern void arch_switch(void);
|
||||
extern void free_irq(unsigned int, void *);
|
||||
extern int um_in_interrupt(void);
|
||||
extern int cpu(void);
|
||||
|
||||
/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
|
||||
extern int __cant_sleep(void);
|
||||
extern void segv_handler(int sig, union uml_pt_regs *regs);
|
||||
extern void sigio_handler(int sig, union uml_pt_regs *regs);
|
||||
|
||||
|
19
arch/um/include/longjmp.h
Normal file
19
arch/um/include/longjmp.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef __UML_LONGJMP_H
|
||||
#define __UML_LONGJMP_H
|
||||
|
||||
#include <setjmp.h>
|
||||
#include "os.h"
|
||||
|
||||
#define UML_SIGLONGJMP(buf, val) do { \
|
||||
longjmp(*buf, val); \
|
||||
} while(0)
|
||||
|
||||
#define UML_SIGSETJMP(buf, enable) ({ \
|
||||
int n; \
|
||||
enable = get_signals(); \
|
||||
n = setjmp(*buf); \
|
||||
if(n != 0) \
|
||||
set_signals(enable); \
|
||||
n; })
|
||||
|
||||
#endif
|
@ -9,22 +9,11 @@
|
||||
#include "linux/config.h"
|
||||
|
||||
#ifdef CONFIG_MODE_TT
|
||||
#include "mode_kern-tt.h"
|
||||
#include "mode_kern_tt.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MODE_SKAS
|
||||
#include "mode_kern-skas.h"
|
||||
#include "mode_kern_skas.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "../os/include/file.h"
|
||||
#include "sysdep/ptrace.h"
|
||||
#include "kern_util.h"
|
||||
#include "skas/mm_id.h"
|
||||
|
||||
#define OS_TYPE_FILE 1
|
||||
#define OS_TYPE_DIR 2
|
||||
@ -190,11 +191,12 @@ extern int os_protect_memory(void *addr, unsigned long len,
|
||||
int r, int w, int x);
|
||||
extern int os_unmap_memory(void *addr, int len);
|
||||
extern void os_flush_stdout(void);
|
||||
extern unsigned long long os_usecs(void);
|
||||
|
||||
/* tt.c
|
||||
* for tt mode only (will be deleted in future...)
|
||||
*/
|
||||
extern void stop(void);
|
||||
extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
|
||||
extern int protect_memory(unsigned long addr, unsigned long len,
|
||||
int r, int w, int x, int must_succeed);
|
||||
extern void forward_pending_sigio(int target);
|
||||
@ -230,9 +232,63 @@ extern void block_signals(void);
|
||||
extern void unblock_signals(void);
|
||||
extern int get_signals(void);
|
||||
extern int set_signals(int enable);
|
||||
extern void os_usr1_signal(int on);
|
||||
|
||||
/* trap.c */
|
||||
extern void os_fill_handlinfo(struct kern_handlers h);
|
||||
extern void do_longjmp(void *p, int val);
|
||||
|
||||
/* util.c */
|
||||
extern void stack_protections(unsigned long address);
|
||||
extern void task_protections(unsigned long address);
|
||||
extern int raw(int fd);
|
||||
extern void setup_machinename(char *machine_out);
|
||||
extern void setup_hostinfo(void);
|
||||
extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
|
||||
|
||||
/* time.c */
|
||||
#define BILLION (1000 * 1000 * 1000)
|
||||
|
||||
extern void switch_timers(int to_real);
|
||||
extern void idle_sleep(int secs);
|
||||
extern void enable_timer(void);
|
||||
extern void disable_timer(void);
|
||||
extern void user_time_init(void);
|
||||
extern void uml_idle_timer(void);
|
||||
extern unsigned long long os_nsecs(void);
|
||||
|
||||
/* skas/mem.c */
|
||||
extern long run_syscall_stub(struct mm_id * mm_idp,
|
||||
int syscall, unsigned long *args, long expected,
|
||||
void **addr, int done);
|
||||
extern long syscall_stub_data(struct mm_id * mm_idp,
|
||||
unsigned long *data, int data_count,
|
||||
void **addr, void **stub_addr);
|
||||
extern int map(struct mm_id * mm_idp, unsigned long virt,
|
||||
unsigned long len, int r, int w, int x, int phys_fd,
|
||||
unsigned long long offset, int done, void **data);
|
||||
extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
|
||||
int done, void **data);
|
||||
extern int protect(struct mm_id * mm_idp, unsigned long addr,
|
||||
unsigned long len, int r, int w, int x, int done,
|
||||
void **data);
|
||||
|
||||
/* skas/process.c */
|
||||
extern int is_skas_winch(int pid, int fd, void *data);
|
||||
extern int start_userspace(unsigned long stub_stack);
|
||||
extern int copy_context_skas0(unsigned long stack, int pid);
|
||||
extern void userspace(union uml_pt_regs *regs);
|
||||
extern void map_stub_pages(int fd, unsigned long code,
|
||||
unsigned long data, unsigned long stack);
|
||||
extern void new_thread(void *stack, void **switch_buf_ptr,
|
||||
void **fork_buf_ptr, void (*handler)(int));
|
||||
extern void thread_wait(void *sw, void *fb);
|
||||
extern void switch_threads(void *me, void *next);
|
||||
extern int start_idle_thread(void *stack, void *switch_buf_ptr,
|
||||
void **fork_buf_ptr);
|
||||
extern void initial_thread_cb_skas(void (*proc)(void *),
|
||||
void *arg);
|
||||
extern void halt_skas(void);
|
||||
extern void reboot_skas(void);
|
||||
|
||||
#endif
|
||||
|
24
arch/um/include/skas/mmu-skas.h
Normal file
24
arch/um/include/skas/mmu-skas.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __SKAS_MMU_H
|
||||
#define __SKAS_MMU_H
|
||||
|
||||
#include "linux/config.h"
|
||||
#include "mm_id.h"
|
||||
#include "asm/ldt.h"
|
||||
|
||||
struct mmu_context_skas {
|
||||
struct mm_id id;
|
||||
unsigned long last_page_table;
|
||||
#ifdef CONFIG_3_LEVEL_PGTABLES
|
||||
unsigned long last_pmd;
|
||||
#endif
|
||||
uml_ldt_t ldt;
|
||||
};
|
||||
|
||||
extern void switch_mm_skas(struct mm_id * mm_idp);
|
||||
|
||||
#endif
|
19
arch/um/include/skas/mode-skas.h
Normal file
19
arch/um/include/skas/mode-skas.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __MODE_SKAS_H__
|
||||
#define __MODE_SKAS_H__
|
||||
|
||||
#include <sysdep/ptrace.h>
|
||||
|
||||
extern unsigned long exec_regs[];
|
||||
extern unsigned long exec_fp_regs[];
|
||||
extern unsigned long exec_fpx_regs[];
|
||||
extern int have_fpx_regs;
|
||||
|
||||
extern void sig_handler_common_skas(int sig, void *sc_ptr);
|
||||
extern void kill_off_processes_skas(void);
|
||||
|
||||
#endif
|
@ -18,7 +18,6 @@ extern int copy_thread_skas(int nr, unsigned long clone_flags,
|
||||
unsigned long sp, unsigned long stack_top,
|
||||
struct task_struct *p, struct pt_regs *regs);
|
||||
extern void release_thread_skas(struct task_struct *task);
|
||||
extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
|
||||
extern void init_idle_skas(void);
|
||||
extern void flush_tlb_kernel_range_skas(unsigned long start,
|
||||
unsigned long end);
|
||||
@ -39,14 +38,3 @@ extern int thread_pid_skas(struct task_struct *task);
|
||||
#define kmem_end_skas (host_task_size - 1024 * 1024)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
@ -22,13 +22,13 @@ struct mm_mmap {
|
||||
|
||||
struct mm_munmap {
|
||||
unsigned long addr;
|
||||
unsigned long len;
|
||||
unsigned long len;
|
||||
};
|
||||
|
||||
struct mm_mprotect {
|
||||
unsigned long addr;
|
||||
unsigned long len;
|
||||
unsigned int prot;
|
||||
unsigned int prot;
|
||||
};
|
||||
|
||||
struct proc_mm_op {
|
||||
@ -42,14 +42,3 @@ struct proc_mm_op {
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
26
arch/um/include/skas/skas.h
Normal file
26
arch/um/include/skas/skas.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __SKAS_H
|
||||
#define __SKAS_H
|
||||
|
||||
#include "mm_id.h"
|
||||
#include "sysdep/ptrace.h"
|
||||
|
||||
extern int userspace_pid[];
|
||||
extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
|
||||
extern int skas_needs_stub;
|
||||
|
||||
extern int user_thread(unsigned long stack, int flags);
|
||||
extern void new_thread_proc(void *stack, void (*handler)(int sig));
|
||||
extern void new_thread_handler(int sig);
|
||||
extern void handle_syscall(union uml_pt_regs *regs);
|
||||
extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
|
||||
extern int new_mm(unsigned long stack);
|
||||
extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
|
||||
extern long execute_syscall_skas(void *r);
|
||||
extern unsigned long current_stub_stack(void);
|
||||
|
||||
#endif
|
@ -19,14 +19,3 @@ extern int clear_user_skas(void __user *mem, int len);
|
||||
extern int strnlen_user_skas(const void __user *str, int len);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __TIME_USER_H__
|
||||
#define __TIME_USER_H__
|
||||
|
||||
extern void timer(void);
|
||||
extern void switch_timers(int to_real);
|
||||
extern void idle_sleep(int secs);
|
||||
extern void enable_timer(void);
|
||||
extern void prepare_timer(void * ptr);
|
||||
extern void disable_timer(void);
|
||||
extern unsigned long time_lock(void);
|
||||
extern void time_unlock(unsigned long);
|
||||
extern void user_time_init(void);
|
||||
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and
|
||||
* Lars Brinkhoff.
|
||||
* Licensed under the GPL
|
12
arch/um/include/tt/mmu-tt.h
Normal file
12
arch/um/include/tt/mmu-tt.h
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __TT_MMU_H
|
||||
#define __TT_MMU_H
|
||||
|
||||
struct mmu_context_tt {
|
||||
};
|
||||
|
||||
#endif
|
23
arch/um/include/tt/mode-tt.h
Normal file
23
arch/um/include/tt/mode-tt.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __MODE_TT_H__
|
||||
#define __MODE_TT_H__
|
||||
|
||||
#include "sysdep/ptrace.h"
|
||||
|
||||
enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
|
||||
|
||||
extern int tracing_pid;
|
||||
|
||||
extern int tracer(int (*init_proc)(void *), void *sp);
|
||||
extern void sig_handler_common_tt(int sig, void *sc);
|
||||
extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
|
||||
extern void reboot_tt(void);
|
||||
extern void halt_tt(void);
|
||||
extern int is_tracer_winch(int pid, int fd, void *data);
|
||||
extern void kill_off_processes_tt(void);
|
||||
|
||||
#endif
|
41
arch/um/include/tt/mode_kern_tt.h
Normal file
41
arch/um/include/tt/mode_kern_tt.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __TT_MODE_KERN_H__
|
||||
#define __TT_MODE_KERN_H__
|
||||
|
||||
#include "linux/sched.h"
|
||||
#include "asm/page.h"
|
||||
#include "asm/ptrace.h"
|
||||
#include "asm/uaccess.h"
|
||||
|
||||
extern void switch_to_tt(void *prev, void *next);
|
||||
extern void flush_thread_tt(void);
|
||||
extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
|
||||
unsigned long esp);
|
||||
extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
|
||||
unsigned long stack_top, struct task_struct *p,
|
||||
struct pt_regs *regs);
|
||||
extern void release_thread_tt(struct task_struct *task);
|
||||
extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
|
||||
extern void init_idle_tt(void);
|
||||
extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
|
||||
extern void flush_tlb_kernel_vm_tt(void);
|
||||
extern void __flush_tlb_one_tt(unsigned long addr);
|
||||
extern void flush_tlb_range_tt(struct vm_area_struct *vma,
|
||||
unsigned long start, unsigned long end);
|
||||
extern void flush_tlb_mm_tt(struct mm_struct *mm);
|
||||
extern void force_flush_all_tt(void);
|
||||
extern long execute_syscall_tt(void *r);
|
||||
extern void before_mem_tt(unsigned long brk_start);
|
||||
extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
|
||||
unsigned long *task_size_out);
|
||||
extern int start_uml_tt(void);
|
||||
extern int external_pid_tt(struct task_struct *task);
|
||||
extern int thread_pid_tt(struct task_struct *task);
|
||||
|
||||
#define kmem_end_tt (host_task_size - ABOVE_KMEM)
|
||||
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
@ -34,13 +34,3 @@ extern long execute_syscall_tt(void *r);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
@ -46,14 +46,3 @@ extern int clear_user_tt(void __user *mem, int len);
|
||||
extern int strnlen_user_tt(const void __user *str, int len);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
@ -18,6 +18,7 @@ extern int open_gdb_chan(void);
|
||||
extern unsigned long strlcpy(char *, const char *, unsigned long);
|
||||
extern unsigned long strlcat(char *, const char *, unsigned long);
|
||||
extern void *um_vmalloc(int size);
|
||||
extern void *um_vmalloc_atomic(int size);
|
||||
extern void vfree(void *ptr);
|
||||
|
||||
#endif
|
||||
|
@ -44,10 +44,6 @@ extern unsigned long brk_start;
|
||||
extern int pty_output_sigio;
|
||||
extern int pty_close_sigio;
|
||||
|
||||
extern void stop(void);
|
||||
extern void stack_protections(unsigned long address);
|
||||
extern void task_protections(unsigned long address);
|
||||
extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
|
||||
extern void *add_signal_handler(int sig, void (*handler)(int));
|
||||
extern int linux_main(int argc, char **argv);
|
||||
extern void set_cmdline(char *cmd);
|
||||
@ -55,8 +51,6 @@ extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
|
||||
extern int get_pty(void);
|
||||
extern void *um_kmalloc(int size);
|
||||
extern int switcheroo(int fd, int prot, void *from, void *to, int size);
|
||||
extern void setup_machinename(char *machine_out);
|
||||
extern void setup_hostinfo(void);
|
||||
extern void do_exec(int old_pid, int new_pid);
|
||||
extern void tracer_panic(char *msg, ...);
|
||||
extern int detach(int pid, int sig);
|
||||
@ -70,18 +64,6 @@ extern int cpu_feature(char *what, char *buf, int len);
|
||||
extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
|
||||
extern int arch_fixup(unsigned long address, void *sc_ptr);
|
||||
extern void arch_init_thread(void);
|
||||
extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
|
||||
extern int raw(int fd);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
|
@ -9,9 +9,8 @@ clean-files :=
|
||||
obj-y = config.o exec_kern.o exitcode.o \
|
||||
init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
|
||||
process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
|
||||
signal_kern.o smp.o syscall_kern.o sysrq.o time.o \
|
||||
time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o \
|
||||
user_util.o
|
||||
signal_kern.o smp.o syscall_kern.o sysrq.o \
|
||||
time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o
|
||||
|
||||
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
|
||||
obj-$(CONFIG_GPROF) += gprof_syms.o
|
||||
@ -24,7 +23,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/
|
||||
|
||||
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
|
||||
|
||||
USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o
|
||||
USER_OBJS := $(user-objs-y) config.o tty_log.o
|
||||
|
||||
include arch/um/scripts/Makefile.rules
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "irq_user.h"
|
||||
#include "tlb.h"
|
||||
#include "os.h"
|
||||
#include "time_user.h"
|
||||
#include "choose-mode.h"
|
||||
#include "mode_kern.h"
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include "init.h"
|
||||
#include "irq_user.h"
|
||||
#include "mem_user.h"
|
||||
#include "time_user.h"
|
||||
#include "tlb.h"
|
||||
#include "frame_kern.h"
|
||||
#include "sigcontext.h"
|
||||
@ -288,17 +287,27 @@ EXPORT_SYMBOL(disable_hlt);
|
||||
|
||||
void *um_kmalloc(int size)
|
||||
{
|
||||
return(kmalloc(size, GFP_KERNEL));
|
||||
return kmalloc(size, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void *um_kmalloc_atomic(int size)
|
||||
{
|
||||
return(kmalloc(size, GFP_ATOMIC));
|
||||
return kmalloc(size, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
void *um_vmalloc(int size)
|
||||
{
|
||||
return(vmalloc(size));
|
||||
return vmalloc(size);
|
||||
}
|
||||
|
||||
void *um_vmalloc_atomic(int size)
|
||||
{
|
||||
return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
|
||||
}
|
||||
|
||||
int __cant_sleep(void) {
|
||||
return in_atomic() || irqs_disabled() || in_interrupt();
|
||||
/* Is in_interrupt() really needed? */
|
||||
}
|
||||
|
||||
unsigned long get_fault_addr(void)
|
||||
@ -370,11 +379,6 @@ int smp_sigio_handler(void)
|
||||
return(0);
|
||||
}
|
||||
|
||||
int um_in_interrupt(void)
|
||||
{
|
||||
return(in_interrupt());
|
||||
}
|
||||
|
||||
int cpu(void)
|
||||
{
|
||||
return(current_thread->cpu);
|
||||
|
@ -337,70 +337,103 @@ int ignore_sigio_fd(int fd)
|
||||
return(err);
|
||||
}
|
||||
|
||||
static int setup_initial_poll(int fd)
|
||||
static struct pollfd* setup_initial_poll(int fd)
|
||||
{
|
||||
struct pollfd *p;
|
||||
|
||||
p = um_kmalloc_atomic(sizeof(struct pollfd));
|
||||
if(p == NULL){
|
||||
p = um_kmalloc(sizeof(struct pollfd));
|
||||
if (p == NULL) {
|
||||
printk("setup_initial_poll : failed to allocate poll\n");
|
||||
return(-1);
|
||||
return NULL;
|
||||
}
|
||||
*p = ((struct pollfd) { .fd = fd,
|
||||
.events = POLLIN,
|
||||
.revents = 0 });
|
||||
current_poll = ((struct pollfds) { .poll = p,
|
||||
.used = 1,
|
||||
.size = 1 });
|
||||
return(0);
|
||||
return p;
|
||||
}
|
||||
|
||||
void write_sigio_workaround(void)
|
||||
{
|
||||
unsigned long stack;
|
||||
struct pollfd *p;
|
||||
int err;
|
||||
int l_write_sigio_fds[2];
|
||||
int l_sigio_private[2];
|
||||
int l_write_sigio_pid;
|
||||
|
||||
/* We call this *tons* of times - and most ones we must just fail. */
|
||||
sigio_lock();
|
||||
if(write_sigio_pid != -1)
|
||||
goto out;
|
||||
l_write_sigio_pid = write_sigio_pid;
|
||||
sigio_unlock();
|
||||
|
||||
err = os_pipe(write_sigio_fds, 1, 1);
|
||||
if (l_write_sigio_pid != -1)
|
||||
return;
|
||||
|
||||
err = os_pipe(l_write_sigio_fds, 1, 1);
|
||||
if(err < 0){
|
||||
printk("write_sigio_workaround - os_pipe 1 failed, "
|
||||
"err = %d\n", -err);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
err = os_pipe(sigio_private, 1, 1);
|
||||
err = os_pipe(l_sigio_private, 1, 1);
|
||||
if(err < 0){
|
||||
printk("write_sigio_workaround - os_pipe 2 failed, "
|
||||
printk("write_sigio_workaround - os_pipe 1 failed, "
|
||||
"err = %d\n", -err);
|
||||
goto out_close1;
|
||||
}
|
||||
if(setup_initial_poll(sigio_private[1]))
|
||||
|
||||
p = setup_initial_poll(l_sigio_private[1]);
|
||||
if(!p)
|
||||
goto out_close2;
|
||||
|
||||
write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
|
||||
sigio_lock();
|
||||
|
||||
/* Did we race? Don't try to optimize this, please, it's not so likely
|
||||
* to happen, and no more than once at the boot. */
|
||||
if(write_sigio_pid != -1)
|
||||
goto out_unlock;
|
||||
|
||||
write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
|
||||
CLONE_FILES | CLONE_VM, &stack, 0);
|
||||
|
||||
if(write_sigio_pid < 0) goto out_close2;
|
||||
if (write_sigio_pid < 0)
|
||||
goto out_clear;
|
||||
|
||||
if(write_sigio_irq(write_sigio_fds[0]))
|
||||
if (write_sigio_irq(l_write_sigio_fds[0]))
|
||||
goto out_kill;
|
||||
|
||||
out:
|
||||
/* Success, finally. */
|
||||
memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
|
||||
memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
|
||||
|
||||
current_poll = ((struct pollfds) { .poll = p,
|
||||
.used = 1,
|
||||
.size = 1 });
|
||||
|
||||
sigio_unlock();
|
||||
return;
|
||||
|
||||
out_kill:
|
||||
os_kill_process(write_sigio_pid, 1);
|
||||
l_write_sigio_pid = write_sigio_pid;
|
||||
write_sigio_pid = -1;
|
||||
out_close2:
|
||||
os_close_file(sigio_private[0]);
|
||||
os_close_file(sigio_private[1]);
|
||||
out_close1:
|
||||
os_close_file(write_sigio_fds[0]);
|
||||
os_close_file(write_sigio_fds[1]);
|
||||
sigio_unlock();
|
||||
/* Going to call waitpid, avoid holding the lock. */
|
||||
os_kill_process(l_write_sigio_pid, 1);
|
||||
goto out_free;
|
||||
|
||||
out_clear:
|
||||
write_sigio_pid = -1;
|
||||
out_unlock:
|
||||
sigio_unlock();
|
||||
out_free:
|
||||
kfree(p);
|
||||
out_close2:
|
||||
os_close_file(l_sigio_private[0]);
|
||||
os_close_file(l_sigio_private[1]);
|
||||
out_close1:
|
||||
os_close_file(l_write_sigio_fds[0]);
|
||||
os_close_file(l_write_sigio_fds[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
int read_sigio_fd(int fd)
|
||||
|
@ -99,31 +99,46 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||
static int kern_do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct k_sigaction ka_copy;
|
||||
siginfo_t info;
|
||||
sigset_t *oldset;
|
||||
int sig, handled_sig = 0;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){
|
||||
handled_sig = 1;
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if(!handle_signal(regs, sig, &ka_copy, &info, oldset))
|
||||
if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){
|
||||
/* a signal was successfully delivered; the saved
|
||||
* sigmask will have been stored in the signal frame,
|
||||
* and will be restored by sigreturn, so we can simply
|
||||
* clear the TIF_RESTORE_SIGMASK flag */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we come from a system call? */
|
||||
if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
|
||||
/* Restart the system call - no handlers present */
|
||||
if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND ||
|
||||
PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS ||
|
||||
PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){
|
||||
switch(PT_REGS_SYSCALL_RET(regs)){
|
||||
case -ERESTARTNOHAND:
|
||||
case -ERESTARTSYS:
|
||||
case -ERESTARTNOINTR:
|
||||
PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
|
||||
PT_REGS_RESTART_SYSCALL(regs);
|
||||
}
|
||||
else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){
|
||||
break;
|
||||
case -ERESTART_RESTARTBLOCK:
|
||||
PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
|
||||
PT_REGS_RESTART_SYSCALL(regs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,12 +152,19 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||
if(current->ptrace & PT_DTRACE)
|
||||
current->thread.singlestep_syscall =
|
||||
is_syscall(PT_REGS_IP(¤t->thread.regs));
|
||||
|
||||
/* if there's no signal to deliver, we just put the saved sigmask
|
||||
* back */
|
||||
if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
return(handled_sig);
|
||||
}
|
||||
|
||||
int do_signal(void)
|
||||
{
|
||||
return(kern_do_signal(¤t->thread.regs, ¤t->blocked));
|
||||
return(kern_do_signal(¤t->thread.regs));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -150,63 +172,20 @@ int do_signal(void)
|
||||
*/
|
||||
long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||
{
|
||||
sigset_t saveset;
|
||||
|
||||
mask &= _BLOCKABLE;
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->saved_sigmask = current->blocked;
|
||||
siginitset(¤t->blocked, mask);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR;
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if(kern_do_signal(¤t->thread.regs, &saveset))
|
||||
return(-EINTR);
|
||||
}
|
||||
}
|
||||
|
||||
long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
|
||||
{
|
||||
sigset_t saveset, newset;
|
||||
|
||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
||||
return -EFAULT;
|
||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->blocked = newset;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR;
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (kern_do_signal(¤t->thread.regs, &saveset))
|
||||
return(-EINTR);
|
||||
}
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
|
||||
{
|
||||
return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
|
@ -1,12 +1,12 @@
|
||||
#
|
||||
#
|
||||
# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
|
||||
# Licensed under the GPL
|
||||
#
|
||||
|
||||
obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
|
||||
obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
|
||||
syscall.o tlb.o uaccess.o
|
||||
|
||||
USER_OBJS := process.o clone.o
|
||||
USER_OBJS := clone.o
|
||||
|
||||
include arch/um/scripts/Makefile.rules
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __SKAS_MMU_H
|
||||
#define __SKAS_MMU_H
|
||||
|
||||
#include "linux/config.h"
|
||||
#include "mm_id.h"
|
||||
#include "asm/ldt.h"
|
||||
|
||||
struct mmu_context_skas {
|
||||
struct mm_id id;
|
||||
unsigned long last_page_table;
|
||||
#ifdef CONFIG_3_LEVEL_PGTABLES
|
||||
unsigned long last_pmd;
|
||||
#endif
|
||||
uml_ldt_t ldt;
|
||||
};
|
||||
|
||||
extern void switch_mm_skas(struct mm_id * mm_idp);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __MODE_SKAS_H__
|
||||
#define __MODE_SKAS_H__
|
||||
|
||||
#include <sysdep/ptrace.h>
|
||||
|
||||
extern unsigned long exec_regs[];
|
||||
extern unsigned long exec_fp_regs[];
|
||||
extern unsigned long exec_fpx_regs[];
|
||||
extern int have_fpx_regs;
|
||||
|
||||
extern void sig_handler_common_skas(int sig, void *sc_ptr);
|
||||
extern void halt_skas(void);
|
||||
extern void reboot_skas(void);
|
||||
extern void kill_off_processes_skas(void);
|
||||
extern int is_skas_winch(int pid, int fd, void *data);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __SKAS_H
|
||||
#define __SKAS_H
|
||||
|
||||
#include "mm_id.h"
|
||||
#include "sysdep/ptrace.h"
|
||||
|
||||
extern int userspace_pid[];
|
||||
extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
|
||||
extern int skas_needs_stub;
|
||||
|
||||
extern void switch_threads(void *me, void *next);
|
||||
extern void thread_wait(void *sw, void *fb);
|
||||
extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
|
||||
void (*handler)(int));
|
||||
extern int start_idle_thread(void *stack, void *switch_buf_ptr,
|
||||
void **fork_buf_ptr);
|
||||
extern int user_thread(unsigned long stack, int flags);
|
||||
extern void userspace(union uml_pt_regs *regs);
|
||||
extern void new_thread_proc(void *stack, void (*handler)(int sig));
|
||||
extern void new_thread_handler(int sig);
|
||||
extern void handle_syscall(union uml_pt_regs *regs);
|
||||
extern int map(struct mm_id * mm_idp, unsigned long virt,
|
||||
unsigned long len, int r, int w, int x, int phys_fd,
|
||||
unsigned long long offset, int done, void **data);
|
||||
extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
|
||||
int done, void **data);
|
||||
extern int protect(struct mm_id * mm_idp, unsigned long addr,
|
||||
unsigned long len, int r, int w, int x, int done,
|
||||
void **data);
|
||||
extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
|
||||
extern int new_mm(int from, unsigned long stack);
|
||||
extern int start_userspace(unsigned long stub_stack);
|
||||
extern int copy_context_skas0(unsigned long stack, int pid);
|
||||
extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
|
||||
extern long execute_syscall_skas(void *r);
|
||||
extern unsigned long current_stub_stack(void);
|
||||
extern long run_syscall_stub(struct mm_id * mm_idp,
|
||||
int syscall, unsigned long *args, long expected,
|
||||
void **addr, int done);
|
||||
extern long syscall_stub_data(struct mm_id * mm_idp,
|
||||
unsigned long *data, int data_count,
|
||||
void **addr, void **stub_addr);
|
||||
|
||||
#endif
|
@ -78,7 +78,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
|
||||
struct mmu_context_skas *from_mm = NULL;
|
||||
struct mmu_context_skas *to_mm = &mm->context.skas;
|
||||
unsigned long stack = 0;
|
||||
int from_fd, ret = -ENOMEM;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
if(skas_needs_stub){
|
||||
stack = get_zeroed_page(GFP_KERNEL);
|
||||
@ -108,11 +108,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
|
||||
from_mm = ¤t->mm->context.skas;
|
||||
|
||||
if(proc_mm){
|
||||
if(from_mm)
|
||||
from_fd = from_mm->id.u.mm_fd;
|
||||
else from_fd = -1;
|
||||
|
||||
ret = new_mm(from_fd, stack);
|
||||
ret = new_mm(stack);
|
||||
if(ret < 0){
|
||||
printk("init_new_context_skas - new_mm failed, "
|
||||
"errno = %d\n", ret);
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <asm/types.h>
|
||||
#include "user.h"
|
||||
#include "ptrace_user.h"
|
||||
#include "time_user.h"
|
||||
#include "sysdep/ptrace.h"
|
||||
#include "user_util.h"
|
||||
#include "kern_util.h"
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
@ -13,14 +13,12 @@
|
||||
#include "asm/uaccess.h"
|
||||
#include "asm/atomic.h"
|
||||
#include "kern_util.h"
|
||||
#include "time_user.h"
|
||||
#include "skas.h"
|
||||
#include "os.h"
|
||||
#include "user_util.h"
|
||||
#include "tlb.h"
|
||||
#include "kern.h"
|
||||
#include "mode.h"
|
||||
#include "proc_mm.h"
|
||||
#include "registers.h"
|
||||
|
||||
void switch_to_skas(void *prev, void *next)
|
||||
@ -34,7 +32,7 @@ void switch_to_skas(void *prev, void *next)
|
||||
if(current->pid == 0)
|
||||
switch_timers(0);
|
||||
|
||||
switch_threads(&from->thread.mode.skas.switch_buf,
|
||||
switch_threads(&from->thread.mode.skas.switch_buf,
|
||||
to->thread.mode.skas.switch_buf);
|
||||
|
||||
if(current->pid == 0)
|
||||
@ -50,8 +48,8 @@ void new_thread_handler(int sig)
|
||||
|
||||
fn = current->thread.request.u.thread.proc;
|
||||
arg = current->thread.request.u.thread.arg;
|
||||
change_sig(SIGUSR1, 1);
|
||||
thread_wait(¤t->thread.mode.skas.switch_buf,
|
||||
os_usr1_signal(1);
|
||||
thread_wait(¤t->thread.mode.skas.switch_buf,
|
||||
current->thread.mode.skas.fork_buf);
|
||||
|
||||
if(current->thread.prev_sched != NULL)
|
||||
@ -82,8 +80,8 @@ void release_thread_skas(struct task_struct *task)
|
||||
|
||||
void fork_handler(int sig)
|
||||
{
|
||||
change_sig(SIGUSR1, 1);
|
||||
thread_wait(¤t->thread.mode.skas.switch_buf,
|
||||
os_usr1_signal(1);
|
||||
thread_wait(¤t->thread.mode.skas.switch_buf,
|
||||
current->thread.mode.skas.fork_buf);
|
||||
|
||||
force_flush_all();
|
||||
@ -93,13 +91,13 @@ void fork_handler(int sig)
|
||||
schedule_tail(current->thread.prev_sched);
|
||||
current->thread.prev_sched = NULL;
|
||||
|
||||
/* Handle any immediate reschedules or signals */
|
||||
/* Handle any immediate reschedules or signals */
|
||||
interrupt_end();
|
||||
userspace(¤t->thread.regs.regs);
|
||||
}
|
||||
|
||||
int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
|
||||
unsigned long stack_top, struct task_struct * p,
|
||||
unsigned long stack_top, struct task_struct * p,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
void (*handler)(int);
|
||||
@ -123,27 +121,14 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
|
||||
return(0);
|
||||
}
|
||||
|
||||
extern void map_stub_pages(int fd, unsigned long code,
|
||||
unsigned long data, unsigned long stack);
|
||||
int new_mm(int from, unsigned long stack)
|
||||
int new_mm(unsigned long stack)
|
||||
{
|
||||
struct proc_mm_op copy;
|
||||
int n, fd;
|
||||
int fd;
|
||||
|
||||
fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
|
||||
if(fd < 0)
|
||||
return(fd);
|
||||
|
||||
if(from != -1){
|
||||
copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
|
||||
.u =
|
||||
{ .copy_segments = from } } );
|
||||
n = os_write_file(fd, ©, sizeof(copy));
|
||||
if(n != sizeof(copy))
|
||||
printk("new_mm : /proc/mm copy_segments failed, "
|
||||
"err = %d\n", -n);
|
||||
}
|
||||
|
||||
if(skas_needs_stub)
|
||||
map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "asm/pgtable.h"
|
||||
#include "asm/uaccess.h"
|
||||
#include "kern_util.h"
|
||||
#include "user_util.h"
|
||||
#include "os.h"
|
||||
|
||||
extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
|
||||
pte_t *pte_out);
|
||||
|
@ -25,12 +25,12 @@ int record_syscall_start(int syscall)
|
||||
syscall_record[index].syscall = syscall;
|
||||
syscall_record[index].pid = current_pid();
|
||||
syscall_record[index].result = 0xdeadbeef;
|
||||
syscall_record[index].start = os_usecs();
|
||||
syscall_record[index].start = os_nsecs();
|
||||
return(index);
|
||||
}
|
||||
|
||||
void record_syscall_end(int index, long result)
|
||||
{
|
||||
syscall_record[index].result = result;
|
||||
syscall_record[index].end = os_usecs();
|
||||
syscall_record[index].end = os_nsecs();
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
@ -13,12 +13,12 @@
|
||||
#include "linux/interrupt.h"
|
||||
#include "linux/init.h"
|
||||
#include "linux/delay.h"
|
||||
#include "linux/hrtimer.h"
|
||||
#include "asm/irq.h"
|
||||
#include "asm/param.h"
|
||||
#include "asm/current.h"
|
||||
#include "kern_util.h"
|
||||
#include "user_util.h"
|
||||
#include "time_user.h"
|
||||
#include "mode.h"
|
||||
#include "os.h"
|
||||
|
||||
@ -39,7 +39,7 @@ unsigned long long sched_clock(void)
|
||||
int timer_irq_inited = 0;
|
||||
|
||||
static int first_tick;
|
||||
static unsigned long long prev_usecs;
|
||||
static unsigned long long prev_nsecs;
|
||||
#ifdef CONFIG_UML_REAL_TIME_CLOCK
|
||||
static long long delta; /* Deviation per interval */
|
||||
#endif
|
||||
@ -58,23 +58,23 @@ void timer_irq(union uml_pt_regs *regs)
|
||||
if(first_tick){
|
||||
#ifdef CONFIG_UML_REAL_TIME_CLOCK
|
||||
/* We've had 1 tick */
|
||||
unsigned long long usecs = os_usecs();
|
||||
unsigned long long nsecs = os_nsecs();
|
||||
|
||||
delta += usecs - prev_usecs;
|
||||
prev_usecs = usecs;
|
||||
delta += nsecs - prev_nsecs;
|
||||
prev_nsecs = nsecs;
|
||||
|
||||
/* Protect against the host clock being set backwards */
|
||||
if(delta < 0)
|
||||
delta = 0;
|
||||
|
||||
ticks += (delta * HZ) / MILLION;
|
||||
delta -= (ticks * MILLION) / HZ;
|
||||
ticks += (delta * HZ) / BILLION;
|
||||
delta -= (ticks * BILLION) / HZ;
|
||||
#else
|
||||
ticks = 1;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
prev_usecs = os_usecs();
|
||||
prev_nsecs = os_nsecs();
|
||||
first_tick = 1;
|
||||
}
|
||||
|
||||
@ -84,49 +84,102 @@ void timer_irq(union uml_pt_regs *regs)
|
||||
}
|
||||
}
|
||||
|
||||
void boot_timer_handler(int sig)
|
||||
void do_boot_timer_handler(struct sigcontext * sc)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
CHOOSE_MODE((void)
|
||||
(UPT_SC(®s.regs) = (struct sigcontext *) (&sig + 1)),
|
||||
CHOOSE_MODE((void) (UPT_SC(®s.regs) = sc),
|
||||
(void) (regs.regs.skas.is_user = 0));
|
||||
do_timer(®s);
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(timer_spinlock);
|
||||
|
||||
static unsigned long long local_offset = 0;
|
||||
|
||||
static inline unsigned long long get_time(void)
|
||||
{
|
||||
unsigned long long nsecs;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&timer_spinlock, flags);
|
||||
nsecs = os_nsecs();
|
||||
nsecs += local_offset;
|
||||
spin_unlock_irqrestore(&timer_spinlock, flags);
|
||||
|
||||
return nsecs;
|
||||
}
|
||||
|
||||
irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long long nsecs;
|
||||
unsigned long flags;
|
||||
|
||||
do_timer(regs);
|
||||
|
||||
write_seqlock_irqsave(&xtime_lock, flags);
|
||||
timer();
|
||||
nsecs = get_time() + local_offset;
|
||||
xtime.tv_sec = nsecs / NSEC_PER_SEC;
|
||||
xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
|
||||
write_sequnlock_irqrestore(&xtime_lock, flags);
|
||||
|
||||
return(IRQ_HANDLED);
|
||||
}
|
||||
|
||||
long um_time(int __user *tloc)
|
||||
{
|
||||
struct timeval now;
|
||||
long ret = get_time() / NSEC_PER_SEC;
|
||||
|
||||
do_gettimeofday(&now);
|
||||
if (tloc) {
|
||||
if (put_user(now.tv_sec, tloc))
|
||||
now.tv_sec = -EFAULT;
|
||||
}
|
||||
return now.tv_sec;
|
||||
if((tloc != NULL) && put_user(ret, tloc))
|
||||
return -EFAULT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void do_gettimeofday(struct timeval *tv)
|
||||
{
|
||||
unsigned long long nsecs = get_time();
|
||||
|
||||
tv->tv_sec = nsecs / NSEC_PER_SEC;
|
||||
/* Careful about calculations here - this was originally done as
|
||||
* (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
|
||||
* which gave bogus (> 1000000) values. Dunno why, suspect gcc
|
||||
* (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
|
||||
* problem that I missed.
|
||||
*/
|
||||
nsecs -= tv->tv_sec * NSEC_PER_SEC;
|
||||
tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
static inline void set_time(unsigned long long nsecs)
|
||||
{
|
||||
unsigned long long now;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&timer_spinlock, flags);
|
||||
now = os_nsecs();
|
||||
local_offset = nsecs - now;
|
||||
spin_unlock_irqrestore(&timer_spinlock, flags);
|
||||
|
||||
clock_was_set();
|
||||
}
|
||||
|
||||
long um_stime(int __user *tptr)
|
||||
{
|
||||
int value;
|
||||
struct timespec new;
|
||||
|
||||
if (get_user(value, tptr))
|
||||
return -EFAULT;
|
||||
new.tv_sec = value;
|
||||
new.tv_nsec = 0;
|
||||
do_settimeofday(&new);
|
||||
|
||||
set_time((unsigned long long) value * NSEC_PER_SEC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_settimeofday(struct timespec *tv)
|
||||
{
|
||||
set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -134,29 +187,15 @@ void timer_handler(int sig, union uml_pt_regs *regs)
|
||||
{
|
||||
local_irq_disable();
|
||||
irq_enter();
|
||||
update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)),
|
||||
(regs)->skas.is_user));
|
||||
update_process_times(CHOOSE_MODE(
|
||||
(UPT_SC(regs) && user_context(UPT_SP(regs))),
|
||||
(regs)->skas.is_user));
|
||||
irq_exit();
|
||||
local_irq_enable();
|
||||
if(current_thread->cpu == 0)
|
||||
timer_irq(regs);
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(timer_spinlock);
|
||||
|
||||
unsigned long time_lock(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&timer_spinlock, flags);
|
||||
return(flags);
|
||||
}
|
||||
|
||||
void time_unlock(unsigned long flags)
|
||||
{
|
||||
spin_unlock_irqrestore(&timer_spinlock, flags);
|
||||
}
|
||||
|
||||
int __init timer_init(void)
|
||||
{
|
||||
int err;
|
||||
@ -171,14 +210,3 @@ int __init timer_init(void)
|
||||
}
|
||||
|
||||
__initcall(timer_init);
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user