提交 4aa96ccf 编写于 作者: R Russell King

Merge branch 'kprobes-thumb' of git://git.yxit.co.uk/linux into devel-stable

......@@ -518,7 +518,7 @@ N: Zach Brown
E: zab@zabbo.net
D: maestro pci sound
M: David Brownell
N: David Brownell
D: Kernel engineer, mentor, and friend. Maintained USB EHCI and
D: gadget layers, SPI subsystem, GPIO subsystem, and more than a few
D: device drivers. His encouragement also helped many engineers get
......
......@@ -2,13 +2,7 @@ Intro
=====
This document is designed to provide a list of the minimum levels of
software necessary to run the 2.6 kernels, as well as provide brief
instructions regarding any other "Gotchas" users may encounter when
trying life on the Bleeding Edge. If upgrading from a pre-2.4.x
kernel, please consult the Changes file included with 2.4.x kernels for
additional information; most of that information will not be repeated
here. Basically, this document assumes that your system is already
functional and running at least 2.4.x kernels.
software necessary to run the 3.0 kernels.
This document is originally based on my "Changes" file for 2.0.x kernels
and therefore owes credit to the same people as that file (Jared Mauch,
......@@ -22,11 +16,10 @@ Upgrade to at *least* these software revisions before thinking you've
encountered a bug! If you're unsure what version you're currently
running, the suggested command should tell you.
Again, keep in mind that this list assumes you are already
functionally running a Linux 2.4 kernel. Also, not all tools are
necessary on all systems; obviously, if you don't have any ISDN
hardware, for example, you probably needn't concern yourself with
isdn4k-utils.
Again, keep in mind that this list assumes you are already functionally
running a Linux kernel. Also, not all tools are necessary on all
systems; obviously, if you don't have any ISDN hardware, for example,
you probably needn't concern yourself with isdn4k-utils.
o Gnu C 3.2 # gcc --version
o Gnu make 3.80 # make --version
......@@ -114,12 +107,12 @@ Ksymoops
If the unthinkable happens and your kernel oopses, you may need the
ksymoops tool to decode it, but in most cases you don't.
In the 2.6 kernel it is generally preferred to build the kernel with
CONFIG_KALLSYMS so that it produces readable dumps that can be used as-is
(this also produces better output than ksymoops).
If for some reason your kernel is not build with CONFIG_KALLSYMS and
you have no way to rebuild and reproduce the Oops with that option, then
you can still decode that Oops with ksymoops.
It is generally preferred to build the kernel with CONFIG_KALLSYMS so
that it produces readable dumps that can be used as-is (this also
produces better output than ksymoops). If for some reason your kernel
is not build with CONFIG_KALLSYMS and you have no way to rebuild and
reproduce the Oops with that option, then you can still decode that Oops
with ksymoops.
Module-Init-Tools
-----------------
......@@ -261,8 +254,8 @@ needs to be recompiled or (preferably) upgraded.
NFS-utils
---------
In 2.4 and earlier kernels, the nfs server needed to know about any
client that expected to be able to access files via NFS. This
In ancient (2.4 and earlier) kernels, the nfs server needed to know
about any client that expected to be able to access files via NFS. This
information would be given to the kernel by "mountd" when the client
mounted the filesystem, or by "exportfs" at system startup. exportfs
would take information about active clients from /var/lib/nfs/rmtab.
......@@ -272,11 +265,11 @@ which is not always easy, particularly when trying to implement
fail-over. Even when the system is working well, rmtab suffers from
getting lots of old entries that never get removed.
With 2.6 we have the option of having the kernel tell mountd when it
gets a request from an unknown host, and mountd can give appropriate
export information to the kernel. This removes the dependency on
rmtab and means that the kernel only needs to know about currently
active clients.
With modern kernels we have the option of having the kernel tell mountd
when it gets a request from an unknown host, and mountd can give
appropriate export information to the kernel. This removes the
dependency on rmtab and means that the kernel only needs to know about
currently active clients.
To enable this new functionality, you need to:
......
......@@ -680,8 +680,8 @@ ones already enabled by DEBUG.
Chapter 14: Allocating memory
The kernel provides the following general purpose memory allocators:
kmalloc(), kzalloc(), kcalloc(), and vmalloc(). Please refer to the API
documentation for further information about them.
kmalloc(), kzalloc(), kcalloc(), vmalloc(), and vzalloc(). Please refer to
the API documentation for further information about them.
The preferred form for passing a size of a struct is the following:
......
......@@ -77,7 +77,7 @@ Throttling/Upper Limit policy
- Specify a bandwidth rate on particular device for root group. The format
for policy is "<major>:<minor> <byes_per_second>".
echo "8:16 1048576" > /sys/fs/cgroup/blkio/blkio.read_bps_device
echo "8:16 1048576" > /sys/fs/cgroup/blkio/blkio.throttle.read_bps_device
Above will put a limit of 1MB/second on reads happening for root group
on device having major/minor number 8:16.
......@@ -90,7 +90,7 @@ Throttling/Upper Limit policy
1024+0 records out
4194304 bytes (4.2 MB) copied, 4.0001 s, 1.0 MB/s
Limits for writes can be put using blkio.write_bps_device file.
Limits for writes can be put using blkio.throttle.write_bps_device file.
Hierarchical Cgroups
====================
......@@ -286,28 +286,28 @@ Throttling/Upper limit policy files
specified in bytes per second. Rules are per deivce. Following is
the format.
echo "<major>:<minor> <rate_bytes_per_second>" > /cgrp/blkio.read_bps_device
echo "<major>:<minor> <rate_bytes_per_second>" > /cgrp/blkio.throttle.read_bps_device
- blkio.throttle.write_bps_device
- Specifies upper limit on WRITE rate to the device. IO rate is
specified in bytes per second. Rules are per deivce. Following is
the format.
echo "<major>:<minor> <rate_bytes_per_second>" > /cgrp/blkio.write_bps_device
echo "<major>:<minor> <rate_bytes_per_second>" > /cgrp/blkio.throttle.write_bps_device
- blkio.throttle.read_iops_device
- Specifies upper limit on READ rate from the device. IO rate is
specified in IO per second. Rules are per deivce. Following is
the format.
echo "<major>:<minor> <rate_io_per_second>" > /cgrp/blkio.read_iops_device
echo "<major>:<minor> <rate_io_per_second>" > /cgrp/blkio.throttle.read_iops_device
- blkio.throttle.write_iops_device
- Specifies upper limit on WRITE rate to the device. IO rate is
specified in io per second. Rules are per deivce. Following is
the format.
echo "<major>:<minor> <rate_io_per_second>" > /cgrp/blkio.write_iops_device
echo "<major>:<minor> <rate_io_per_second>" > /cgrp/blkio.throttle.write_iops_device
Note: If both BW and IOPS rules are specified for a device, then IO is
subjectd to both the constraints.
......
......@@ -583,3 +583,25 @@ Why: Superseded by the UVCIOC_CTRL_QUERY ioctl.
Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----------------------------
What: For VIDIOC_S_FREQUENCY the type field must match the device node's type.
If not, return -EINVAL.
When: 3.2
Why: It makes no sense to switch the tuner to radio mode by calling
VIDIOC_S_FREQUENCY on a video node, or to switch the tuner to tv mode by
calling VIDIOC_S_FREQUENCY on a radio node. This is the first step of a
move to more consistent handling of tv and radio tuners.
Who: Hans Verkuil <hans.verkuil@cisco.com>
----------------------------
What: Opening a radio device node will no longer automatically switch the
tuner mode from tv to radio.
When: 3.3
Why: Just opening a V4L device should not change the state of the hardware
like that. It's very unexpected and against the V4L spec. Instead, you
switch to radio mode by calling VIDIOC_S_FREQUENCY. This is the second
and last step of the move to consistent handling of tv and radio tuners.
Who: Hans Verkuil <hans.verkuil@cisco.com>
----------------------------
......@@ -673,6 +673,22 @@ storage request to complete, or it may attempt to cancel the storage request -
in which case the page will not be stored in the cache this time.
BULK INODE PAGE UNCACHE
-----------------------
A convenience routine is provided to perform an uncache on all the pages
attached to an inode. This assumes that the pages on the inode correspond on a
1:1 basis with the pages in the cache.
void fscache_uncache_all_inode_pages(struct fscache_cookie *cookie,
struct inode *inode);
This takes the netfs cookie that the pages were cached with and the inode that
the pages are attached to. This function will wait for pages to finish being
written to the cache and for the cache to finish with the page generally. No
error is returned.
==========================
INDEX AND DATA FILE UPDATE
==========================
......
......@@ -22,6 +22,10 @@ Supported chips:
Prefix: 'f71869'
Addresses scanned: none, address read from Super I/O config space
Datasheet: Available from the Fintek website
* Fintek F71869A
Prefix: 'f71869a'
Addresses scanned: none, address read from Super I/O config space
Datasheet: Not public
* Fintek F71882FG and F71883FG
Prefix: 'f71882fg'
Addresses scanned: none, address read from Super I/O config space
......
......@@ -9,8 +9,8 @@ Supported chips:
Socket S1G3: Athlon II, Sempron, Turion II
* AMD Family 11h processors:
Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra)
* AMD Family 12h processors: "Llano"
* AMD Family 14h processors: "Brazos" (C/E/G-Series)
* AMD Family 12h processors: "Llano" (E2/A4/A6/A8-Series)
* AMD Family 14h processors: "Brazos" (C/E/G/Z-Series)
* AMD Family 15h processors: "Bulldozer"
Prefix: 'k10temp'
......@@ -20,12 +20,16 @@ Supported chips:
http://support.amd.com/us/Processor_TechDocs/31116.pdf
BIOS and Kernel Developer's Guide (BKDG) for AMD Family 11h Processors:
http://support.amd.com/us/Processor_TechDocs/41256.pdf
BIOS and Kernel Developer's Guide (BKDG) for AMD Family 12h Processors:
http://support.amd.com/us/Processor_TechDocs/41131.pdf
BIOS and Kernel Developer's Guide (BKDG) for AMD Family 14h Models 00h-0Fh Processors:
http://support.amd.com/us/Processor_TechDocs/43170.pdf
Revision Guide for AMD Family 10h Processors:
http://support.amd.com/us/Processor_TechDocs/41322.pdf
Revision Guide for AMD Family 11h Processors:
http://support.amd.com/us/Processor_TechDocs/41788.pdf
Revision Guide for AMD Family 12h Processors:
http://support.amd.com/us/Processor_TechDocs/44739.pdf
Revision Guide for AMD Family 14h Models 00h-0Fh Processors:
http://support.amd.com/us/Processor_TechDocs/47534.pdf
AMD Family 11h Processor Power and Thermal Data Sheet for Notebooks:
......
......@@ -2015,6 +2015,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
the default.
off: Turn ECRC off
on: Turn ECRC on.
realloc reallocate PCI resources if allocations done by BIOS
are erroneous.
pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power
Management.
......
......@@ -534,6 +534,8 @@ Events that are never propagated by the driver:
0x2404 System is waking up from hibernation to undock
0x2405 System is waking up from hibernation to eject bay
0x5010 Brightness level changed/control event
0x6000 KEYBOARD: Numlock key pressed
0x6005 KEYBOARD: Fn key pressed (TO BE VERIFIED)
Events that are propagated by the driver to userspace:
......@@ -545,6 +547,8 @@ Events that are propagated by the driver to userspace:
0x3006 Bay hotplug request (hint to power up SATA link when
the optical drive tray is ejected)
0x4003 Undocked (see 0x2x04), can sleep again
0x4010 Docked into hotplug port replicator (non-ACPI dock)
0x4011 Undocked from hotplug port replicator (non-ACPI dock)
0x500B Tablet pen inserted into its storage bay
0x500C Tablet pen removed from its storage bay
0x6011 ALARM: battery is too hot
......@@ -552,6 +556,7 @@ Events that are propagated by the driver to userspace:
0x6021 ALARM: a sensor is too hot
0x6022 ALARM: a sensor is extremely hot
0x6030 System thermal table changed
0x6040 Nvidia Optimus/AC adapter related (TO BE VERIFIED)
Battery nearly empty alarms are a last resort attempt to get the
operating system to hibernate or shutdown cleanly (0x2313), or shutdown
......
......@@ -501,13 +501,29 @@ helper functions described in Section 4. In that case, pm_runtime_resume()
should be used. Of course, for this purpose the device's run-time PM has to be
enabled earlier by calling pm_runtime_enable().
If the device bus type's or driver's ->probe() or ->remove() callback runs
If the device bus type's or driver's ->probe() callback runs
pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
they will fail returning -EAGAIN, because the device's usage counter is
incremented by the core before executing ->probe() and ->remove(). Still, it
may be desirable to suspend the device as soon as ->probe() or ->remove() has
finished, so the PM core uses pm_runtime_idle_sync() to invoke the
subsystem-level idle callback for the device at that time.
incremented by the driver core before executing ->probe(). Still, it may be
desirable to suspend the device as soon as ->probe() has finished, so the driver
core uses pm_runtime_put_sync() to invoke the subsystem-level idle callback for
the device at that time.
Moreover, the driver core prevents runtime PM callbacks from racing with the bus
notifier callback in __device_release_driver(), which is necessary, because the
notifier is used by some subsystems to carry out operations affecting the
runtime PM functionality. It does so by calling pm_runtime_get_sync() before
driver_sysfs_remove() and the BUS_NOTIFY_UNBIND_DRIVER notifications. This
resumes the device if it's in the suspended state and prevents it from
being suspended again while those routines are being executed.
To allow bus types and drivers to put devices into the suspended state by
calling pm_runtime_suspend() from their ->remove() routines, the driver core
executes pm_runtime_put_sync() after running the BUS_NOTIFY_UNBIND_DRIVER
notifications in __device_release_driver(). This requires bus types and
drivers to make their ->remove() callbacks avoid races with runtime PM directly,
but also it allows of more flexibility in the handling of devices during the
removal of their drivers.
The user space can effectively disallow the driver of the device to power manage
it at run time by changing the value of its /sys/devices/.../power/control
......
......@@ -13,18 +13,8 @@ static DEFINE_SPINLOCK(xxx_lock);
The above is always safe. It will disable interrupts _locally_, but the
spinlock itself will guarantee the global lock, so it will guarantee that
there is only one thread-of-control within the region(s) protected by that
lock. This works well even under UP. The above sequence under UP
essentially is just the same as doing
unsigned long flags;
save_flags(flags); cli();
... critical section ...
restore_flags(flags);
so the code does _not_ need to worry about UP vs SMP issues: the spinlocks
work correctly under both (and spinlocks are actually more efficient on
architectures that allow doing the "save_flags + cli" in one operation).
lock. This works well even under UP also, so the code does _not_ need to
worry about UP vs SMP issues: the spinlocks work correctly under both.
NOTE! Implications of spin_locks for memory are further described in:
......@@ -36,27 +26,7 @@ The above is usually pretty simple (you usually need and want only one
spinlock for most things - using more than one spinlock can make things a
lot more complex and even slower and is usually worth it only for
sequences that you _know_ need to be split up: avoid it at all cost if you
aren't sure). HOWEVER, it _does_ mean that if you have some code that does
cli();
.. critical section ..
sti();
and another sequence that does
spin_lock_irqsave(flags);
.. critical section ..
spin_unlock_irqrestore(flags);
then they are NOT mutually exclusive, and the critical regions can happen
at the same time on two different CPU's. That's fine per se, but the
critical regions had better be critical for different things (ie they
can't stomp on each other).
The above is a problem mainly if you end up mixing code - for example the
routines in ll_rw_block() tend to use cli/sti to protect the atomicity of
their actions, and if a driver uses spinlocks instead then you should
think about issues like the above.
aren't sure).
This is really the only really hard part about spinlocks: once you start
using spinlocks they tend to expand to areas you might not have noticed
......@@ -120,11 +90,10 @@ Lesson 3: spinlocks revisited.
The single spin-lock primitives above are by no means the only ones. They
are the most safe ones, and the ones that work under all circumstances,
but partly _because_ they are safe they are also fairly slow. They are
much faster than a generic global cli/sti pair, but slower than they'd
need to be, because they do have to disable interrupts (which is just a
single instruction on a x86, but it's an expensive one - and on other
architectures it can be worse).
but partly _because_ they are safe they are also fairly slow. They are slower
than they'd need to be, because they do have to disable interrupts
(which is just a single instruction on a x86, but it's an expensive one -
and on other architectures it can be worse).
If you have a case where you have to protect a data structure across
several CPU's and you want to use spinlocks you can potentially use
......
......@@ -76,6 +76,13 @@ A transfer's actual_length may be positive even when an error has been
reported. That's because transfers often involve several packets, so that
one or more packets could finish before an error stops further endpoint I/O.
For isochronous URBs, the urb status value is non-zero only if the URB is
unlinked, the device is removed, the host controller is disabled, or the total
transferred length is less than the requested length and the URB_SHORT_NOT_OK
flag is set. Completion handlers for isochronous URBs should only see
urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO.
Individual frame descriptor status fields may report more status codes.
0 Transfer completed successfully
......@@ -132,7 +139,7 @@ one or more packets could finish before an error stops further endpoint I/O.
device removal events immediately.
-EXDEV ISO transfer only partially completed
look at individual frame status for details
(only set in iso_frame_desc[n].status, not urb->status)
-EINVAL ISO madness, if this happens: Log off and go home
......
......@@ -594,6 +594,16 @@ S: Maintained
F: arch/arm/lib/floppydma.S
F: arch/arm/include/asm/floppy.h
ARM PMU PROFILING AND DEBUGGING
M: Will Deacon <will.deacon@arm.com>
S: Maintained
F: arch/arm/kernel/perf_event*
F: arch/arm/oprofile/common.c
F: arch/arm/kernel/pmu.c
F: arch/arm/include/asm/pmu.h
F: arch/arm/kernel/hw_breakpoint.c
F: arch/arm/include/asm/hw_breakpoint.h
ARM PORT
M: Russell King <linux@arm.linux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
......@@ -1345,16 +1355,18 @@ F: drivers/auxdisplay/
F: include/linux/cfag12864b.h
AVR32 ARCHITECTURE
M: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>
M: Haavard Skinnemoen <hskinnemoen@gmail.com>
M: Hans-Christian Egtvedt <egtvedt@samfundet.no>
W: http://www.atmel.com/products/AVR32/
W: http://avr32linux.org/
W: http://avrfreaks.net/
S: Supported
S: Maintained
F: arch/avr32/
AVR32/AT32AP MACHINE SUPPORT
M: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>
S: Supported
M: Haavard Skinnemoen <hskinnemoen@gmail.com>
M: Hans-Christian Egtvedt <egtvedt@samfundet.no>
S: Maintained
F: arch/avr32/mach-at32ap/
AX.25 NETWORK LAYER
......@@ -1390,7 +1402,6 @@ F: include/linux/backlight.h
BATMAN ADVANCED
M: Marek Lindner <lindner_marek@yahoo.de>
M: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
M: Sven Eckelmann <sven@narfation.org>
L: b.a.t.m.a.n@lists.open-mesh.org
W: http://www.open-mesh.org/
S: Maintained
......@@ -1423,7 +1434,6 @@ S: Supported
F: arch/blackfin/
BLACKFIN EMAC DRIVER
M: Michael Hennerich <michael.hennerich@analog.com>
L: uclinux-dist-devel@blackfin.uclinux.org
W: http://blackfin.uclinux.org
S: Supported
......@@ -1639,7 +1649,7 @@ CAN NETWORK LAYER
M: Oliver Hartkopp <socketcan@hartkopp.net>
M: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
M: Urs Thuermann <urs.thuermann@volkswagen.de>
L: socketcan-core@lists.berlios.de
L: socketcan-core@lists.berlios.de (subscribers-only)
L: netdev@vger.kernel.org
W: http://developer.berlios.de/projects/socketcan/
S: Maintained
......@@ -1651,7 +1661,7 @@ F: include/linux/can/raw.h
CAN NETWORK DRIVERS
M: Wolfgang Grandegger <wg@grandegger.com>
L: socketcan-core@lists.berlios.de
L: socketcan-core@lists.berlios.de (subscribers-only)
L: netdev@vger.kernel.org
W: http://developer.berlios.de/projects/socketcan/
S: Maintained
......@@ -2197,7 +2207,7 @@ F: drivers/acpi/dock.c
DOCUMENTATION
M: Randy Dunlap <rdunlap@xenotime.net>
L: linux-doc@vger.kernel.org
T: quilt oss.oracle.com/~rdunlap/kernel-doc-patches/current/
T: quilt http://userweb.kernel.org/~rdunlap/kernel-doc-patches/current/
S: Maintained
F: Documentation/
......@@ -4982,7 +4992,7 @@ F: drivers/power/power_supply*
PNP SUPPORT
M: Adam Belay <abelay@mit.edu>
M: Bjorn Helgaas <bjorn.helgaas@hp.com>
M: Bjorn Helgaas <bhelgaas@google.com>
S: Maintained
F: drivers/pnp/
......@@ -5181,6 +5191,7 @@ S: Supported
F: drivers/net/qlcnic/
QLOGIC QLGE 10Gb ETHERNET DRIVER
M: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
M: Ron Mercer <ron.mercer@qlogic.com>
M: linux-driver@qlogic.com
L: netdev@vger.kernel.org
......@@ -6434,8 +6445,9 @@ S: Maintained
F: drivers/usb/misc/rio500*
USB EHCI DRIVER
M: Alan Stern <stern@rowland.harvard.edu>
L: linux-usb@vger.kernel.org
S: Orphan
S: Maintained
F: Documentation/usb/ehci.txt
F: drivers/usb/host/ehci*
......@@ -6465,6 +6477,12 @@ S: Maintained
F: Documentation/hid/hiddev.txt
F: drivers/hid/usbhid/
USB/IP DRIVERS
M: Matt Mooney <mfm@muteddisk.com>
L: linux-usb@vger.kernel.org
S: Maintained
F: drivers/staging/usbip/
USB ISP116X DRIVER
M: Olav Kongas <ok@artecdesign.ee>
L: linux-usb@vger.kernel.org
......@@ -6494,8 +6512,9 @@ S: Maintained
F: sound/usb/midi.*
USB OHCI DRIVER
M: Alan Stern <stern@rowland.harvard.edu>
L: linux-usb@vger.kernel.org
S: Orphan
S: Maintained
F: Documentation/usb/ohci.txt
F: drivers/usb/host/ohci*
......@@ -6724,6 +6743,7 @@ F: fs/fat/
VIDEOBUF2 FRAMEWORK
M: Pawel Osciak <pawel@osciak.com>
M: Marek Szyprowski <m.szyprowski@samsung.com>
M: Kyungmin Park <kyungmin.park@samsung.com>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/video/videobuf2-*
......
VERSION = 3
PATCHLEVEL = 0
SUBLEVEL = 0
EXTRAVERSION = -rc5
EXTRAVERSION = -rc7
NAME = Sneaky Weasel
# *DOCUMENTATION*
......
Linux kernel release 2.6.xx <http://kernel.org/>
Linux kernel release 3.x <http://kernel.org/>
These are the release notes for Linux version 2.6. Read them carefully,
These are the release notes for Linux version 3. Read them carefully,
as they tell you what this is all about, explain how to install the
kernel, and what to do if something goes wrong.
......@@ -62,10 +62,10 @@ INSTALLING the kernel source:
directory where you have permissions (eg. your home directory) and
unpack it:
gzip -cd linux-2.6.XX.tar.gz | tar xvf -
gzip -cd linux-3.X.tar.gz | tar xvf -
or
bzip2 -dc linux-2.6.XX.tar.bz2 | tar xvf -
bzip2 -dc linux-3.X.tar.bz2 | tar xvf -
Replace "XX" with the version number of the latest kernel.
......@@ -75,15 +75,15 @@ INSTALLING the kernel source:
files. They should match the library, and not get messed up by
whatever the kernel-du-jour happens to be.
- You can also upgrade between 2.6.xx releases by patching. Patches are
- You can also upgrade between 3.x releases by patching. Patches are
distributed in the traditional gzip and the newer bzip2 format. To
install by patching, get all the newer patch files, enter the
top level directory of the kernel source (linux-2.6.xx) and execute:
top level directory of the kernel source (linux-3.x) and execute:
gzip -cd ../patch-2.6.xx.gz | patch -p1
gzip -cd ../patch-3.x.gz | patch -p1
or
bzip2 -dc ../patch-2.6.xx.bz2 | patch -p1
bzip2 -dc ../patch-3.x.bz2 | patch -p1
(repeat xx for all versions bigger than the version of your current
source tree, _in_order_) and you should be ok. You may want to remove
......@@ -91,9 +91,9 @@ INSTALLING the kernel source:
failed patches (xxx# or xxx.rej). If there are, either you or me has
made a mistake.
Unlike patches for the 2.6.x kernels, patches for the 2.6.x.y kernels
Unlike patches for the 3.x kernels, patches for the 3.x.y kernels
(also known as the -stable kernels) are not incremental but instead apply
directly to the base 2.6.x kernel. Please read
directly to the base 3.x kernel. Please read
Documentation/applying-patches.txt for more information.
Alternatively, the script patch-kernel can be used to automate this
......@@ -107,14 +107,14 @@ INSTALLING the kernel source:
an alternative directory can be specified as the second argument.
- If you are upgrading between releases using the stable series patches
(for example, patch-2.6.xx.y), note that these "dot-releases" are
not incremental and must be applied to the 2.6.xx base tree. For
example, if your base kernel is 2.6.12 and you want to apply the
2.6.12.3 patch, you do not and indeed must not first apply the
2.6.12.1 and 2.6.12.2 patches. Similarly, if you are running kernel
version 2.6.12.2 and want to jump to 2.6.12.3, you must first
reverse the 2.6.12.2 patch (that is, patch -R) _before_ applying
the 2.6.12.3 patch.
(for example, patch-3.x.y), note that these "dot-releases" are
not incremental and must be applied to the 3.x base tree. For
example, if your base kernel is 3.0 and you want to apply the
3.0.3 patch, you do not and indeed must not first apply the
3.0.1 and 3.0.2 patches. Similarly, if you are running kernel
version 3.0.2 and want to jump to 3.0.3, you must first
reverse the 3.0.2 patch (that is, patch -R) _before_ applying
the 3.0.3 patch.
You can read more on this in Documentation/applying-patches.txt
- Make sure you have no stale .o files and dependencies lying around:
......@@ -126,7 +126,7 @@ INSTALLING the kernel source:
SOFTWARE REQUIREMENTS
Compiling and running the 2.6.xx kernels requires up-to-date
Compiling and running the 3.x kernels requires up-to-date
versions of various software packages. Consult
Documentation/Changes for the minimum version numbers required
and how to get updates for these packages. Beware that using
......@@ -142,11 +142,11 @@ BUILD directory for the kernel:
Using the option "make O=output/dir" allow you to specify an alternate
place for the output files (including .config).
Example:
kernel source code: /usr/src/linux-2.6.N
kernel source code: /usr/src/linux-3.N
build directory: /home/name/build/kernel
To configure and build the kernel use:
cd /usr/src/linux-2.6.N
cd /usr/src/linux-3.N
make O=/home/name/build/kernel menuconfig
make O=/home/name/build/kernel
sudo make O=/home/name/build/kernel modules_install install
......
......@@ -10,7 +10,7 @@ config ARM
select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
select HAVE_ARCH_KGDB
select HAVE_KPROBES if (!XIP_KERNEL && !THUMB2_KERNEL)
select HAVE_KPROBES if !XIP_KERNEL
select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
......
......@@ -255,7 +255,7 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
if (buf == 0) {
dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
__func__, ptr);
return 0;
return ~0;
}
dev_dbg(dev,
......
......@@ -24,12 +24,6 @@
#define MAX_INSN_SIZE 2
#define MAX_STACK_SIZE 64 /* 32 would probably be OK */
/*
* This undefined instruction must be unique and
* reserved solely for kprobes' use.
*/
#define KPROBE_BREAKPOINT_INSTRUCTION 0xe7f001f8
#define regs_return_value(regs) ((regs)->ARM_r0)
#define flush_insn_slot(p) do { } while (0)
#define kretprobe_blacklist_size 0
......@@ -38,14 +32,17 @@ typedef u32 kprobe_opcode_t;
struct kprobe;
typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
typedef unsigned long (kprobe_check_cc)(unsigned long);
typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *);
typedef void (kprobe_insn_fn_t)(void);
/* Architecture specific copy of original instruction. */
struct arch_specific_insn {
kprobe_opcode_t *insn;
kprobe_insn_handler_t *insn_handler;
kprobe_check_cc *insn_check_cc;
kprobe_opcode_t *insn;
kprobe_insn_handler_t *insn_handler;
kprobe_check_cc *insn_check_cc;
kprobe_insn_singlestep_t *insn_singlestep;
kprobe_insn_fn_t *insn_fn;
};
struct prev_kprobe {
......@@ -62,20 +59,9 @@ struct kprobe_ctlblk {
};
void arch_remove_kprobe(struct kprobe *);
void kretprobe_trampoline(void);
int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
enum kprobe_insn {
INSN_REJECTED,
INSN_GOOD,
INSN_GOOD_NO_SLOT
};
enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
struct arch_specific_insn *);
void __init arm_kprobe_decode_init(void);
#endif /* _ARM_KPROBES_H */
......@@ -69,8 +69,9 @@
#define PSR_c 0x000000ff /* Control */
/*
* ARMv7 groups of APSR bits
* ARMv7 groups of PSR bits
*/
#define APSR_MASK 0xf80f0000 /* N, Z, C, V, Q and GE flags */
#define PSR_ISET_MASK 0x01000010 /* ISA state (J, T) mask */
#define PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */
#define PSR_ENDIAN_MASK 0x00000200 /* Endianness state mask */
......@@ -199,6 +200,14 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define predicate(x) ((x) & 0xf0000000)
#define PREDICATE_ALWAYS 0xe0000000
/*
* True if instr is a 32-bit thumb instruction. This works if instr
* is the first or only half-word of a thumb instruction. It also works
* when instr holds all 32-bits of a wide thumb instruction if stored
* in the form (first_half<<16)|(second_half)
*/
#define is_wide_instruction(instr) ((unsigned)(instr) >= 0xe800)
/*
* kprobe-based event tracer support
*/
......
......@@ -37,7 +37,12 @@ obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
obj-$(CONFIG_KPROBES) += kprobes.o kprobes-common.o
ifdef CONFIG_THUMB2_KERNEL
obj-$(CONFIG_KPROBES) += kprobes-thumb.o
else
obj-$(CONFIG_KPROBES) += kprobes-arm.o
endif
obj-$(CONFIG_ATAGS_PROC) += atags.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
......
......@@ -121,15 +121,13 @@
.endm
#else /* CONFIG_THUMB2_KERNEL */
.macro svc_exit, rpsr
ldr lr, [sp, #S_SP] @ top of the stack
ldrd r0, r1, [sp, #S_LR] @ calling lr and pc
clrex @ clear the exclusive monitor
ldr r0, [sp, #S_SP] @ top of the stack
ldr r1, [sp, #S_PC] @ return address
tst r0, #4 @ orig stack 8-byte aligned?
stmdb r0, {r1, \rpsr} @ rfe context
stmdb lr!, {r0, r1, \rpsr} @ calling lr and rfe context
ldmia sp, {r0 - r12}
ldr lr, [sp, #S_LR]
addeq sp, sp, #S_FRAME_SIZE - 8 @ aligned
addne sp, sp, #S_FRAME_SIZE - 4 @ not aligned
mov sp, lr
ldr lr, [sp], #4
rfeia sp!
.endm
......
此差异已折叠。
/*
* arch/arm/kernel/kprobes-common.c
*
* Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
*
* Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is
* Copyright (C) 2006, 2007 Motorola Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include "kprobes.h"
#ifndef find_str_pc_offset
/*
* For STR and STM instructions, an ARM core may choose to use either
* a +8 or a +12 displacement from the current instruction's address.
* Whichever value is chosen for a given core, it must be the same for
* both instructions and may not change. This function measures it.
*/
int str_pc_offset;
void __init find_str_pc_offset(void)
{
int addr, scratch, ret;
__asm__ (
"sub %[ret], pc, #4 \n\t"
"str pc, %[addr] \n\t"
"ldr %[scr], %[addr] \n\t"
"sub %[ret], %[scr], %[ret] \n\t"
: [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
str_pc_offset = ret;
}
#endif /* !find_str_pc_offset */
#ifndef test_load_write_pc_interworking
bool load_write_pc_interworks;
void __init test_load_write_pc_interworking(void)
{
int arch = cpu_architecture();
BUG_ON(arch == CPU_ARCH_UNKNOWN);
load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T;
}
#endif /* !test_load_write_pc_interworking */
#ifndef test_alu_write_pc_interworking
bool alu_write_pc_interworks;
void __init test_alu_write_pc_interworking(void)
{
int arch = cpu_architecture();
BUG_ON(arch == CPU_ARCH_UNKNOWN);
alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7;
}
#endif /* !test_alu_write_pc_interworking */
void __init arm_kprobe_decode_init(void)
{
find_str_pc_offset();
test_load_write_pc_interworking();
test_alu_write_pc_interworking();
}
static unsigned long __kprobes __check_eq(unsigned long cpsr)
{
return cpsr & PSR_Z_BIT;
}
static unsigned long __kprobes __check_ne(unsigned long cpsr)
{
return (~cpsr) & PSR_Z_BIT;
}
static unsigned long __kprobes __check_cs(unsigned long cpsr)
{
return cpsr & PSR_C_BIT;
}
static unsigned long __kprobes __check_cc(unsigned long cpsr)
{
return (~cpsr) & PSR_C_BIT;
}
static unsigned long __kprobes __check_mi(unsigned long cpsr)
{
return cpsr & PSR_N_BIT;
}
static unsigned long __kprobes __check_pl(unsigned long cpsr)
{
return (~cpsr) & PSR_N_BIT;
}
static unsigned long __kprobes __check_vs(unsigned long cpsr)
{
return cpsr & PSR_V_BIT;
}
static unsigned long __kprobes __check_vc(unsigned long cpsr)
{
return (~cpsr) & PSR_V_BIT;
}
static unsigned long __kprobes __check_hi(unsigned long cpsr)
{
cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
return cpsr & PSR_C_BIT;
}
static unsigned long __kprobes __check_ls(unsigned long cpsr)
{
cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
return (~cpsr) & PSR_C_BIT;
}
static unsigned long __kprobes __check_ge(unsigned long cpsr)
{
cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
return (~cpsr) & PSR_N_BIT;
}
static unsigned long __kprobes __check_lt(unsigned long cpsr)
{
cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
return cpsr & PSR_N_BIT;
}
static unsigned long __kprobes __check_gt(unsigned long cpsr)
{
unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
return (~temp) & PSR_N_BIT;
}
static unsigned long __kprobes __check_le(unsigned long cpsr)
{
unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
return temp & PSR_N_BIT;
}
static unsigned long __kprobes __check_al(unsigned long cpsr)
{
return true;
}
kprobe_check_cc * const kprobe_condition_checks[16] = {
&__check_eq, &__check_ne, &__check_cs, &__check_cc,
&__check_mi, &__check_pl, &__check_vs, &__check_vc,
&__check_hi, &__check_ls, &__check_ge, &__check_lt,
&__check_gt, &__check_le, &__check_al, &__check_al
};
void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs)
{
}
void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs)
{
p->ainsn.insn_fn();
}
static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
int rn = (insn >> 16) & 0xf;
int lbit = insn & (1 << 20);
int wbit = insn & (1 << 21);
int ubit = insn & (1 << 23);
int pbit = insn & (1 << 24);
long *addr = (long *)regs->uregs[rn];
int reg_bit_vector;
int reg_count;
reg_count = 0;
reg_bit_vector = insn & 0xffff;
while (reg_bit_vector) {
reg_bit_vector &= (reg_bit_vector - 1);
++reg_count;
}
if (!ubit)
addr -= reg_count;
addr += (!pbit == !ubit);
reg_bit_vector = insn & 0xffff;
while (reg_bit_vector) {
int reg = __ffs(reg_bit_vector);
reg_bit_vector &= (reg_bit_vector - 1);
if (lbit)
regs->uregs[reg] = *addr++;
else
*addr++ = regs->uregs[reg];
}
if (wbit) {
if (!ubit)
addr -= reg_count;
addr -= (!pbit == !ubit);
regs->uregs[rn] = (long)addr;
}
}
static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
{
regs->ARM_pc = (long)p->addr + str_pc_offset;
simulate_ldm1stm1(p, regs);
regs->ARM_pc = (long)p->addr + 4;
}
static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs)
{
simulate_ldm1stm1(p, regs);
load_write_pc(regs->ARM_pc, regs);
}
static void __kprobes
emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs)
{
register void *rregs asm("r1") = regs;
register void *rfn asm("lr") = p->ainsn.insn_fn;
__asm__ __volatile__ (
"stmdb sp!, {%[regs], r11} \n\t"
"ldmia %[regs], {r0-r12} \n\t"
#if __LINUX_ARM_ARCH__ >= 6
"blx %[fn] \n\t"
#else
"str %[fn], [sp, #-4]! \n\t"
"adr lr, 1f \n\t"
"ldr pc, [sp], #4 \n\t"
"1: \n\t"
#endif
"ldr lr, [sp], #4 \n\t" /* lr = regs */
"stmia lr, {r0-r12} \n\t"
"ldr r11, [sp], #4 \n\t"
: [regs] "=r" (rregs), [fn] "=r" (rfn)
: "0" (rregs), "1" (rfn)
: "r0", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r12", "memory", "cc"
);
}
static void __kprobes
emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs)
{
emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2));
}
static void __kprobes
emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs)
{
emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3));
load_write_pc(regs->ARM_pc, regs);
}
enum kprobe_insn __kprobes
kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
kprobe_insn_handler_t *handler = 0;
unsigned reglist = insn & 0xffff;
int is_ldm = insn & 0x100000;
int rn = (insn >> 16) & 0xf;
if (rn <= 12 && (reglist & 0xe000) == 0) {
/* Instruction only uses registers in the range R0..R12 */
handler = emulate_generic_r0_12_noflags;
} else if (rn >= 2 && (reglist & 0x8003) == 0) {
/* Instruction only uses registers in the range R2..R14 */
rn -= 2;
reglist >>= 2;
handler = emulate_generic_r2_14_noflags;
} else if (rn >= 3 && (reglist & 0x0007) == 0) {
/* Instruction only uses registers in the range R3..R15 */
if (is_ldm && (reglist & 0x8000)) {
rn -= 3;
reglist >>= 3;
handler = emulate_ldm_r3_15;
}
}
if (handler) {
/* We can emulate the instruction in (possibly) modified form */
asi->insn[0] = (insn & 0xfff00000) | (rn << 16) | reglist;
asi->insn_handler = handler;
return INSN_GOOD;
}
/* Fallback to slower simulation... */
if (reglist & 0x8000)
handler = is_ldm ? simulate_ldm1_pc : simulate_stm1_pc;
else
handler = simulate_ldm1stm1;
asi->insn_handler = handler;
return INSN_GOOD_NO_SLOT;
}
/*
* Prepare an instruction slot to receive an instruction for emulating.
* This is done by placing a subroutine return after the location where the
* instruction will be placed. We also modify ARM instructions to be
* unconditional as the condition code will already be checked before any
* emulation handler is called.
*/
static kprobe_opcode_t __kprobes
prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
bool thumb)
{
#ifdef CONFIG_THUMB2_KERNEL
if (thumb) {
u16 *thumb_insn = (u16 *)asi->insn;
thumb_insn[1] = 0x4770; /* Thumb bx lr */
thumb_insn[2] = 0x4770; /* Thumb bx lr */
return insn;
}
asi->insn[1] = 0xe12fff1e; /* ARM bx lr */
#else
asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */
#endif
/* Make an ARM instruction unconditional */
if (insn < 0xe0000000)
insn = (insn | 0xe0000000) & ~0x10000000;
return insn;
}
/*
* Write a (probably modified) instruction into the slot previously prepared by
* prepare_emulated_insn
*/
static void __kprobes
set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
bool thumb)
{
#ifdef CONFIG_THUMB2_KERNEL
if (thumb) {
u16 *ip = (u16 *)asi->insn;
if (is_wide_instruction(insn))
*ip++ = insn >> 16;
*ip++ = insn;
return;
}
#endif
asi->insn[0] = insn;
}
/*
* When we modify the register numbers encoded in an instruction to be emulated,
* the new values come from this define. For ARM and 32-bit Thumb instructions
* this gives...
*
* bit position 16 12 8 4 0
* ---------------+---+---+---+---+---+
* register r2 r0 r1 -- r3
*/
#define INSN_NEW_BITS 0x00020103
/* Each nibble has same value as that at INSN_NEW_BITS bit 16 */
#define INSN_SAMEAS16_BITS 0x22222222
/*
* Validate and modify each of the registers encoded in an instruction.
*
* Each nibble in regs contains a value from enum decode_reg_type. For each
* non-zero value, the corresponding nibble in pinsn is validated and modified
* according to the type.
*/
static bool __kprobes decode_regs(kprobe_opcode_t* pinsn, u32 regs)
{
kprobe_opcode_t insn = *pinsn;
kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */
for (; regs != 0; regs >>= 4, mask <<= 4) {
kprobe_opcode_t new_bits = INSN_NEW_BITS;
switch (regs & 0xf) {
case REG_TYPE_NONE:
/* Nibble not a register, skip to next */
continue;
case REG_TYPE_ANY:
/* Any register is allowed */
break;
case REG_TYPE_SAMEAS16:
/* Replace register with same as at bit position 16 */
new_bits = INSN_SAMEAS16_BITS;
break;
case REG_TYPE_SP:
/* Only allow SP (R13) */
if ((insn ^ 0xdddddddd) & mask)
goto reject;
break;
case REG_TYPE_PC:
/* Only allow PC (R15) */
if ((insn ^ 0xffffffff) & mask)
goto reject;
break;
case REG_TYPE_NOSP:
/* Reject SP (R13) */
if (((insn ^ 0xdddddddd) & mask) == 0)
goto reject;
break;
case REG_TYPE_NOSPPC:
case REG_TYPE_NOSPPCX:
/* Reject SP and PC (R13 and R15) */
if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0)
goto reject;
break;
case REG_TYPE_NOPCWB:
if (!is_writeback(insn))
break; /* No writeback, so any register is OK */
/* fall through... */
case REG_TYPE_NOPC:
case REG_TYPE_NOPCX:
/* Reject PC (R15) */
if (((insn ^ 0xffffffff) & mask) == 0)
goto reject;
break;
}
/* Replace value of nibble with new register number... */
insn &= ~mask;
insn |= new_bits & mask;
}
*pinsn = insn;
return true;
reject:
return false;
}
static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
[DECODE_TYPE_TABLE] = sizeof(struct decode_table),
[DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom),
[DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate),
[DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate),
[DECODE_TYPE_OR] = sizeof(struct decode_or),
[DECODE_TYPE_REJECT] = sizeof(struct decode_reject)
};
/*
* kprobe_decode_insn operates on data tables in order to decode an ARM
* architecture instruction onto which a kprobe has been placed.
*
* These instruction decoding tables are a concatenation of entries each
* of which consist of one of the following structs:
*
* decode_table
* decode_custom
* decode_simulate
* decode_emulate
* decode_or
* decode_reject
*
* Each of these starts with a struct decode_header which has the following
* fields:
*
* type_regs
* mask
* value
*
* The least significant DECODE_TYPE_BITS of type_regs contains a value
* from enum decode_type, this indicates which of the decode_* structs
* the entry contains. The value DECODE_TYPE_END indicates the end of the
* table.
*
* When the table is parsed, each entry is checked in turn to see if it
* matches the instruction to be decoded using the test:
*
* (insn & mask) == value
*
* If no match is found before the end of the table is reached then decoding
* fails with INSN_REJECTED.
*
* When a match is found, decode_regs() is called to validate and modify each
* of the registers encoded in the instruction; the data it uses to do this
* is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding
* to fail with INSN_REJECTED.
*
* Once the instruction has passed the above tests, further processing
* depends on the type of the table entry's decode struct.
*
*/
int __kprobes
kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
const union decode_item *table, bool thumb)
{
const struct decode_header *h = (struct decode_header *)table;
const struct decode_header *next;
bool matched = false;
insn = prepare_emulated_insn(insn, asi, thumb);
for (;; h = next) {
enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS;
if (type == DECODE_TYPE_END)
return INSN_REJECTED;
next = (struct decode_header *)
((uintptr_t)h + decode_struct_sizes[type]);
if (!matched && (insn & h->mask.bits) != h->value.bits)
continue;
if (!decode_regs(&insn, regs))
return INSN_REJECTED;
switch (type) {
case DECODE_TYPE_TABLE: {
struct decode_table *d = (struct decode_table *)h;
next = (struct decode_header *)d->table.table;
break;
}
case DECODE_TYPE_CUSTOM: {
struct decode_custom *d = (struct decode_custom *)h;
return (*d->decoder.decoder)(insn, asi);
}
case DECODE_TYPE_SIMULATE: {
struct decode_simulate *d = (struct decode_simulate *)h;
asi->insn_handler = d->handler.handler;
return INSN_GOOD_NO_SLOT;
}
case DECODE_TYPE_EMULATE: {
struct decode_emulate *d = (struct decode_emulate *)h;
asi->insn_handler = d->handler.handler;
set_emulated_insn(insn, asi, thumb);
return INSN_GOOD;
}
case DECODE_TYPE_OR:
matched = true;
break;
case DECODE_TYPE_REJECT:
default:
return INSN_REJECTED;
}
}
}
此差异已折叠。
此差异已折叠。
......@@ -28,14 +28,16 @@
#include <asm/traps.h>
#include <asm/cacheflush.h>
#include "kprobes.h"
#define MIN_STACK_SIZE(addr) \
min((unsigned long)MAX_STACK_SIZE, \
(unsigned long)current_thread_info() + THREAD_START_SP - (addr))
#define flush_insns(addr, cnt) \
#define flush_insns(addr, size) \
flush_icache_range((unsigned long)(addr), \
(unsigned long)(addr) + \
sizeof(kprobe_opcode_t) * (cnt))
(size))
/* Used as a marker in ARM_pc to note when we're in a jprobe. */
#define JPROBE_MAGIC_ADDR 0xffffffff
......@@ -49,16 +51,35 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
kprobe_opcode_t insn;
kprobe_opcode_t tmp_insn[MAX_INSN_SIZE];
unsigned long addr = (unsigned long)p->addr;
bool thumb;
kprobe_decode_insn_t *decode_insn;
int is;
if (addr & 0x3 || in_exception_text(addr))
if (in_exception_text(addr))
return -EINVAL;
#ifdef CONFIG_THUMB2_KERNEL
thumb = true;
addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */
insn = ((u16 *)addr)[0];
if (is_wide_instruction(insn)) {
insn <<= 16;
insn |= ((u16 *)addr)[1];
decode_insn = thumb32_kprobe_decode_insn;
} else
decode_insn = thumb16_kprobe_decode_insn;
#else /* !CONFIG_THUMB2_KERNEL */
thumb = false;
if (addr & 0x3)
return -EINVAL;
insn = *p->addr;
decode_insn = arm_kprobe_decode_insn;
#endif
p->opcode = insn;
p->ainsn.insn = tmp_insn;
switch (arm_kprobe_decode_insn(insn, &p->ainsn)) {
switch ((*decode_insn)(insn, &p->ainsn)) {
case INSN_REJECTED: /* not supported */
return -EINVAL;
......@@ -68,7 +89,10 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
return -ENOMEM;
for (is = 0; is < MAX_INSN_SIZE; ++is)
p->ainsn.insn[is] = tmp_insn[is];
flush_insns(p->ainsn.insn, MAX_INSN_SIZE);
flush_insns(p->ainsn.insn,
sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE);
p->ainsn.insn_fn = (kprobe_insn_fn_t *)
((uintptr_t)p->ainsn.insn | thumb);
break;
case INSN_GOOD_NO_SLOT: /* instruction doesn't need insn slot */
......@@ -79,24 +103,88 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
return 0;
}
#ifdef CONFIG_THUMB2_KERNEL
/*
* For a 32-bit Thumb breakpoint spanning two memory words we need to take
* special precautions to insert the breakpoint atomically, especially on SMP
* systems. This is achieved by calling this arming function using stop_machine.
*/
static int __kprobes set_t32_breakpoint(void *addr)
{
((u16 *)addr)[0] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION >> 16;
((u16 *)addr)[1] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION & 0xffff;
flush_insns(addr, 2*sizeof(u16));
return 0;
}
void __kprobes arch_arm_kprobe(struct kprobe *p)
{
uintptr_t addr = (uintptr_t)p->addr & ~1; /* Remove any Thumb flag */
if (!is_wide_instruction(p->opcode)) {
*(u16 *)addr = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION;
flush_insns(addr, sizeof(u16));
} else if (addr & 2) {
/* A 32-bit instruction spanning two words needs special care */
stop_machine(set_t32_breakpoint, (void *)addr, &cpu_online_map);
} else {
/* Word aligned 32-bit instruction can be written atomically */
u32 bkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION;
#ifndef __ARMEB__ /* Swap halfwords for little-endian */
bkp = (bkp >> 16) | (bkp << 16);
#endif
*(u32 *)addr = bkp;
flush_insns(addr, sizeof(u32));
}
}
#else /* !CONFIG_THUMB2_KERNEL */
void __kprobes arch_arm_kprobe(struct kprobe *p)
{
*p->addr = KPROBE_BREAKPOINT_INSTRUCTION;
flush_insns(p->addr, 1);
kprobe_opcode_t insn = p->opcode;
kprobe_opcode_t brkp = KPROBE_ARM_BREAKPOINT_INSTRUCTION;
if (insn >= 0xe0000000)
brkp |= 0xe0000000; /* Unconditional instruction */
else
brkp |= insn & 0xf0000000; /* Copy condition from insn */
*p->addr = brkp;
flush_insns(p->addr, sizeof(p->addr[0]));
}
#endif /* !CONFIG_THUMB2_KERNEL */
/*
* The actual disarming is done here on each CPU and synchronized using
* stop_machine. This synchronization is necessary on SMP to avoid removing
* a probe between the moment the 'Undefined Instruction' exception is raised
* and the moment the exception handler reads the faulting instruction from
* memory.
* memory. It is also needed to atomically set the two half-words of a 32-bit
* Thumb breakpoint.
*/
int __kprobes __arch_disarm_kprobe(void *p)
{
struct kprobe *kp = p;
#ifdef CONFIG_THUMB2_KERNEL
u16 *addr = (u16 *)((uintptr_t)kp->addr & ~1);
kprobe_opcode_t insn = kp->opcode;
unsigned int len;
if (is_wide_instruction(insn)) {
((u16 *)addr)[0] = insn>>16;
((u16 *)addr)[1] = insn;
len = 2*sizeof(u16);
} else {
((u16 *)addr)[0] = insn;
len = sizeof(u16);
}
flush_insns(addr, len);
#else /* !CONFIG_THUMB2_KERNEL */
*kp->addr = kp->opcode;
flush_insns(kp->addr, 1);
flush_insns(kp->addr, sizeof(kp->addr[0]));
#endif
return 0;
}
......@@ -130,12 +218,24 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
__get_cpu_var(current_kprobe) = p;
}
static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
static void __kprobes
singlestep_skip(struct kprobe *p, struct pt_regs *regs)
{
#ifdef CONFIG_THUMB2_KERNEL
regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
if (is_wide_instruction(p->opcode))
regs->ARM_pc += 4;
else
regs->ARM_pc += 2;
#else
regs->ARM_pc += 4;
if (p->ainsn.insn_check_cc(regs->ARM_cpsr))
p->ainsn.insn_handler(p, regs);
#endif
}
static inline void __kprobes
singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
{
p->ainsn.insn_singlestep(p, regs);
}
/*
......@@ -149,11 +249,23 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p, *cur;
struct kprobe_ctlblk *kcb;
kprobe_opcode_t *addr = (kprobe_opcode_t *)regs->ARM_pc;
kcb = get_kprobe_ctlblk();
cur = kprobe_running();
p = get_kprobe(addr);
#ifdef CONFIG_THUMB2_KERNEL
/*
* First look for a probe which was registered using an address with
* bit 0 set, this is the usual situation for pointers to Thumb code.
* If not found, fallback to looking for one with bit 0 clear.
*/
p = get_kprobe((kprobe_opcode_t *)(regs->ARM_pc | 1));
if (!p)
p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
#else /* ! CONFIG_THUMB2_KERNEL */
p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
#endif
if (p) {
if (cur) {
......@@ -173,7 +285,8 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
/* impossible cases */
BUG();
}
} else {
} else if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) {
/* Probe hit and conditional execution check ok. */
set_current_kprobe(p);
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
......@@ -193,6 +306,13 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
}
reset_current_kprobe();
}
} else {
/*
* Probe hit but conditional execution check failed,
* so just skip the instruction and continue as if
* nothing had happened.
*/
singlestep_skip(p, regs);
}
} else if (cur) {
/* We probably hit a jprobe. Call its break handler. */
......@@ -300,7 +420,11 @@ void __naked __kprobes kretprobe_trampoline(void)
"bl trampoline_handler \n\t"
"mov lr, r0 \n\t"
"ldmia sp!, {r0 - r11} \n\t"
#ifdef CONFIG_THUMB2_KERNEL
"bx lr \n\t"
#else
"mov pc, lr \n\t"
#endif
: : : "memory");
}
......@@ -378,11 +502,22 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
struct jprobe *jp = container_of(p, struct jprobe, kp);
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
long sp_addr = regs->ARM_sp;
long cpsr;
kcb->jprobe_saved_regs = *regs;
memcpy(kcb->jprobes_stack, (void *)sp_addr, MIN_STACK_SIZE(sp_addr));
regs->ARM_pc = (long)jp->entry;
regs->ARM_cpsr |= PSR_I_BIT;
cpsr = regs->ARM_cpsr | PSR_I_BIT;
#ifdef CONFIG_THUMB2_KERNEL
/* Set correct Thumb state in cpsr */
if (regs->ARM_pc & 1)
cpsr |= PSR_T_BIT;
else
cpsr &= ~PSR_T_BIT;
#endif
regs->ARM_cpsr = cpsr;
preempt_disable();
return 1;
}
......@@ -404,7 +539,12 @@ void __kprobes jprobe_return(void)
* This is to prevent any simulated instruction from writing
* over the regs when they are accessing the stack.
*/
#ifdef CONFIG_THUMB2_KERNEL
"sub r0, %0, %1 \n\t"
"mov sp, r0 \n\t"
#else
"sub sp, %0, %1 \n\t"
#endif
"ldr r0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t"
"str %0, [sp, %2] \n\t"
"str r0, [sp, %3] \n\t"
......@@ -415,15 +555,28 @@ void __kprobes jprobe_return(void)
* Return to the context saved by setjmp_pre_handler
* and restored by longjmp_break_handler.
*/
#ifdef CONFIG_THUMB2_KERNEL
"ldr lr, [sp, %2] \n\t" /* lr = saved sp */
"ldrd r0, r1, [sp, %5] \n\t" /* r0,r1 = saved lr,pc */
"ldr r2, [sp, %4] \n\t" /* r2 = saved psr */
"stmdb lr!, {r0, r1, r2} \n\t" /* push saved lr and */
/* rfe context */
"ldmia sp, {r0 - r12} \n\t"
"mov sp, lr \n\t"
"ldr lr, [sp], #4 \n\t"
"rfeia sp! \n\t"
#else
"ldr r0, [sp, %4] \n\t"
"msr cpsr_cxsf, r0 \n\t"
"ldmia sp, {r0 - pc} \n\t"
#endif
:
: "r" (kcb->jprobe_saved_regs.ARM_sp),
"I" (sizeof(struct pt_regs) * 2),
"J" (offsetof(struct pt_regs, ARM_sp)),
"J" (offsetof(struct pt_regs, ARM_pc)),
"J" (offsetof(struct pt_regs, ARM_cpsr))
"J" (offsetof(struct pt_regs, ARM_cpsr)),
"J" (offsetof(struct pt_regs, ARM_lr))
: "memory", "cc");
}
......@@ -460,17 +613,44 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
return 0;
}
static struct undef_hook kprobes_break_hook = {
#ifdef CONFIG_THUMB2_KERNEL
static struct undef_hook kprobes_thumb16_break_hook = {
.instr_mask = 0xffff,
.instr_val = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION,
.cpsr_mask = MODE_MASK,
.cpsr_val = SVC_MODE,
.fn = kprobe_trap_handler,
};
static struct undef_hook kprobes_thumb32_break_hook = {
.instr_mask = 0xffffffff,
.instr_val = KPROBE_BREAKPOINT_INSTRUCTION,
.instr_val = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION,
.cpsr_mask = MODE_MASK,
.cpsr_val = SVC_MODE,
.fn = kprobe_trap_handler,
};
#else /* !CONFIG_THUMB2_KERNEL */
static struct undef_hook kprobes_arm_break_hook = {
.instr_mask = 0x0fffffff,
.instr_val = KPROBE_ARM_BREAKPOINT_INSTRUCTION,
.cpsr_mask = MODE_MASK,
.cpsr_val = SVC_MODE,
.fn = kprobe_trap_handler,
};
#endif /* !CONFIG_THUMB2_KERNEL */
int __init arch_init_kprobes()
{
arm_kprobe_decode_init();
register_undef_hook(&kprobes_break_hook);
#ifdef CONFIG_THUMB2_KERNEL
register_undef_hook(&kprobes_thumb16_break_hook);
register_undef_hook(&kprobes_thumb32_break_hook);
#else
register_undef_hook(&kprobes_arm_break_hook);
#endif
return 0;
}
/*
* arch/arm/kernel/kprobes.h
*
* Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
*
* Some contents moved here from arch/arm/include/asm/kprobes.h which is
* Copyright (C) 2006, 2007 Motorola Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#ifndef _ARM_KERNEL_KPROBES_H
#define _ARM_KERNEL_KPROBES_H
/*
* These undefined instructions must be unique and
* reserved solely for kprobes' use.
*/
#define KPROBE_ARM_BREAKPOINT_INSTRUCTION 0x07f001f8
#define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18
#define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018
enum kprobe_insn {
INSN_REJECTED,
INSN_GOOD,
INSN_GOOD_NO_SLOT
};
typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
struct arch_specific_insn *);
#ifdef CONFIG_THUMB2_KERNEL
enum kprobe_insn thumb16_kprobe_decode_insn(kprobe_opcode_t,
struct arch_specific_insn *);
enum kprobe_insn thumb32_kprobe_decode_insn(kprobe_opcode_t,
struct arch_specific_insn *);
#else /* !CONFIG_THUMB2_KERNEL */
enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
struct arch_specific_insn *);
#endif
void __init arm_kprobe_decode_init(void);
extern kprobe_check_cc * const kprobe_condition_checks[16];
#if __LINUX_ARM_ARCH__ >= 7
/* str_pc_offset is architecturally defined from ARMv7 onwards */
#define str_pc_offset 8
#define find_str_pc_offset()
#else /* __LINUX_ARM_ARCH__ < 7 */
/* We need a run-time check to determine str_pc_offset */
extern int str_pc_offset;
void __init find_str_pc_offset(void);
#endif
/*
* Update ITSTATE after normal execution of an IT block instruction.
*
* The 8 IT state bits are split into two parts in CPSR:
* ITSTATE<1:0> are in CPSR<26:25>
* ITSTATE<7:2> are in CPSR<15:10>
*/
static inline unsigned long it_advance(unsigned long cpsr)
{
if ((cpsr & 0x06000400) == 0) {
/* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */
cpsr &= ~PSR_IT_MASK;
} else {
/* We need to shift left ITSTATE<4:0> */
const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */
unsigned long it = cpsr & mask;
it <<= 1;
it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */
it &= mask;
cpsr &= ~mask;
cpsr |= it;
}
return cpsr;
}
static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs)
{
long cpsr = regs->ARM_cpsr;
if (pcv & 0x1) {
cpsr |= PSR_T_BIT;
pcv &= ~0x1;
} else {
cpsr &= ~PSR_T_BIT;
pcv &= ~0x2; /* Avoid UNPREDICTABLE address allignment */
}
regs->ARM_cpsr = cpsr;
regs->ARM_pc = pcv;
}
#if __LINUX_ARM_ARCH__ >= 6
/* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */
#define load_write_pc_interworks true
#define test_load_write_pc_interworking()
#else /* __LINUX_ARM_ARCH__ < 6 */
/* We need run-time testing to determine if load_write_pc() should interwork. */
extern bool load_write_pc_interworks;
void __init test_load_write_pc_interworking(void);
#endif
static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs)
{
if (load_write_pc_interworks)
bx_write_pc(pcv, regs);
else
regs->ARM_pc = pcv;
}
#if __LINUX_ARM_ARCH__ >= 7
#define alu_write_pc_interworks true
#define test_alu_write_pc_interworking()
#elif __LINUX_ARM_ARCH__ <= 5
/* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */
#define alu_write_pc_interworks false
#define test_alu_write_pc_interworking()
#else /* __LINUX_ARM_ARCH__ == 6 */
/* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */
extern bool alu_write_pc_interworks;
void __init test_alu_write_pc_interworking(void);
#endif /* __LINUX_ARM_ARCH__ == 6 */
static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
{
if (alu_write_pc_interworks)
bx_write_pc(pcv, regs);
else
regs->ARM_pc = pcv;
}
void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
enum kprobe_insn __kprobes
kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi);
/*
* Test if load/store instructions writeback the address register.
* if P (bit 24) == 0 or W (bit 21) == 1
*/
#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
/*
* The following definitions and macros are used to build instruction
* decoding tables for use by kprobe_decode_insn.
*
* These tables are a concatenation of entries each of which consist of one of
* the decode_* structs. All of the fields in every type of decode structure
* are of the union type decode_item, therefore the entire decode table can be
* viewed as an array of these and declared like:
*
* static const union decode_item table_name[] = {};
*
* In order to construct each entry in the table, macros are used to
* initialise a number of sequential decode_item values in a layout which
* matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct
* decode_simulate by initialising four decode_item objects like this...
*
* {.bits = _type},
* {.bits = _mask},
* {.bits = _value},
* {.handler = _handler},
*
* Initialising a specified member of the union means that the compiler
* will produce a warning if the argument is of an incorrect type.
*
* Below is a list of each of the macros used to initialise entries and a
* description of the action performed when that entry is matched to an
* instruction. A match is found when (instruction & mask) == value.
*
* DECODE_TABLE(mask, value, table)
* Instruction decoding jumps to parsing the new sub-table 'table'.
*
* DECODE_CUSTOM(mask, value, decoder)
* The custom function 'decoder' is called to the complete decoding
* of an instruction.
*
* DECODE_SIMULATE(mask, value, handler)
* Set the probes instruction handler to 'handler', this will be used
* to simulate the instruction when the probe is hit. Decoding returns
* with INSN_GOOD_NO_SLOT.
*
* DECODE_EMULATE(mask, value, handler)
* Set the probes instruction handler to 'handler', this will be used
* to emulate the instruction when the probe is hit. The modified
* instruction (see below) is placed in the probes instruction slot so it
* may be called by the emulation code. Decoding returns with INSN_GOOD.
*
* DECODE_REJECT(mask, value)
* Instruction decoding fails with INSN_REJECTED
*
* DECODE_OR(mask, value)
* This allows the mask/value test of multiple table entries to be
* logically ORed. Once an 'or' entry is matched the decoding action to
* be performed is that of the next entry which isn't an 'or'. E.g.
*
* DECODE_OR (mask1, value1)
* DECODE_OR (mask2, value2)
* DECODE_SIMULATE (mask3, value3, simulation_handler)
*
* This means that if any of the three mask/value pairs match the
* instruction being decoded, then 'simulation_handler' will be used
* for it.
*
* Both the SIMULATE and EMULATE macros have a second form which take an
* additional 'regs' argument.
*
* DECODE_SIMULATEX(mask, value, handler, regs)
* DECODE_EMULATEX (mask, value, handler, regs)
*
* These are used to specify what kind of CPU register is encoded in each of the
* least significant 5 nibbles of the instruction being decoded. The regs value
* is specified using the REGS macro, this takes any of the REG_TYPE_* values
* from enum decode_reg_type as arguments; only the '*' part of the name is
* given. E.g.
*
* REGS(0, ANY, NOPC, 0, ANY)
*
* This indicates an instruction is encoded like:
*
* bits 19..16 ignore
* bits 15..12 any register allowed here
* bits 11.. 8 any register except PC allowed here
* bits 7.. 4 ignore
* bits 3.. 0 any register allowed here
*
* This register specification is checked after a decode table entry is found to
* match an instruction (through the mask/value test). Any invalid register then
* found in the instruction will cause decoding to fail with INSN_REJECTED. In
* the above example this would happen if bits 11..8 of the instruction were
* 1111, indicating R15 or PC.
*
* As well as checking for legal combinations of registers, this data is also
* used to modify the registers encoded in the instructions so that an
* emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.)
*
* Here is a real example which matches ARM instructions of the form
* "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>"
*
* DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
* REGS(ANY, ANY, NOPC, 0, ANY)),
* ^ ^ ^ ^
* Rn Rd Rs Rm
*
* Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because
* Rs == R15
*
* Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the
* instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into
* the kprobes instruction slot. This can then be called later by the handler
* function emulate_rd12rn16rm0rs8_rwflags in order to simulate the instruction.
*/
enum decode_type {
DECODE_TYPE_END,
DECODE_TYPE_TABLE,
DECODE_TYPE_CUSTOM,
DECODE_TYPE_SIMULATE,
DECODE_TYPE_EMULATE,
DECODE_TYPE_OR,
DECODE_TYPE_REJECT,
NUM_DECODE_TYPES /* Must be last enum */
};
#define DECODE_TYPE_BITS 4
#define DECODE_TYPE_MASK ((1 << DECODE_TYPE_BITS) - 1)
enum decode_reg_type {
REG_TYPE_NONE = 0, /* Not a register, ignore */
REG_TYPE_ANY, /* Any register allowed */
REG_TYPE_SAMEAS16, /* Register should be same as that at bits 19..16 */
REG_TYPE_SP, /* Register must be SP */
REG_TYPE_PC, /* Register must be PC */
REG_TYPE_NOSP, /* Register must not be SP */
REG_TYPE_NOSPPC, /* Register must not be SP or PC */
REG_TYPE_NOPC, /* Register must not be PC */
REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */
/* The following types are used when the encoding for PC indicates
* another instruction form. This distiction only matters for test
* case coverage checks.
*/
REG_TYPE_NOPCX, /* Register must not be PC */
REG_TYPE_NOSPPCX, /* Register must not be SP or PC */
/* Alias to allow '0' arg to be used in REGS macro. */
REG_TYPE_0 = REG_TYPE_NONE
};
#define REGS(r16, r12, r8, r4, r0) \
((REG_TYPE_##r16) << 16) + \
((REG_TYPE_##r12) << 12) + \
((REG_TYPE_##r8) << 8) + \
((REG_TYPE_##r4) << 4) + \
(REG_TYPE_##r0)
union decode_item {
u32 bits;
const union decode_item *table;
kprobe_insn_handler_t *handler;
kprobe_decode_insn_t *decoder;
};
#define DECODE_END \
{.bits = DECODE_TYPE_END}
struct decode_header {
union decode_item type_regs;
union decode_item mask;
union decode_item value;
};
#define DECODE_HEADER(_type, _mask, _value, _regs) \
{.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \
{.bits = (_mask)}, \
{.bits = (_value)}
struct decode_table {
struct decode_header header;
union decode_item table;
};
#define DECODE_TABLE(_mask, _value, _table) \
DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \
{.table = (_table)}
struct decode_custom {
struct decode_header header;
union decode_item decoder;
};
#define DECODE_CUSTOM(_mask, _value, _decoder) \
DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \
{.decoder = (_decoder)}
struct decode_simulate {
struct decode_header header;
union decode_item handler;
};
#define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \
DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \
{.handler = (_handler)}
#define DECODE_SIMULATE(_mask, _value, _handler) \
DECODE_SIMULATEX(_mask, _value, _handler, 0)
struct decode_emulate {
struct decode_header header;
union decode_item handler;
};
#define DECODE_EMULATEX(_mask, _value, _handler, _regs) \
DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \
{.handler = (_handler)}
#define DECODE_EMULATE(_mask, _value, _handler) \
DECODE_EMULATEX(_mask, _value, _handler, 0)
struct decode_or {
struct decode_header header;
};
#define DECODE_OR(_mask, _value) \
DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0)
struct decode_reject {
struct decode_header header;
};
#define DECODE_REJECT(_mask, _value) \
DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
const union decode_item *table, bool thumb16);
#endif /* _ARM_KERNEL_KPROBES_H */
......@@ -583,7 +583,7 @@ static int armpmu_event_init(struct perf_event *event)
static void armpmu_enable(struct pmu *pmu)
{
/* Enable all of the perf events on hardware. */
int idx;
int idx, enabled = 0;
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
if (!armpmu)
......@@ -596,9 +596,11 @@ static void armpmu_enable(struct pmu *pmu)
continue;
armpmu->enable(&event->hw, idx);
enabled = 1;
}
armpmu->start();
if (enabled)
armpmu->start();
}
static void armpmu_disable(struct pmu *pmu)
......
......@@ -228,34 +228,12 @@ static struct undef_hook thumb_break_hook = {
.fn = break_trap,
};
static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr)
{
unsigned int instr2;
void __user *pc;
/* Check the second half of the instruction. */
pc = (void __user *)(instruction_pointer(regs) + 2);
if (processor_mode(regs) == SVC_MODE) {
instr2 = *(u16 *) pc;
} else {
get_user(instr2, (u16 __user *)pc);
}
if (instr2 == 0xa000) {
ptrace_break(current, regs);
return 0;
} else {
return 1;
}
}
static struct undef_hook thumb2_break_hook = {
.instr_mask = 0xffff,
.instr_val = 0xf7f0,
.instr_mask = 0xffffffff,
.instr_val = 0xf7f0a000,
.cpsr_mask = PSR_T_BIT,
.cpsr_val = PSR_T_BIT,
.fn = thumb2_break_trap,
.fn = break_trap,
};
static int __init ptrace_break_init(void)
......
......@@ -73,6 +73,7 @@ __setup("fpe=", fpe_setup);
#endif
extern void paging_init(struct machine_desc *desc);
extern void sanity_check_meminfo(void);
extern void reboot_setup(char *str);
unsigned int processor_id;
......@@ -900,6 +901,7 @@ void __init setup_arch(char **cmdline_p)
parse_early_param();
sanity_check_meminfo();
arm_memblock_init(&meminfo, mdesc);
paging_init(mdesc);
......
......@@ -115,7 +115,7 @@ static void __cpuinit twd_calibrate_rate(void)
twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000,
(twd_timer_rate / 1000000) % 100);
(twd_timer_rate / 10000) % 100);
}
}
......
......@@ -355,9 +355,24 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
pc = (void __user *)instruction_pointer(regs);
if (processor_mode(regs) == SVC_MODE) {
instr = *(u32 *) pc;
#ifdef CONFIG_THUMB2_KERNEL
if (thumb_mode(regs)) {
instr = ((u16 *)pc)[0];
if (is_wide_instruction(instr)) {
instr <<= 16;
instr |= ((u16 *)pc)[1];
}
} else
#endif
instr = *(u32 *) pc;
} else if (thumb_mode(regs)) {
get_user(instr, (u16 __user *)pc);
if (is_wide_instruction(instr)) {
unsigned int instr2;
get_user(instr2, (u16 __user *)pc+1);
instr <<= 16;
instr |= instr2;
}
} else {
get_user(instr, (u32 __user *)pc);
}
......
......@@ -223,15 +223,15 @@ static struct clk *periph_clocks[] __initdata = {
};
static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk),
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk),
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk),
CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.1", &mmc1_clk),
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
CLKDEV_CON_DEV_ID("ssc", "ssc.0", &ssc0_clk),
CLKDEV_CON_DEV_ID("ssc", "ssc.1", &ssc1_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
......
......@@ -1220,7 +1220,7 @@ void __init at91_set_serial_console(unsigned portnr)
{
if (portnr < ATMEL_MAX_UART) {
atmel_default_console_device = at91_uarts[portnr];
at91cap9_set_console_clock(portnr);
at91cap9_set_console_clock(at91_uarts[portnr]->id);
}
}
......
......@@ -199,9 +199,9 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
CLKDEV_CON_DEV_ID("ssc", "ssc.0", &ssc0_clk),
CLKDEV_CON_DEV_ID("ssc", "ssc.1", &ssc1_clk),
CLKDEV_CON_DEV_ID("ssc", "ssc.2", &ssc2_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
......
......@@ -1135,7 +1135,7 @@ void __init at91_set_serial_console(unsigned portnr)
{
if (portnr < ATMEL_MAX_UART) {
atmel_default_console_device = at91_uarts[portnr];
at91rm9200_set_console_clock(portnr);
at91rm9200_set_console_clock(at91_uarts[portnr]->id);
}
}
......
......@@ -1173,7 +1173,7 @@ void __init at91_set_serial_console(unsigned portnr)
{
if (portnr < ATMEL_MAX_UART) {
atmel_default_console_device = at91_uarts[portnr];
at91sam9260_set_console_clock(portnr);
at91sam9260_set_console_clock(at91_uarts[portnr]->id);
}
}
......
......@@ -1013,7 +1013,7 @@ void __init at91_set_serial_console(unsigned portnr)
{
if (portnr < ATMEL_MAX_UART) {
atmel_default_console_device = at91_uarts[portnr];
at91sam9261_set_console_clock(portnr);
at91sam9261_set_console_clock(at91_uarts[portnr]->id);
}
}
......
......@@ -1395,7 +1395,7 @@ void __init at91_set_serial_console(unsigned portnr)
{
if (portnr < ATMEL_MAX_UART) {
atmel_default_console_device = at91_uarts[portnr];
at91sam9263_set_console_clock(portnr);
at91sam9263_set_console_clock(at91_uarts[portnr]->id);
}
}
......
......@@ -217,11 +217,11 @@ static struct clk *periph_clocks[] __initdata = {
static struct clk_lookup periph_clocks_lookups[] = {
/* One additional fake clock for ohci */
CLKDEV_CON_ID("ohci_clk", &uhphs_clk),
CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci.0", &uhphs_clk),
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk),
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk),
CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk),
CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.1", &mmc1_clk),
CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci", &uhphs_clk),
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk),
......
......@@ -1550,7 +1550,7 @@ void __init at91_set_serial_console(unsigned portnr)
{
if (portnr < ATMEL_MAX_UART) {
atmel_default_console_device = at91_uarts[portnr];
at91sam9g45_set_console_clock(portnr);
at91sam9g45_set_console_clock(at91_uarts[portnr]->id);
}
}
......
......@@ -191,8 +191,8 @@ static struct clk *periph_clocks[] __initdata = {
};
static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk),
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk),
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
......
......@@ -1168,7 +1168,7 @@ void __init at91_set_serial_console(unsigned portnr)
{
if (portnr < ATMEL_MAX_UART) {
atmel_default_console_device = at91_uarts[portnr];
at91sam9rl_set_console_clock(portnr);
at91sam9rl_set_console_clock(at91_uarts[portnr]->id);
}
}
......
......@@ -215,7 +215,7 @@ static void __init cap9adk_add_device_nand(void)
csa = at91_sys_read(AT91_MATRIX_EBICSA);
at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_VDDIOMSEL_3_3V);
cap9adk_nand_data.bus_width_16 = !board_have_nand_8bit();
cap9adk_nand_data.bus_width_16 = board_have_nand_16bit();
/* setup bus-width (8 or 16) */
if (cap9adk_nand_data.bus_width_16)
cap9adk_nand_smc_config.mode |= AT91_SMC_DBW_16;
......
......@@ -214,7 +214,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
static void __init ek_add_device_nand(void)
{
ek_nand_data.bus_width_16 = !board_have_nand_8bit();
ek_nand_data.bus_width_16 = board_have_nand_16bit();
/* setup bus-width (8 or 16) */
if (ek_nand_data.bus_width_16)
ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
......
......@@ -220,7 +220,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
static void __init ek_add_device_nand(void)
{
ek_nand_data.bus_width_16 = !board_have_nand_8bit();
ek_nand_data.bus_width_16 = board_have_nand_16bit();
/* setup bus-width (8 or 16) */
if (ek_nand_data.bus_width_16)
ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
......
......@@ -221,7 +221,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
static void __init ek_add_device_nand(void)
{
ek_nand_data.bus_width_16 = !board_have_nand_8bit();
ek_nand_data.bus_width_16 = board_have_nand_16bit();
/* setup bus-width (8 or 16) */
if (ek_nand_data.bus_width_16)
ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册