Merge branch 'upstream-fixes'

This commit is contained in:
Jeff Garzik 2006-01-26 22:19:57 -05:00
commit 97309d1a0b
346 changed files with 13886 additions and 4676 deletions

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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) {
/*

View File

@ -9,4 +9,4 @@
*/
#define KERN_SIGRETURN_CODE 0xffff0500
extern const unsigned long sigreturn_codes[4];
extern const unsigned long sigreturn_codes[7];

View File

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

View File

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

View File

@ -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[] = {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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(&current->sighand->siglock);
saveset = current->blocked;
current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->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(&current->sighand->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->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(&current->sighand->siglock);
sigorsets(&current->blocked, &current->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 = &current->saved_sigmask;
else
oldset = &current->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, &current->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() */

View File

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

View File

@ -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(&current->sighand->siglock);
saveset = current->blocked;
current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->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(&current->sighand->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
regs.eax = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(&regs, &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(&current->sighand->siglock);
sigorsets(&current->blocked,&current->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 = &current->saved_sigmask;
else
oldset = &current->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, &current->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);
}

View File

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

View File

@ -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(&current->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 */

View File

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

View File

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

View File

@ -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.
*/

View File

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

View File

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

View File

@ -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(&registration->sema) != 0) {
if (mutex_lock_interruptible(&registration->mutex) != 0) {
return xpcInterrupted;
}
/* if XPC_CHANNEL_REGISTERED(ch_number) */
if (registration->func != NULL) {
up(&registration->sema);
mutex_unlock(&registration->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(&registration->sema);
mutex_unlock(&registration->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(&registration->sema);
mutex_lock(&registration->mutex);
/* if !XPC_CHANNEL_REGISTERED(ch_number) */
if (registration->func == NULL) {
up(&registration->sema);
mutex_unlock(&registration->mutex);
return;
}
@ -208,7 +209,7 @@ xpc_disconnect(int ch_number)
xpc_interface.disconnect(ch_number);
up(&registration->sema);
mutex_unlock(&registration->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;

View File

@ -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(&registration->sema) != 0) {
if (mutex_trylock(&registration->mutex) == 0) {
return xpcRetry;
}
if (!XPC_CHANNEL_REGISTERED(ch->number)) {
up(&registration->sema);
mutex_unlock(&registration->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(&registration->sema);
mutex_unlock(&registration->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(&registration->sema);
mutex_unlock(&registration->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(&registration->sema);
mutex_unlock(&registration->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;

View File

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

View File

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

View File

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

View File

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

View File

@ -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(&current->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(&current->sighand->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->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 = &current->saved_sigmask;
else if (!oldset)
oldset = &current->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, &current->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(&current->blocked, signr);
recalc_sigpending();
spin_unlock_irq(&current->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;

View File

@ -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(&current->sighand->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->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 = &current->saved_sigmask;
else if (!oldset)
oldset = &current->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, &current->saved_sigmask, NULL);
}
return 0;
}

View File

@ -321,3 +321,5 @@ SYSCALL(inotify_add_watch)
SYSCALL(inotify_rm_watch)
SYSCALL(spu_run)
SYSCALL(spu_create)
COMPAT_SYS(pselect6)
COMPAT_SYS(ppoll)

View File

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

View File

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

View File

@ -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(&current->sighand->siglock);
saveset = current->blocked;
current->saved_sigmask = current->blocked;
siginitset(&current->blocked, set);
recalc_sigpending();
spin_unlock_irq(&current->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(&current->sighand->siglock);
oldset = current->blocked;
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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 = &current->saved_sigmask;
else
oldset = &current->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, &current->saved_sigmask, NULL);
}
}
asmlinkage int

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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(&current->sighand->siglock);
saveset = current->blocked;
current->saved_sigmask = current->blocked;
siginitset(&current->blocked, set);
recalc_sigpending();
spin_unlock_irq(&current->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(&current->sighand->siglock);
oldset = current->blocked;
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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 = &current->saved_sigmask;
else
oldset = &current->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, &current->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)

View File

@ -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(&current->sighand->siglock);
saveset = current->blocked;
siginitset(&current->blocked, set);
recalc_sigpending();
spin_unlock_irq(&current->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(&current->sighand->siglock);
oldset = current->blocked;
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, &current->saved_sigmask, NULL);
}
}
struct sigstack32 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,6 +11,7 @@
#include "user.h"
#include "user_util.h"
#include "chan_user.h"
#include "os.h"
struct fd_chan {
int fd;

View File

@ -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(&uml_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

View File

@ -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, &sectorsize, &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,

View File

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

View File

@ -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:
*/

View File

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

View 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

View 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

View File

@ -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:
*/

View File

@ -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:
*/

View 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

View File

@ -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:
*/

View File

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

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and
* Lars Brinkhoff.
* Licensed under the GPL

View 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

View 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

View 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

View File

@ -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:
*/

View File

@ -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:
*/

View File

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

View File

@ -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:
*/

View File

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

View File

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

View File

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

View File

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

View File

@ -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 = &current->saved_sigmask;
else
oldset = &current->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(&current->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, &current->saved_sigmask, NULL);
}
return(handled_sig);
}
int do_signal(void)
{
return(kern_do_signal(&current->thread.regs, &current->blocked));
return(kern_do_signal(&current->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(&current->sighand->siglock);
saveset = current->blocked;
current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if(kern_do_signal(&current->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(&current->sighand->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (kern_do_signal(&current->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(&current->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:
*/

View File

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

View File

@ -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:
*/

View File

@ -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:
*/

View File

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

View File

@ -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 = &current->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);

View File

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

View File

@ -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(&current->thread.mode.skas.switch_buf,
os_usr1_signal(1);
thread_wait(&current->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(&current->thread.mode.skas.switch_buf,
os_usr1_signal(1);
thread_wait(&current->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(&current->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, &copy, 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);

View File

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

View File

@ -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();
}

View File

@ -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(&regs.regs) = (struct sigcontext *) (&sig + 1)),
CHOOSE_MODE((void) (UPT_SC(&regs.regs) = sc),
(void) (regs.regs.skas.is_user = 0));
do_timer(&regs);
}
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