Auto merge with /home/aegl/GIT/linus
This commit is contained in:
commit
88c3cdfdde
344 changed files with 14723 additions and 7158 deletions
|
@ -13,14 +13,17 @@ different way: With the help of a dvb-usb-framework.
|
|||
The framework provides generic functions (mostly kernel API calls), such as:
|
||||
|
||||
- Transport Stream URB handling in conjunction with dvb-demux-feed-control
|
||||
(bulk and isoc (TODO) are supported)
|
||||
(bulk and isoc are supported)
|
||||
- registering the device for the DVB-API
|
||||
- registering an I2C-adapter if applicable
|
||||
- remote-control/input-device handling
|
||||
- firmware requesting and loading (currently just for the Cypress USB
|
||||
controller)
|
||||
controllers)
|
||||
- other functions/methods which can be shared by several drivers (such as
|
||||
functions for bulk-control-commands)
|
||||
- TODO: a I2C-chunker. It creates device-specific chunks of register-accesses
|
||||
depending on length of a register and the number of values that can be
|
||||
multi-written and multi-read.
|
||||
|
||||
The source code of the particular DVB USB devices does just the communication
|
||||
with the device via the bus. The connection between the DVB-API-functionality
|
||||
|
@ -36,93 +39,18 @@ the dvb-usb-lib.
|
|||
TODO: dynamic enabling and disabling of the pid-filter in regard to number of
|
||||
feeds requested.
|
||||
|
||||
Supported devices USB1.1
|
||||
Supported devices
|
||||
========================
|
||||
|
||||
Produced and reselled by Twinhan:
|
||||
---------------------------------
|
||||
- TwinhanDTV USB-Ter DVB-T Device (VP7041)
|
||||
http://www.twinhan.com/product_terrestrial_3.asp
|
||||
See the LinuxTV DVB Wiki at www.linuxtv.org for a complete list of
|
||||
cards/drivers/firmwares:
|
||||
|
||||
- TwinhanDTV Magic Box (VP7041e)
|
||||
http://www.twinhan.com/product_terrestrial_4.asp
|
||||
|
||||
- HAMA DVB-T USB device
|
||||
http://www.hama.de/portal/articleId*110620/action*2598
|
||||
|
||||
- CTS Portable (Chinese Television System) (2)
|
||||
http://www.2cts.tv/ctsportable/
|
||||
|
||||
- Unknown USB DVB-T device with vendor ID Hyper-Paltek
|
||||
|
||||
|
||||
Produced and reselled by KWorld:
|
||||
--------------------------------
|
||||
- KWorld V-Stream XPERT DTV DVB-T USB
|
||||
http://www.kworld.com.tw/en/product/DVBT-USB/DVBT-USB.html
|
||||
|
||||
- JetWay DTV DVB-T USB
|
||||
http://www.jetway.com.tw/evisn/product/lcd-tv/DVT-USB/dtv-usb.htm
|
||||
|
||||
- ADSTech Instant TV DVB-T USB
|
||||
http://www.adstech.com/products/PTV-333/intro/PTV-333_intro.asp?pid=PTV-333
|
||||
|
||||
|
||||
Others:
|
||||
-------
|
||||
- Ultima Electronic/Artec T1 USB TVBOX (AN2135, AN2235, AN2235 with Panasonic Tuner)
|
||||
http://82.161.246.249/products-tvbox.html
|
||||
|
||||
- Compro Videomate DVB-U2000 - DVB-T USB (2)
|
||||
http://www.comprousa.com/products/vmu2000.htm
|
||||
|
||||
- Grandtec USB DVB-T
|
||||
http://www.grand.com.tw/
|
||||
|
||||
- AVerMedia AverTV DVBT USB
|
||||
http://www.avermedia.com/
|
||||
|
||||
- DiBcom USB DVB-T reference device (non-public)
|
||||
|
||||
|
||||
Supported devices USB2.0-only
|
||||
=============================
|
||||
- Twinhan MagicBox II
|
||||
http://www.twinhan.com/product_terrestrial_7.asp
|
||||
|
||||
- TwinhanDTV Alpha
|
||||
http://www.twinhan.com/product_terrestrial_8.asp
|
||||
|
||||
- DigitalNow TinyUSB 2 DVB-t Receiver
|
||||
http://www.digitalnow.com.au/DigitalNow%20tinyUSB2%20Specifications.html
|
||||
|
||||
- Hanftek UMT-010
|
||||
http://www.globalsources.com/si/6008819757082/ProductDetail/Digital-TV/product_id-100046529
|
||||
|
||||
|
||||
Supported devices USB2.0 and USB1.1
|
||||
=============================
|
||||
- Typhoon/Yakumo/HAMA/Yuan DVB-T mobile USB2.0
|
||||
http://www.yakumo.de/produkte/index.php?pid=1&ag=DVB-T
|
||||
http://www.yuan.com.tw/en/products/vdo_ub300.html
|
||||
http://www.hama.de/portal/articleId*114663/action*2563
|
||||
http://www.anubisline.com/english/articlec.asp?id=50502&catid=002
|
||||
|
||||
- Artec T1 USB TVBOX (FX2) (2)
|
||||
|
||||
- Hauppauge WinTV NOVA-T USB2
|
||||
http://www.hauppauge.com/
|
||||
|
||||
- KWorld/ADSTech Instant DVB-T USB2.0 (DiB3000M-B)
|
||||
|
||||
- DiBcom USB2.0 DVB-T reference device (non-public)
|
||||
|
||||
- AVerMedia AverTV A800 DVB-T USB2.0
|
||||
|
||||
1) It is working almost - work-in-progress.
|
||||
2) No test reports received yet.
|
||||
http://www.linuxtv.org/wiki/index.php/DVB_USB
|
||||
|
||||
0. History & News:
|
||||
2005-06-30 - added support for WideView WT-220U (Thanks to Steve Chang)
|
||||
2005-05-30 - added basic isochronous support to the dvb-usb-framework
|
||||
added support for Conexant Hybrid reference design and Nebula DigiTV USB
|
||||
2005-04-17 - all dibusb devices ported to make use of the dvb-usb-framework
|
||||
2005-04-02 - re-enabled and improved remote control code.
|
||||
2005-03-31 - ported the Yakumo/Hama/Typhoon DVB-T USB2.0 device to dvb-usb.
|
||||
|
@ -137,7 +65,7 @@ Supported devices USB2.0 and USB1.1
|
|||
2005-01-31 - distorted streaming is gone for USB1.1 devices
|
||||
2005-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb
|
||||
- first almost working version for HanfTek UMT-010
|
||||
- found out, that Yakumo/HAMA/Typhoon are predessors of the HanfTek UMT-010
|
||||
- found out, that Yakumo/HAMA/Typhoon are predecessors of the HanfTek UMT-010
|
||||
2005-01-10 - refactoring completed, now everything is very delightful
|
||||
- tuner quirks for some weird devices (Artec T1 AN2235 device has sometimes a
|
||||
Panasonic Tuner assembled). Tunerprobing implemented. Thanks a lot to Gunnar Wittich.
|
||||
|
@ -187,25 +115,13 @@ Supported devices USB2.0 and USB1.1
|
|||
1. How to use?
|
||||
1.1. Firmware
|
||||
|
||||
Most of the USB drivers need to download a firmware to start working.
|
||||
Most of the USB drivers need to download a firmware to the device before start
|
||||
working.
|
||||
|
||||
for USB1.1 (AN2135) you need: dvb-usb-dibusb-5.0.0.11.fw
|
||||
for USB2.0 HanfTek: dvb-usb-umt-010-02.fw
|
||||
for USB2.0 DiBcom: dvb-usb-dibusb-6.0.0.8.fw
|
||||
for USB2.0 AVerMedia AverTV DVB-T USB2: dvb-usb-avertv-a800-01.fw
|
||||
for USB2.0 TwinhanDTV Alpha/MagicBox II: dvb-usb-vp7045-01.fw
|
||||
Have a look at the Wikipage for the DVB-USB-drivers to find out, which firmware
|
||||
you need for your device:
|
||||
|
||||
The files can be found on http://www.linuxtv.org/download/firmware/ .
|
||||
|
||||
We do not have the permission (yet) to publish the following firmware-files.
|
||||
You'll need to extract them from the windows drivers.
|
||||
|
||||
You should be able to use "get_dvb_firmware dvb-usb" to get the firmware:
|
||||
|
||||
for USB1.1 (AN2235) (a few Artec T1 devices): dvb-usb-dibusb-an2235-01.fw
|
||||
for USB2.0 Hauppauge: dvb-usb-nova-t-usb2-01.fw
|
||||
for USB2.0 ADSTech/Kworld USB2.0: dvb-usb-adstech-usb2-01.fw
|
||||
for USB2.0 Yakumo/Typhoon/Hama: dvb-usb-dtt200u-01.fw
|
||||
http://www.linuxtv.org/wiki/index.php/DVB_USB
|
||||
|
||||
1.2. Compiling
|
||||
|
||||
|
@ -289,6 +205,9 @@ Patches, comments and suggestions are very very welcome.
|
|||
Gunnar Wittich and Joachim von Caron for their trust for providing
|
||||
root-shells on their machines to implement support for new devices.
|
||||
|
||||
Allan Third and Michael Hutchinson for their help to write the Nebula
|
||||
digitv-driver.
|
||||
|
||||
Glen Harris for bringing up, that there is a new dibusb-device and Jiun-Kuei
|
||||
Jung from AVerMedia who kindly provided a special firmware to get the device
|
||||
up and running in Linux.
|
||||
|
@ -296,7 +215,12 @@ Patches, comments and suggestions are very very welcome.
|
|||
Jennifer Chen, Jeff and Jack from Twinhan for kindly supporting by
|
||||
writing the vp7045-driver.
|
||||
|
||||
Some guys on the linux-dvb mailing list for encouraging me
|
||||
Steve Chang from WideView for providing information for new devices and
|
||||
firmware files.
|
||||
|
||||
Michael Paxton for submitting remote control keymaps.
|
||||
|
||||
Some guys on the linux-dvb mailing list for encouraging me.
|
||||
|
||||
Peter Schildmann >peter.schildmann-nospam-at-web.de< for his
|
||||
user-level firmware loader, which saves a lot of time
|
||||
|
@ -305,4 +229,4 @@ Patches, comments and suggestions are very very welcome.
|
|||
Ulf Hermenau for helping me out with traditional chinese.
|
||||
|
||||
André Smoktun and Christian Frömmel for supporting me with
|
||||
hardware and listening to my problems very patient.
|
||||
hardware and listening to my problems very patiently.
|
||||
|
|
|
@ -1,66 +1,55 @@
|
|||
How to get the Nebula, PCTV and Twinhan DST cards working
|
||||
=========================================================
|
||||
How to get the Nebula Electronics DigiTV, Pinnacle PCTV Sat, Twinhan DST + clones working
|
||||
=========================================================================================
|
||||
|
||||
This class of cards has a bt878a as the PCI interface, and
|
||||
require the bttv driver.
|
||||
1) General information
|
||||
======================
|
||||
|
||||
Please pay close attention to the warning about the bttv module
|
||||
options below for the DST card.
|
||||
This class of cards has a bt878a chip as the PCI interface.
|
||||
The different card drivers require the bttv driver to provide the means
|
||||
to access the i2c bus and the gpio pins of the bt8xx chipset.
|
||||
|
||||
1) General informations
|
||||
=======================
|
||||
2) Compilation rules for Kernel >= 2.6.12
|
||||
=========================================
|
||||
|
||||
These drivers require the bttv driver to provide the means to access
|
||||
the i2c bus and the gpio pins of the bt8xx chipset.
|
||||
Enable the following options:
|
||||
|
||||
Because of this, you need to enable
|
||||
"Device drivers" => "Multimedia devices"
|
||||
=> "Video For Linux" => "BT848 Video For Linux"
|
||||
|
||||
Furthermore you need to enable
|
||||
=> "Video For Linux" => "BT848 Video For Linux"
|
||||
"Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices"
|
||||
=> "DVB for Linux" "DVB Core Support" "Nebula/Pinnacle PCTV/TwinHan PCI Cards"
|
||||
=> "DVB for Linux" "DVB Core Support" "Nebula/Pinnacle PCTV/TwinHan PCI Cards"
|
||||
|
||||
2) Loading Modules
|
||||
==================
|
||||
3) Loading Modules, described by two approaches
|
||||
===============================================
|
||||
|
||||
In general you need to load the bttv driver, which will handle the gpio and
|
||||
i2c communication for us, plus the common dvb-bt8xx device driver.
|
||||
The frontends for Nebula (nxt6000), Pinnacle PCTV (cx24110) and
|
||||
TwinHan (dst) are loaded automatically by the dvb-bt8xx device driver.
|
||||
i2c communication for us, plus the common dvb-bt8xx device driver,
|
||||
which is called the backend.
|
||||
The frontends for Nebula DigiTV (nxt6000), Pinnacle PCTV Sat (cx24110),
|
||||
TwinHan DST + clones (dst and dst-ca) are loaded automatically by the backend.
|
||||
For further details about TwinHan DST + clones see /Documentation/dvb/ci.txt.
|
||||
|
||||
3a) Nebula / Pinnacle PCTV
|
||||
3a) The manual approach
|
||||
-----------------------
|
||||
|
||||
Loading modules:
|
||||
modprobe bttv
|
||||
modprobe dvb-bt8xx
|
||||
|
||||
Unloading modules:
|
||||
modprobe -r dvb-bt8xx
|
||||
modprobe -r bttv
|
||||
|
||||
3b) The automatic approach
|
||||
--------------------------
|
||||
|
||||
$ modprobe bttv (normally bttv is being loaded automatically by kmod)
|
||||
$ modprobe dvb-bt8xx (or just place dvb-bt8xx in /etc/modules for automatic loading)
|
||||
If not already done by installation, place a line either in
|
||||
/etc/modules.conf or in /etc/modprobe.conf containing this text:
|
||||
alias char-major-81 bttv
|
||||
|
||||
Then place a line in /etc/modules containing this text:
|
||||
dvb-bt8xx
|
||||
|
||||
3b) TwinHan and Clones
|
||||
--------------------------
|
||||
|
||||
$ modprobe bttv i2c_hw=1 card=0x71
|
||||
$ modprobe dvb-bt8xx
|
||||
$ modprobe dst
|
||||
|
||||
The value 0x71 will override the PCI type detection for dvb-bt8xx,
|
||||
which is necessary for TwinHan cards.
|
||||
|
||||
If you're having an older card (blue color circuit) and card=0x71 locks
|
||||
your machine, try using 0x68, too. If that does not work, ask on the
|
||||
mailing list.
|
||||
|
||||
The DST module takes a couple of useful parameters:
|
||||
|
||||
a. verbose takes values 0 to 5. These values control the verbosity level.
|
||||
b. debug takes values 0 and 1. You can either disable or enable debugging.
|
||||
c. dst_addons takes values 0 and 0x20:
|
||||
- A value of 0 means it is a FTA card.
|
||||
- A value of 0x20 means it has a Conditional Access slot.
|
||||
|
||||
The autodetected values are determined by the "response string"
|
||||
of the card, which you can see in your logs:
|
||||
e.g.: dst_get_device_id: Recognize [DSTMCI]
|
||||
Reboot your system and have fun!
|
||||
|
||||
--
|
||||
Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham, Uwe Bugla
|
||||
|
|
|
@ -119,3 +119,19 @@ Why: Match the other drivers' name for the same function, duplicate names
|
|||
will be available until removal of old names.
|
||||
Who: Grant Coady <gcoady@gmail.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
|
||||
When: November 2005
|
||||
Files: drivers/pcmcia/: pcmcia_ioctl.c
|
||||
Why: With the 16-bit PCMCIA subsystem now behaving (almost) like a
|
||||
normal hotpluggable bus, and with it using the default kernel
|
||||
infrastructure (hotplug, driver core, sysfs) keeping the PCMCIA
|
||||
control ioctl needed by cardmgr and cardctl from pcmcia-cs is
|
||||
unnecessary, and makes further cleanups and integration of the
|
||||
PCMCIA subsystem into the Linux kernel device driver model more
|
||||
difficult. The features provided by cardmgr and cardctl are either
|
||||
handled by the kernel itself now or are available in the new
|
||||
pcmciautils package available at
|
||||
http://kernel.org/pub/linux/utils/kernel/pcmcia/
|
||||
Who: Dominik Brodowski <linux@brodo.de>
|
||||
|
|
69
Documentation/infiniband/user_verbs.txt
Normal file
69
Documentation/infiniband/user_verbs.txt
Normal file
|
@ -0,0 +1,69 @@
|
|||
USERSPACE VERBS ACCESS
|
||||
|
||||
The ib_uverbs module, built by enabling CONFIG_INFINIBAND_USER_VERBS,
|
||||
enables direct userspace access to IB hardware via "verbs," as
|
||||
described in chapter 11 of the InfiniBand Architecture Specification.
|
||||
|
||||
To use the verbs, the libibverbs library, available from
|
||||
<http://openib.org/>, is required. libibverbs contains a
|
||||
device-independent API for using the ib_uverbs interface.
|
||||
libibverbs also requires appropriate device-dependent kernel and
|
||||
userspace driver for your InfiniBand hardware. For example, to use
|
||||
a Mellanox HCA, you will need the ib_mthca kernel module and the
|
||||
libmthca userspace driver be installed.
|
||||
|
||||
User-kernel communication
|
||||
|
||||
Userspace communicates with the kernel for slow path, resource
|
||||
management operations via the /dev/infiniband/uverbsN character
|
||||
devices. Fast path operations are typically performed by writing
|
||||
directly to hardware registers mmap()ed into userspace, with no
|
||||
system call or context switch into the kernel.
|
||||
|
||||
Commands are sent to the kernel via write()s on these device files.
|
||||
The ABI is defined in drivers/infiniband/include/ib_user_verbs.h.
|
||||
The structs for commands that require a response from the kernel
|
||||
contain a 64-bit field used to pass a pointer to an output buffer.
|
||||
Status is returned to userspace as the return value of the write()
|
||||
system call.
|
||||
|
||||
Resource management
|
||||
|
||||
Since creation and destruction of all IB resources is done by
|
||||
commands passed through a file descriptor, the kernel can keep track
|
||||
of which resources are attached to a given userspace context. The
|
||||
ib_uverbs module maintains idr tables that are used to translate
|
||||
between kernel pointers and opaque userspace handles, so that kernel
|
||||
pointers are never exposed to userspace and userspace cannot trick
|
||||
the kernel into following a bogus pointer.
|
||||
|
||||
This also allows the kernel to clean up when a process exits and
|
||||
prevent one process from touching another process's resources.
|
||||
|
||||
Memory pinning
|
||||
|
||||
Direct userspace I/O requires that memory regions that are potential
|
||||
I/O targets be kept resident at the same physical address. The
|
||||
ib_uverbs module manages pinning and unpinning memory regions via
|
||||
get_user_pages() and put_page() calls. It also accounts for the
|
||||
amount of memory pinned in the process's locked_vm, and checks that
|
||||
unprivileged processes do not exceed their RLIMIT_MEMLOCK limit.
|
||||
|
||||
Pages that are pinned multiple times are counted each time they are
|
||||
pinned, so the value of locked_vm may be an overestimate of the
|
||||
number of pages pinned by a process.
|
||||
|
||||
/dev files
|
||||
|
||||
To create the appropriate character device files automatically with
|
||||
udev, a rule like
|
||||
|
||||
KERNEL="uverbs*", NAME="infiniband/%k"
|
||||
|
||||
can be used. This will create device nodes named
|
||||
|
||||
/dev/infiniband/uverbs0
|
||||
|
||||
and so on. Since the InfiniBand userspace verbs should be safe for
|
||||
use by non-privileged processes, it may be useful to add an
|
||||
appropriate MODE or GROUP to the udev rule.
|
|
@ -117,6 +117,7 @@ IBM Thinkpad X40 Type 2371-7JG s3_bios,s3_mode (4)
|
|||
Medion MD4220 ??? (*)
|
||||
Samsung P35 vbetool needed (6)
|
||||
Sharp PC-AR10 (ATI rage) none (1)
|
||||
Sony Vaio PCG-C1VRX/K s3_bios (2)
|
||||
Sony Vaio PCG-F403 ??? (*)
|
||||
Sony Vaio PCG-N505SN ??? (*)
|
||||
Sony Vaio vgn-s260 X or boot-radeon can init it (5)
|
||||
|
|
|
@ -370,6 +370,10 @@ W: http://www.thekelleys.org.uk/atmel
|
|||
W: http://atmelwlandriver.sourceforge.net/
|
||||
S: Maintained
|
||||
|
||||
AUDIT SUBSYSTEM
|
||||
L: linux-audit@redhat.com (subscribers-only)
|
||||
S: Maintained
|
||||
|
||||
AX.25 NETWORK LAYER
|
||||
P: Ralf Baechle
|
||||
M: ralf@linux-mips.org
|
||||
|
@ -1803,8 +1807,9 @@ M: greg@kroah.com
|
|||
S: Maintained
|
||||
|
||||
PCMCIA SUBSYSTEM
|
||||
P: Linux PCMCIA Team
|
||||
L: http://lists.infradead.org/mailman/listinfo/linux-pcmcia
|
||||
S: Unmaintained
|
||||
S: Maintained
|
||||
|
||||
PCNET32 NETWORK DRIVER
|
||||
P: Thomas Bogendörfer
|
||||
|
|
6
Makefile
6
Makefile
|
@ -792,6 +792,9 @@ export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
|
|||
$(Q)$(MAKE) $(build)=$(@D) $@
|
||||
%.o: %.c scripts FORCE
|
||||
$(Q)$(MAKE) $(build)=$(@D) $@
|
||||
%.ko: scripts FORCE
|
||||
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) $(build)=$(@D) $(@:.ko=.o)
|
||||
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
|
||||
%/: scripts prepare FORCE
|
||||
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) $(build)=$(@D)
|
||||
%.lst: %.c scripts FORCE
|
||||
|
@ -1033,6 +1036,7 @@ help:
|
|||
@echo ' modules_install - Install all modules'
|
||||
@echo ' dir/ - Build all files in dir and below'
|
||||
@echo ' dir/file.[ois] - Build specified target only'
|
||||
@echo ' dir/file.ko - Build module including final link'
|
||||
@echo ' rpm - Build a kernel as an RPM package'
|
||||
@echo ' tags/TAGS - Generate tags file for editors'
|
||||
@echo ' cscope - Generate cscope index'
|
||||
|
@ -1149,7 +1153,7 @@ endif # KBUILD_EXTMOD
|
|||
#(which is the most common case IMHO) to avoid unneeded clutter in the big tags file.
|
||||
#Adding $(srctree) adds about 20M on i386 to the size of the output file!
|
||||
|
||||
ifeq ($(KBUILD_OUTPUT),)
|
||||
ifeq ($(src),$(obj))
|
||||
__srctree =
|
||||
else
|
||||
__srctree = $(srctree)/
|
||||
|
|
627
arch/frv/defconfig
Normal file
627
arch/frv/defconfig
Normal file
|
@ -0,0 +1,627 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.11.8
|
||||
# Fri May 13 17:16:03 2005
|
||||
#
|
||||
CONFIG_FRV=y
|
||||
CONFIG_UID16=y
|
||||
CONFIG_RWSEM_GENERIC_SPINLOCK=y
|
||||
CONFIG_GENERIC_FIND_NEXT_BIT=y
|
||||
# CONFIG_GENERIC_CALIBRATE_DELAY is not set
|
||||
# CONFIG_GENERIC_HARDIRQS is not set
|
||||
|
||||
#
|
||||
# Code maturity level options
|
||||
#
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_CLEAN_COMPILE=y
|
||||
CONFIG_BROKEN_ON_SMP=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
|
||||
#
|
||||
# General setup
|
||||
#
|
||||
CONFIG_LOCALVERSION=""
|
||||
CONFIG_SWAP=y
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
CONFIG_SYSCTL=y
|
||||
# CONFIG_AUDIT is not set
|
||||
# CONFIG_HOTPLUG is not set
|
||||
# CONFIG_KOBJECT_UEVENT is not set
|
||||
# CONFIG_IKCONFIG is not set
|
||||
CONFIG_EMBEDDED=y
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_ALL is not set
|
||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
CONFIG_EPOLL=y
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
CONFIG_SHMEM=y
|
||||
CONFIG_CC_ALIGN_FUNCTIONS=0
|
||||
CONFIG_CC_ALIGN_LABELS=0
|
||||
CONFIG_CC_ALIGN_LOOPS=0
|
||||
CONFIG_CC_ALIGN_JUMPS=0
|
||||
# CONFIG_TINY_SHMEM is not set
|
||||
CONFIG_BASE_SMALL=0
|
||||
|
||||
#
|
||||
# Loadable module support
|
||||
#
|
||||
# CONFIG_MODULES is not set
|
||||
|
||||
#
|
||||
# Fujitsu FR-V system setup
|
||||
#
|
||||
CONFIG_MMU=y
|
||||
CONFIG_FRV_OUTOFLINE_ATOMIC_OPS=y
|
||||
CONFIG_HIGHMEM=y
|
||||
CONFIG_HIGHPTE=y
|
||||
CONFIG_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_FLATMEM_MANUAL=y
|
||||
# CONFIG_DISCONTIGMEM_MANUAL is not set
|
||||
# CONFIG_SPARSEMEM_MANUAL is not set
|
||||
CONFIG_FLATMEM=y
|
||||
CONFIG_FLAT_NODE_MEM_MAP=y
|
||||
# CONFIG_FRV_DEFL_CACHE_WBACK is not set
|
||||
# CONFIG_FRV_DEFL_CACHE_WBEHIND is not set
|
||||
CONFIG_FRV_DEFL_CACHE_WTHRU=y
|
||||
# CONFIG_FRV_DEFL_CACHE_DISABLED is not set
|
||||
|
||||
#
|
||||
# CPU core support
|
||||
#
|
||||
CONFIG_CPU_FR451=y
|
||||
CONFIG_CPU_FR451_COMPILE=y
|
||||
CONFIG_FRV_L1_CACHE_SHIFT=5
|
||||
CONFIG_MB93091_VDK=y
|
||||
# CONFIG_MB93093_PDK is not set
|
||||
CONFIG_MB93090_MB00=y
|
||||
# CONFIG_MB93091_NO_MB is not set
|
||||
# CONFIG_GPREL_DATA_8 is not set
|
||||
CONFIG_GPREL_DATA_4=y
|
||||
# CONFIG_GPREL_DATA_NONE is not set
|
||||
CONFIG_PCI=y
|
||||
# CONFIG_PCI_LEGACY_PROC is not set
|
||||
# CONFIG_PCI_NAMES is not set
|
||||
# CONFIG_PCI_DEBUG is not set
|
||||
# CONFIG_PCMCIA is not set
|
||||
|
||||
#
|
||||
# Power management options
|
||||
#
|
||||
# CONFIG_PM is not set
|
||||
|
||||
#
|
||||
# Executable formats
|
||||
#
|
||||
# CONFIG_BINFMT_ELF is not set
|
||||
CONFIG_BINFMT_ELF_FDPIC=y
|
||||
# CONFIG_BINFMT_MISC is not set
|
||||
|
||||
#
|
||||
# Device Drivers
|
||||
#
|
||||
|
||||
#
|
||||
# Generic Driver Options
|
||||
#
|
||||
# CONFIG_STANDALONE is not set
|
||||
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
|
||||
# CONFIG_FW_LOADER is not set
|
||||
# CONFIG_DEBUG_DRIVER is not set
|
||||
|
||||
#
|
||||
# Connector - unified userspace <-> kernelspace linker
|
||||
#
|
||||
# CONFIG_CONNECTOR is not set
|
||||
# CONFIG_FORK_CONNECTOR is not set
|
||||
|
||||
#
|
||||
# Memory Technology Devices (MTD)
|
||||
#
|
||||
# CONFIG_MTD is not set
|
||||
|
||||
#
|
||||
# Parallel port support
|
||||
#
|
||||
# CONFIG_PARPORT is not set
|
||||
|
||||
#
|
||||
# Plug and Play support
|
||||
#
|
||||
|
||||
#
|
||||
# Block devices
|
||||
#
|
||||
# CONFIG_BLK_DEV_FD is not set
|
||||
# CONFIG_BLK_CPQ_DA is not set
|
||||
# CONFIG_BLK_CPQ_CISS_DA is not set
|
||||
# CONFIG_BLK_DEV_DAC960 is not set
|
||||
# CONFIG_BLK_DEV_UMEM is not set
|
||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||
# CONFIG_BLK_DEV_LOOP is not set
|
||||
# CONFIG_BLK_DEV_NBD is not set
|
||||
# CONFIG_BLK_DEV_SX8 is not set
|
||||
# CONFIG_BLK_DEV_RAM is not set
|
||||
CONFIG_BLK_DEV_RAM_COUNT=16
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
# CONFIG_CDROM_PKTCDVD is not set
|
||||
|
||||
#
|
||||
# IO Schedulers
|
||||
#
|
||||
CONFIG_IOSCHED_NOOP=y
|
||||
CONFIG_IOSCHED_AS=y
|
||||
CONFIG_IOSCHED_DEADLINE=y
|
||||
CONFIG_IOSCHED_CFQ=y
|
||||
# CONFIG_ATA_OVER_ETH is not set
|
||||
|
||||
#
|
||||
# ATA/ATAPI/MFM/RLL support
|
||||
#
|
||||
# CONFIG_IDE is not set
|
||||
|
||||
#
|
||||
# SCSI device support
|
||||
#
|
||||
# CONFIG_SCSI is not set
|
||||
|
||||
#
|
||||
# Multi-device support (RAID and LVM)
|
||||
#
|
||||
# CONFIG_MD is not set
|
||||
|
||||
#
|
||||
# Fusion MPT device support
|
||||
#
|
||||
# CONFIG_FUSION is not set
|
||||
|
||||
#
|
||||
# IEEE 1394 (FireWire) support
|
||||
#
|
||||
# CONFIG_IEEE1394 is not set
|
||||
|
||||
#
|
||||
# I2O device support
|
||||
#
|
||||
# CONFIG_I2O is not set
|
||||
|
||||
#
|
||||
# Networking support
|
||||
#
|
||||
CONFIG_NET=y
|
||||
|
||||
#
|
||||
# Networking options
|
||||
#
|
||||
CONFIG_PACKET=y
|
||||
# CONFIG_PACKET_MMAP is not set
|
||||
CONFIG_UNIX=y
|
||||
# CONFIG_NET_KEY is not set
|
||||
CONFIG_INET=y
|
||||
# CONFIG_IP_MULTICAST is not set
|
||||
# CONFIG_IP_ADVANCED_ROUTER is not set
|
||||
CONFIG_IP_PNP=y
|
||||
# CONFIG_IP_PNP_DHCP is not set
|
||||
# CONFIG_IP_PNP_BOOTP is not set
|
||||
# CONFIG_IP_PNP_RARP is not set
|
||||
# CONFIG_NET_IPIP is not set
|
||||
# CONFIG_NET_IPGRE is not set
|
||||
# CONFIG_ARPD is not set
|
||||
# CONFIG_SYN_COOKIES is not set
|
||||
# CONFIG_INET_AH is not set
|
||||
# CONFIG_INET_ESP is not set
|
||||
# CONFIG_INET_IPCOMP is not set
|
||||
# CONFIG_INET_TUNNEL is not set
|
||||
# CONFIG_IP_TCPDIAG is not set
|
||||
# CONFIG_IP_TCPDIAG_IPV6 is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_NETFILTER is not set
|
||||
|
||||
#
|
||||
# SCTP Configuration (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_IP_SCTP is not set
|
||||
# CONFIG_ATM is not set
|
||||
# CONFIG_BRIDGE is not set
|
||||
# CONFIG_VLAN_8021Q is not set
|
||||
# CONFIG_DECNET is not set
|
||||
# CONFIG_LLC2 is not set
|
||||
# CONFIG_IPX is not set
|
||||
# CONFIG_ATALK is not set
|
||||
# CONFIG_X25 is not set
|
||||
# CONFIG_LAPB is not set
|
||||
# CONFIG_NET_DIVERT is not set
|
||||
# CONFIG_ECONET is not set
|
||||
# CONFIG_WAN_ROUTER is not set
|
||||
|
||||
#
|
||||
# QoS and/or fair queueing
|
||||
#
|
||||
# CONFIG_NET_SCHED is not set
|
||||
# CONFIG_NET_CLS_ROUTE is not set
|
||||
|
||||
#
|
||||
# Network testing
|
||||
#
|
||||
# CONFIG_NET_PKTGEN is not set
|
||||
# CONFIG_KGDBOE is not set
|
||||
# CONFIG_NETPOLL is not set
|
||||
# CONFIG_NETPOLL_RX is not set
|
||||
# CONFIG_NETPOLL_TRAP is not set
|
||||
# CONFIG_NET_POLL_CONTROLLER is not set
|
||||
# CONFIG_HAMRADIO is not set
|
||||
# CONFIG_IRDA is not set
|
||||
# CONFIG_BT is not set
|
||||
# CONFIG_IEEE80211 is not set
|
||||
CONFIG_NETDEVICES=y
|
||||
# CONFIG_DUMMY is not set
|
||||
# CONFIG_BONDING is not set
|
||||
# CONFIG_EQUALIZER is not set
|
||||
# CONFIG_TUN is not set
|
||||
|
||||
#
|
||||
# ARCnet devices
|
||||
#
|
||||
# CONFIG_ARCNET is not set
|
||||
|
||||
#
|
||||
# Ethernet (10 or 100Mbit)
|
||||
#
|
||||
CONFIG_NET_ETHERNET=y
|
||||
CONFIG_MII=y
|
||||
# CONFIG_HAPPYMEAL is not set
|
||||
# CONFIG_SUNGEM is not set
|
||||
# CONFIG_NET_VENDOR_3COM is not set
|
||||
|
||||
#
|
||||
# Tulip family network device support
|
||||
#
|
||||
# CONFIG_NET_TULIP is not set
|
||||
# CONFIG_HP100 is not set
|
||||
CONFIG_NET_PCI=y
|
||||
# CONFIG_PCNET32 is not set
|
||||
# CONFIG_AMD8111_ETH is not set
|
||||
# CONFIG_ADAPTEC_STARFIRE is not set
|
||||
# CONFIG_B44 is not set
|
||||
# CONFIG_FORCEDETH is not set
|
||||
# CONFIG_DGRS is not set
|
||||
# CONFIG_EEPRO100 is not set
|
||||
# CONFIG_E100 is not set
|
||||
# CONFIG_FEALNX is not set
|
||||
# CONFIG_NATSEMI is not set
|
||||
CONFIG_NE2K_PCI=y
|
||||
# CONFIG_8139CP is not set
|
||||
# CONFIG_8139TOO is not set
|
||||
# CONFIG_SIS900 is not set
|
||||
# CONFIG_EPIC100 is not set
|
||||
# CONFIG_SUNDANCE is not set
|
||||
# CONFIG_TLAN is not set
|
||||
# CONFIG_VIA_RHINE is not set
|
||||
|
||||
#
|
||||
# Ethernet (1000 Mbit)
|
||||
#
|
||||
# CONFIG_ACENIC is not set
|
||||
# CONFIG_DL2K is not set
|
||||
# CONFIG_E1000 is not set
|
||||
# CONFIG_NS83820 is not set
|
||||
# CONFIG_HAMACHI is not set
|
||||
# CONFIG_YELLOWFIN is not set
|
||||
# CONFIG_R8169 is not set
|
||||
# CONFIG_SKGE is not set
|
||||
# CONFIG_SK98LIN is not set
|
||||
# CONFIG_VIA_VELOCITY is not set
|
||||
# CONFIG_TIGON3 is not set
|
||||
|
||||
#
|
||||
# Ethernet (10000 Mbit)
|
||||
#
|
||||
# CONFIG_CHELSIO_T1 is not set
|
||||
# CONFIG_IXGB is not set
|
||||
# CONFIG_S2IO is not set
|
||||
|
||||
#
|
||||
# Token Ring devices
|
||||
#
|
||||
# CONFIG_TR is not set
|
||||
|
||||
#
|
||||
# Wireless LAN (non-hamradio)
|
||||
#
|
||||
# CONFIG_NET_RADIO is not set
|
||||
|
||||
#
|
||||
# Wan interfaces
|
||||
#
|
||||
# CONFIG_WAN is not set
|
||||
# CONFIG_FDDI is not set
|
||||
# CONFIG_HIPPI is not set
|
||||
# CONFIG_PPP is not set
|
||||
# CONFIG_SLIP is not set
|
||||
# CONFIG_SHAPER is not set
|
||||
# CONFIG_NETCONSOLE is not set
|
||||
|
||||
#
|
||||
# ISDN subsystem
|
||||
#
|
||||
# CONFIG_ISDN is not set
|
||||
|
||||
#
|
||||
# Telephony Support
|
||||
#
|
||||
# CONFIG_PHONE is not set
|
||||
|
||||
#
|
||||
# Input device support
|
||||
#
|
||||
# CONFIG_INPUT is not set
|
||||
|
||||
#
|
||||
# Hardware I/O ports
|
||||
#
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_GAMEPORT is not set
|
||||
|
||||
#
|
||||
# Character devices
|
||||
#
|
||||
# CONFIG_VT is not set
|
||||
# CONFIG_SERIAL_NONSTANDARD is not set
|
||||
|
||||
#
|
||||
# Serial drivers
|
||||
#
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=1
|
||||
CONFIG_SERIAL_8250_EXTENDED=y
|
||||
# CONFIG_SERIAL_8250_MANY_PORTS is not set
|
||||
CONFIG_SERIAL_8250_SHARE_IRQ=y
|
||||
# CONFIG_SERIAL_8250_DETECT_IRQ is not set
|
||||
# CONFIG_SERIAL_8250_MULTIPORT is not set
|
||||
# CONFIG_SERIAL_8250_RSA is not set
|
||||
|
||||
#
|
||||
# Non-8250 serial port support
|
||||
#
|
||||
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
|
||||
|
||||
#
|
||||
# IPMI
|
||||
#
|
||||
# CONFIG_IPMI_HANDLER is not set
|
||||
|
||||
#
|
||||
# Watchdog Cards
|
||||
#
|
||||
# CONFIG_WATCHDOG is not set
|
||||
# CONFIG_RTC is not set
|
||||
# CONFIG_GEN_RTC is not set
|
||||
# CONFIG_DTLK is not set
|
||||
# CONFIG_R3964 is not set
|
||||
# CONFIG_APPLICOM is not set
|
||||
|
||||
#
|
||||
# Ftape, the floppy tape device driver
|
||||
#
|
||||
# CONFIG_DRM is not set
|
||||
# CONFIG_RAW_DRIVER is not set
|
||||
|
||||
#
|
||||
# TPM devices
|
||||
#
|
||||
# CONFIG_TCG_TPM is not set
|
||||
|
||||
#
|
||||
# I2C support
|
||||
#
|
||||
# CONFIG_I2C is not set
|
||||
|
||||
#
|
||||
# Dallas's 1-wire bus
|
||||
#
|
||||
# CONFIG_W1 is not set
|
||||
|
||||
#
|
||||
# Misc devices
|
||||
#
|
||||
|
||||
#
|
||||
# Multimedia devices
|
||||
#
|
||||
# CONFIG_VIDEO_DEV is not set
|
||||
|
||||
#
|
||||
# Digital Video Broadcasting Devices
|
||||
#
|
||||
# CONFIG_DVB is not set
|
||||
|
||||
#
|
||||
# Graphics support
|
||||
#
|
||||
# CONFIG_FB is not set
|
||||
|
||||
#
|
||||
# Sound
|
||||
#
|
||||
# CONFIG_SOUND is not set
|
||||
|
||||
#
|
||||
# USB support
|
||||
#
|
||||
CONFIG_USB_ARCH_HAS_HCD=y
|
||||
CONFIG_USB_ARCH_HAS_OHCI=y
|
||||
# CONFIG_USB is not set
|
||||
|
||||
#
|
||||
# USB Gadget Support
|
||||
#
|
||||
# CONFIG_USB_GADGET is not set
|
||||
|
||||
#
|
||||
# MMC/SD Card support
|
||||
#
|
||||
# CONFIG_MMC is not set
|
||||
|
||||
#
|
||||
# InfiniBand support
|
||||
#
|
||||
# CONFIG_INFINIBAND is not set
|
||||
|
||||
#
|
||||
# File systems
|
||||
#
|
||||
# CONFIG_EXT2_FS is not set
|
||||
# CONFIG_EXT3_FS is not set
|
||||
# CONFIG_JBD is not set
|
||||
# CONFIG_REISER4_FS is not set
|
||||
# CONFIG_REISERFS_FS is not set
|
||||
# CONFIG_JFS_FS is not set
|
||||
|
||||
#
|
||||
# XFS support
|
||||
#
|
||||
# CONFIG_XFS_FS is not set
|
||||
# CONFIG_MINIX_FS is not set
|
||||
# CONFIG_ROMFS_FS is not set
|
||||
CONFIG_INOTIFY=y
|
||||
# CONFIG_QUOTA is not set
|
||||
CONFIG_DNOTIFY=y
|
||||
# CONFIG_AUTOFS_FS is not set
|
||||
# CONFIG_AUTOFS4_FS is not set
|
||||
|
||||
#
|
||||
# Caches
|
||||
#
|
||||
# CONFIG_FSCACHE is not set
|
||||
# CONFIG_FUSE_FS is not set
|
||||
|
||||
#
|
||||
# CD-ROM/DVD Filesystems
|
||||
#
|
||||
# CONFIG_ISO9660_FS is not set
|
||||
# CONFIG_UDF_FS is not set
|
||||
|
||||
#
|
||||
# DOS/FAT/NT Filesystems
|
||||
#
|
||||
# CONFIG_MSDOS_FS is not set
|
||||
# CONFIG_VFAT_FS is not set
|
||||
# CONFIG_NTFS_FS is not set
|
||||
|
||||
#
|
||||
# Pseudo filesystems
|
||||
#
|
||||
CONFIG_PROC_FS=y
|
||||
# CONFIG_PROC_KCORE is not set
|
||||
CONFIG_SYSFS=y
|
||||
# CONFIG_DEVFS_FS is not set
|
||||
# CONFIG_DEVPTS_FS_XATTR is not set
|
||||
CONFIG_TMPFS=y
|
||||
# CONFIG_TMPFS_XATTR is not set
|
||||
# CONFIG_HUGETLB_PAGE is not set
|
||||
CONFIG_RAMFS=y
|
||||
# CONFIG_RELAYFS_FS is not set
|
||||
|
||||
#
|
||||
# Miscellaneous filesystems
|
||||
#
|
||||
# CONFIG_ADFS_FS is not set
|
||||
# CONFIG_AFFS_FS is not set
|
||||
# CONFIG_HFS_FS is not set
|
||||
# CONFIG_HFSPLUS_FS is not set
|
||||
# CONFIG_BEFS_FS is not set
|
||||
# CONFIG_BFS_FS is not set
|
||||
# CONFIG_EFS_FS is not set
|
||||
# CONFIG_CRAMFS is not set
|
||||
# CONFIG_VXFS_FS is not set
|
||||
# CONFIG_HPFS_FS is not set
|
||||
# CONFIG_QNX4FS_FS is not set
|
||||
# CONFIG_SYSV_FS is not set
|
||||
# CONFIG_UFS_FS is not set
|
||||
|
||||
#
|
||||
# Network File Systems
|
||||
#
|
||||
CONFIG_NFS_FS=y
|
||||
# CONFIG_NFS_V3 is not set
|
||||
# CONFIG_NFS_V4 is not set
|
||||
# CONFIG_NFS_DIRECTIO is not set
|
||||
# CONFIG_NFSD is not set
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_LOCKD=y
|
||||
CONFIG_NFS_COMMON=y
|
||||
CONFIG_SUNRPC=y
|
||||
# CONFIG_RPCSEC_GSS_KRB5 is not set
|
||||
# CONFIG_RPCSEC_GSS_SPKM3 is not set
|
||||
# CONFIG_SMB_FS is not set
|
||||
# CONFIG_CIFS is not set
|
||||
# CONFIG_NCP_FS is not set
|
||||
# CONFIG_CODA_FS is not set
|
||||
# CONFIG_AFS_FS is not set
|
||||
|
||||
#
|
||||
# Partition Types
|
||||
#
|
||||
# CONFIG_PARTITION_ADVANCED is not set
|
||||
CONFIG_MSDOS_PARTITION=y
|
||||
|
||||
#
|
||||
# Native Language Support
|
||||
#
|
||||
# CONFIG_NLS is not set
|
||||
|
||||
#
|
||||
# Kernel hacking
|
||||
#
|
||||
# CONFIG_PRINTK_TIME is not set
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
# CONFIG_MAGIC_SYSRQ is not set
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
CONFIG_DETECT_SOFTLOCKUP=y
|
||||
# CONFIG_SCHEDSTATS is not set
|
||||
# CONFIG_DEBUG_SLAB is not set
|
||||
# CONFIG_DEBUG_SPINLOCK is not set
|
||||
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
|
||||
# CONFIG_DEBUG_KOBJECT is not set
|
||||
# CONFIG_DEBUG_HIGHMEM is not set
|
||||
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||
# CONFIG_DEBUG_INFO is not set
|
||||
# CONFIG_DEBUG_FS is not set
|
||||
# CONFIG_FRAME_POINTER is not set
|
||||
# CONFIG_EARLY_PRINTK is not set
|
||||
CONFIG_DEBUG_STACKOVERFLOW=y
|
||||
# CONFIG_DEBUG_PAGEALLOC is not set
|
||||
# CONFIG_GDBSTUB is not set
|
||||
|
||||
#
|
||||
# Security options
|
||||
#
|
||||
# CONFIG_KEYS is not set
|
||||
# CONFIG_SECURITY is not set
|
||||
|
||||
#
|
||||
# Cryptographic options
|
||||
#
|
||||
# CONFIG_CRYPTO is not set
|
||||
|
||||
#
|
||||
# Hardware crypto devices
|
||||
#
|
||||
|
||||
#
|
||||
# Library routines
|
||||
#
|
||||
# CONFIG_CRC_CCITT is not set
|
||||
CONFIG_CRC32=y
|
||||
# CONFIG_LIBCRC32C is not set
|
|
@ -435,6 +435,11 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c)
|
|||
if (c == &boot_cpu_data)
|
||||
sysenter_setup();
|
||||
enable_sep_cpu();
|
||||
|
||||
if (c == &boot_cpu_data)
|
||||
mtrr_bp_init();
|
||||
else
|
||||
mtrr_ap_init();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_HT
|
||||
|
|
|
@ -25,7 +25,7 @@ extern int trap_init_f00f_bug(void);
|
|||
/*
|
||||
* Alignment at which movsl is preferred for bulk memory copies.
|
||||
*/
|
||||
struct movsl_mask movsl_mask;
|
||||
struct movsl_mask movsl_mask __read_mostly;
|
||||
#endif
|
||||
|
||||
void __devinit early_intel_workaround(struct cpuinfo_x86 *c)
|
||||
|
|
|
@ -67,13 +67,6 @@ void __init get_mtrr_state(void)
|
|||
mtrr_state.enabled = (lo & 0xc00) >> 10;
|
||||
}
|
||||
|
||||
/* Free resources associated with a struct mtrr_state */
|
||||
void __init finalize_mtrr_state(void)
|
||||
{
|
||||
kfree(mtrr_state.var_ranges);
|
||||
mtrr_state.var_ranges = NULL;
|
||||
}
|
||||
|
||||
/* Some BIOS's are fucked and don't set all MTRRs the same! */
|
||||
void __init mtrr_state_warn(void)
|
||||
{
|
||||
|
@ -334,6 +327,9 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
|
|||
*/
|
||||
{
|
||||
unsigned long flags;
|
||||
struct mtrr_var_range *vr;
|
||||
|
||||
vr = &mtrr_state.var_ranges[reg];
|
||||
|
||||
local_irq_save(flags);
|
||||
prepare_set();
|
||||
|
@ -342,11 +338,15 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
|
|||
/* The invalid bit is kept in the mask, so we simply clear the
|
||||
relevant mask register to disable a range. */
|
||||
mtrr_wrmsr(MTRRphysMask_MSR(reg), 0, 0);
|
||||
memset(vr, 0, sizeof(struct mtrr_var_range));
|
||||
} else {
|
||||
mtrr_wrmsr(MTRRphysBase_MSR(reg), base << PAGE_SHIFT | type,
|
||||
(base & size_and_mask) >> (32 - PAGE_SHIFT));
|
||||
mtrr_wrmsr(MTRRphysMask_MSR(reg), -size << PAGE_SHIFT | 0x800,
|
||||
(-size & size_and_mask) >> (32 - PAGE_SHIFT));
|
||||
vr->base_lo = base << PAGE_SHIFT | type;
|
||||
vr->base_hi = (base & size_and_mask) >> (32 - PAGE_SHIFT);
|
||||
vr->mask_lo = -size << PAGE_SHIFT | 0x800;
|
||||
vr->mask_hi = (-size & size_and_mask) >> (32 - PAGE_SHIFT);
|
||||
|
||||
mtrr_wrmsr(MTRRphysBase_MSR(reg), vr->base_lo, vr->base_hi);
|
||||
mtrr_wrmsr(MTRRphysMask_MSR(reg), vr->mask_lo, vr->mask_hi);
|
||||
}
|
||||
|
||||
post_set();
|
||||
|
|
|
@ -332,6 +332,8 @@ int mtrr_add_page(unsigned long base, unsigned long size,
|
|||
|
||||
error = -EINVAL;
|
||||
|
||||
/* No CPU hotplug when we change MTRR entries */
|
||||
lock_cpu_hotplug();
|
||||
/* Search for existing MTRR */
|
||||
down(&main_lock);
|
||||
for (i = 0; i < num_var_ranges; ++i) {
|
||||
|
@ -372,6 +374,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
|
|||
error = i;
|
||||
out:
|
||||
up(&main_lock);
|
||||
unlock_cpu_hotplug();
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -461,6 +464,8 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
|
|||
return -ENXIO;
|
||||
|
||||
max = num_var_ranges;
|
||||
/* No CPU hotplug when we change MTRR entries */
|
||||
lock_cpu_hotplug();
|
||||
down(&main_lock);
|
||||
if (reg < 0) {
|
||||
/* Search for existing MTRR */
|
||||
|
@ -501,6 +506,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
|
|||
error = reg;
|
||||
out:
|
||||
up(&main_lock);
|
||||
unlock_cpu_hotplug();
|
||||
return error;
|
||||
}
|
||||
/**
|
||||
|
@ -544,21 +550,9 @@ static void __init init_ifs(void)
|
|||
centaur_init_mtrr();
|
||||
}
|
||||
|
||||
static void __init init_other_cpus(void)
|
||||
{
|
||||
if (use_intel())
|
||||
get_mtrr_state();
|
||||
|
||||
/* bring up the other processors */
|
||||
set_mtrr(~0U,0,0,0);
|
||||
|
||||
if (use_intel()) {
|
||||
finalize_mtrr_state();
|
||||
mtrr_state_warn();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The suspend/resume methods are only for CPU without MTRR. CPU using generic
|
||||
* MTRR driver doesn't require this
|
||||
*/
|
||||
struct mtrr_value {
|
||||
mtrr_type ltype;
|
||||
unsigned long lbase;
|
||||
|
@ -611,13 +605,13 @@ static struct sysdev_driver mtrr_sysdev_driver = {
|
|||
|
||||
|
||||
/**
|
||||
* mtrr_init - initialize mtrrs on the boot CPU
|
||||
* mtrr_bp_init - initialize mtrrs on the boot CPU
|
||||
*
|
||||
* This needs to be called early; before any of the other CPUs are
|
||||
* initialized (i.e. before smp_init()).
|
||||
*
|
||||
*/
|
||||
static int __init mtrr_init(void)
|
||||
void __init mtrr_bp_init(void)
|
||||
{
|
||||
init_ifs();
|
||||
|
||||
|
@ -674,12 +668,48 @@ static int __init mtrr_init(void)
|
|||
if (mtrr_if) {
|
||||
set_num_var_ranges();
|
||||
init_table();
|
||||
init_other_cpus();
|
||||
|
||||
return sysdev_driver_register(&cpu_sysdev_class,
|
||||
&mtrr_sysdev_driver);
|
||||
if (use_intel())
|
||||
get_mtrr_state();
|
||||
}
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
subsys_initcall(mtrr_init);
|
||||
void mtrr_ap_init(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!mtrr_if || !use_intel())
|
||||
return;
|
||||
/*
|
||||
* Ideally we should hold main_lock here to avoid mtrr entries changed,
|
||||
* but this routine will be called in cpu boot time, holding the lock
|
||||
* breaks it. This routine is called in two cases: 1.very earily time
|
||||
* of software resume, when there absolutely isn't mtrr entry changes;
|
||||
* 2.cpu hotadd time. We let mtrr_add/del_page hold cpuhotplug lock to
|
||||
* prevent mtrr entry changes
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
|
||||
mtrr_if->set_all();
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static int __init mtrr_init_finialize(void)
|
||||
{
|
||||
if (!mtrr_if)
|
||||
return 0;
|
||||
if (use_intel())
|
||||
mtrr_state_warn();
|
||||
else {
|
||||
/* The CPUs haven't MTRR and seemes not support SMP. They have
|
||||
* specific drivers, we use a tricky method to support
|
||||
* suspend/resume for them.
|
||||
* TBD: is there any system with such CPU which supports
|
||||
* suspend/resume? if no, we should remove the code.
|
||||
*/
|
||||
sysdev_driver_register(&cpu_sysdev_class,
|
||||
&mtrr_sysdev_driver);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(mtrr_init_finialize);
|
||||
|
|
|
@ -91,7 +91,6 @@ extern struct mtrr_ops * mtrr_if;
|
|||
|
||||
extern unsigned int num_var_ranges;
|
||||
|
||||
void finalize_mtrr_state(void);
|
||||
void mtrr_state_warn(void);
|
||||
char *mtrr_attrib_to_str(int x);
|
||||
void mtrr_wrmsr(unsigned, unsigned, unsigned);
|
||||
|
|
|
@ -68,21 +68,21 @@ EXPORT_SYMBOL(smp_num_siblings);
|
|||
#endif
|
||||
|
||||
/* Package ID of each logical CPU */
|
||||
int phys_proc_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID};
|
||||
int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
|
||||
EXPORT_SYMBOL(phys_proc_id);
|
||||
|
||||
/* Core ID of each logical CPU */
|
||||
int cpu_core_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID};
|
||||
int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
|
||||
EXPORT_SYMBOL(cpu_core_id);
|
||||
|
||||
cpumask_t cpu_sibling_map[NR_CPUS];
|
||||
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
|
||||
EXPORT_SYMBOL(cpu_sibling_map);
|
||||
|
||||
cpumask_t cpu_core_map[NR_CPUS];
|
||||
cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
|
||||
EXPORT_SYMBOL(cpu_core_map);
|
||||
|
||||
/* bitmap of online cpus */
|
||||
cpumask_t cpu_online_map;
|
||||
cpumask_t cpu_online_map __read_mostly;
|
||||
EXPORT_SYMBOL(cpu_online_map);
|
||||
|
||||
cpumask_t cpu_callin_map;
|
||||
|
@ -100,7 +100,7 @@ static int __devinitdata tsc_sync_disabled;
|
|||
struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
|
||||
EXPORT_SYMBOL(cpu_data);
|
||||
|
||||
u8 x86_cpu_to_apicid[NR_CPUS] =
|
||||
u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly =
|
||||
{ [0 ... NR_CPUS-1] = 0xff };
|
||||
EXPORT_SYMBOL(x86_cpu_to_apicid);
|
||||
|
||||
|
@ -550,10 +550,10 @@ extern struct {
|
|||
#ifdef CONFIG_NUMA
|
||||
|
||||
/* which logical CPUs are on which nodes */
|
||||
cpumask_t node_2_cpu_mask[MAX_NUMNODES] =
|
||||
cpumask_t node_2_cpu_mask[MAX_NUMNODES] __read_mostly =
|
||||
{ [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE };
|
||||
/* which node each logical CPU is on */
|
||||
int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 };
|
||||
int cpu_2_node[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 };
|
||||
EXPORT_SYMBOL(cpu_2_node);
|
||||
|
||||
/* set up a mapping between cpu and node. */
|
||||
|
@ -581,7 +581,7 @@ static inline void unmap_cpu_to_node(int cpu)
|
|||
|
||||
#endif /* CONFIG_NUMA */
|
||||
|
||||
u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
|
||||
u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
|
||||
|
||||
static void map_cpu_to_logical_apicid(void)
|
||||
{
|
||||
|
|
|
@ -91,7 +91,7 @@ EXPORT_SYMBOL(rtc_lock);
|
|||
DEFINE_SPINLOCK(i8253_lock);
|
||||
EXPORT_SYMBOL(i8253_lock);
|
||||
|
||||
struct timer_opts *cur_timer = &timer_none;
|
||||
struct timer_opts *cur_timer __read_mostly = &timer_none;
|
||||
|
||||
/*
|
||||
* This is a special lock that is owned by the CPU and holds the index
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "mach_timer.h"
|
||||
#include <asm/hpet.h>
|
||||
|
||||
static unsigned long hpet_usec_quotient; /* convert hpet clks to usec */
|
||||
static unsigned long __read_mostly hpet_usec_quotient; /* convert hpet clks to usec */
|
||||
static unsigned long tsc_hpet_quotient; /* convert tsc to hpet clks */
|
||||
static unsigned long hpet_last; /* hpet counter value at last tick*/
|
||||
static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
|
||||
|
@ -180,7 +180,7 @@ static int __init init_hpet(char* override)
|
|||
/************************************************************/
|
||||
|
||||
/* tsc timer_opts struct */
|
||||
static struct timer_opts timer_hpet = {
|
||||
static struct timer_opts timer_hpet __read_mostly = {
|
||||
.name = "hpet",
|
||||
.mark_offset = mark_offset_hpet,
|
||||
.get_offset = get_offset_hpet,
|
||||
|
|
|
@ -57,6 +57,9 @@ SECTIONS
|
|||
*(.data.cacheline_aligned)
|
||||
}
|
||||
|
||||
/* rarely changed data like cpu maps */
|
||||
. = ALIGN(32);
|
||||
.data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
|
||||
_edata = .; /* End of data section */
|
||||
|
||||
. = ALIGN(THREAD_SIZE); /* init_task */
|
||||
|
|
|
@ -228,7 +228,8 @@ EXPORT_SYMBOL(ioremap_nocache);
|
|||
void iounmap(volatile void __iomem *addr)
|
||||
{
|
||||
struct vm_struct *p;
|
||||
if ((void __force *) addr <= high_memory)
|
||||
|
||||
if ((void __force *)addr <= high_memory)
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -241,9 +242,10 @@ void iounmap(volatile void __iomem *addr)
|
|||
return;
|
||||
|
||||
write_lock(&vmlist_lock);
|
||||
p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
|
||||
p = __remove_vm_area((void *)(PAGE_MASK & (unsigned long __force)addr));
|
||||
if (!p) {
|
||||
printk(KERN_WARNING "iounmap: bad address %p\n", addr);
|
||||
dump_stack();
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
|
|
|
@ -137,6 +137,7 @@ void __restore_processor_state(struct saved_context *ctxt)
|
|||
|
||||
fix_processor_context();
|
||||
do_fpu_end();
|
||||
mtrr_ap_init();
|
||||
}
|
||||
|
||||
void restore_processor_state(void)
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
*
|
||||
* Setup routines for Renesas M32700UT Board
|
||||
*
|
||||
* Copyright (c) 2002 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Takeo Takahashi
|
||||
* Copyright (c) 2002-2005 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Takeo Takahashi
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file "COPYING" in the main directory of this
|
||||
|
@ -435,7 +435,7 @@ void __init init_IRQ(void)
|
|||
icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
|
||||
enable_m32700ut_irq(M32R_IRQ_INT2);
|
||||
|
||||
//#if defined(CONFIG_VIDEO_M32R_AR)
|
||||
#if defined(CONFIG_VIDEO_M32R_AR)
|
||||
/*
|
||||
* INT3# is used for AR
|
||||
*/
|
||||
|
@ -445,9 +445,11 @@ void __init init_IRQ(void)
|
|||
irq_desc[M32R_IRQ_INT3].depth = 1;
|
||||
icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
|
||||
disable_m32700ut_irq(M32R_IRQ_INT3);
|
||||
//#endif /* CONFIG_VIDEO_M32R_AR */
|
||||
#endif /* CONFIG_VIDEO_M32R_AR */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SMC91X)
|
||||
|
||||
#define LAN_IOSTART 0x300
|
||||
#define LAN_IOEND 0x320
|
||||
static struct resource smc91x_resources[] = {
|
||||
|
@ -469,10 +471,55 @@ static struct platform_device smc91x_device = {
|
|||
.num_resources = ARRAY_SIZE(smc91x_resources),
|
||||
.resource = smc91x_resources,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FB_S1D13XXX)
|
||||
|
||||
#include <video/s1d13xxxfb.h>
|
||||
#include <asm/s1d13806.h>
|
||||
|
||||
static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
|
||||
.initregs = s1d13xxxfb_initregs,
|
||||
.initregssize = ARRAY_SIZE(s1d13xxxfb_initregs),
|
||||
.platform_init_video = NULL,
|
||||
#ifdef CONFIG_PM
|
||||
.platform_suspend_video = NULL,
|
||||
.platform_resume_video = NULL,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct resource s1d13xxxfb_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x10600000UL,
|
||||
.end = 0x1073FFFFUL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = 0x10400000UL,
|
||||
.end = 0x104001FFUL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device s1d13xxxfb_device = {
|
||||
.name = S1D_DEVICENAME,
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &s1d13xxxfb_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(s1d13xxxfb_resources),
|
||||
.resource = s1d13xxxfb_resources,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init platform_init(void)
|
||||
{
|
||||
#if defined(CONFIG_SMC91X)
|
||||
platform_device_register(&smc91x_device);
|
||||
#endif
|
||||
#if defined(CONFIG_FB_S1D13XXX)
|
||||
platform_device_register(&s1d13xxxfb_device);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(platform_init);
|
||||
|
|
|
@ -3,14 +3,15 @@
|
|||
*
|
||||
* Setup routines for Renesas MAPPI Board
|
||||
*
|
||||
* Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto
|
||||
* Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/m32r.h>
|
||||
|
@ -158,3 +159,49 @@ void __init init_IRQ(void)
|
|||
disable_mappi_irq(M32R_IRQ_INT2);
|
||||
#endif /* CONFIG_M32RPCC */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FB_S1D13XXX)
|
||||
|
||||
#include <video/s1d13xxxfb.h>
|
||||
#include <asm/s1d13806.h>
|
||||
|
||||
static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
|
||||
.initregs = s1d13xxxfb_initregs,
|
||||
.initregssize = ARRAY_SIZE(s1d13xxxfb_initregs),
|
||||
.platform_init_video = NULL,
|
||||
#ifdef CONFIG_PM
|
||||
.platform_suspend_video = NULL,
|
||||
.platform_resume_video = NULL,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct resource s1d13xxxfb_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x10200000UL,
|
||||
.end = 0x1033FFFFUL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = 0x10000000UL,
|
||||
.end = 0x100001FFUL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device s1d13xxxfb_device = {
|
||||
.name = S1D_DEVICENAME,
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &s1d13xxxfb_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(s1d13xxxfb_resources),
|
||||
.resource = s1d13xxxfb_resources,
|
||||
};
|
||||
|
||||
static int __init platform_init(void)
|
||||
{
|
||||
platform_device_register(&s1d13xxxfb_device);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(platform_init);
|
||||
#endif
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
*
|
||||
* Setup routines for Renesas MAPPI-II(M3A-ZA36) Board
|
||||
*
|
||||
* Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Mamoru Sakugawa
|
||||
* Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Mamoru Sakugawa
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
*
|
||||
* Setup routines for Renesas MAPPI-III(M3A-2170) Board
|
||||
*
|
||||
* Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Mamoru Sakugawa
|
||||
* Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Mamoru Sakugawa
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
@ -178,6 +178,8 @@ void __init init_IRQ(void)
|
|||
#endif /* CONFIG_M32R_CFC */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SMC91X)
|
||||
|
||||
#define LAN_IOSTART 0x300
|
||||
#define LAN_IOEND 0x320
|
||||
static struct resource smc91x_resources[] = {
|
||||
|
@ -200,9 +202,55 @@ static struct platform_device smc91x_device = {
|
|||
.resource = smc91x_resources,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FB_S1D13XXX)
|
||||
|
||||
#include <video/s1d13xxxfb.h>
|
||||
#include <asm/s1d13806.h>
|
||||
|
||||
static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
|
||||
.initregs = s1d13xxxfb_initregs,
|
||||
.initregssize = ARRAY_SIZE(s1d13xxxfb_initregs),
|
||||
.platform_init_video = NULL,
|
||||
#ifdef CONFIG_PM
|
||||
.platform_suspend_video = NULL,
|
||||
.platform_resume_video = NULL,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct resource s1d13xxxfb_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x1d600000UL,
|
||||
.end = 0x1d73FFFFUL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = 0x1d400000UL,
|
||||
.end = 0x1d4001FFUL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device s1d13xxxfb_device = {
|
||||
.name = S1D_DEVICENAME,
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &s1d13xxxfb_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(s1d13xxxfb_resources),
|
||||
.resource = s1d13xxxfb_resources,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init platform_init(void)
|
||||
{
|
||||
#if defined(CONFIG_SMC91X)
|
||||
platform_device_register(&smc91x_device);
|
||||
#endif
|
||||
#if defined(CONFIG_FB_S1D13XXX)
|
||||
platform_device_register(&s1d13xxxfb_device);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(platform_init);
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
*
|
||||
* Setup routines for OAKS32R Board
|
||||
*
|
||||
* Copyright (c) 2002-2004 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Mamoru Sakugawa
|
||||
* Copyright (c) 2002-2005 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Mamoru Sakugawa
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
@ -139,5 +139,4 @@ void __init init_IRQ(void)
|
|||
icu_data[M32R_IRQ_SIO1_S].icucr = 0;
|
||||
disable_oaks32r_irq(M32R_IRQ_SIO1_S);
|
||||
#endif /* CONFIG_SERIAL_M32R_SIO */
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Setup routines for Renesas OPSPUT Board
|
||||
*
|
||||
* Copyright (c) 2002-2004
|
||||
* Copyright (c) 2002-2005
|
||||
* Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Takeo Takahashi, Mamoru Sakugawa
|
||||
*
|
||||
|
@ -439,7 +439,7 @@ void __init init_IRQ(void)
|
|||
icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
|
||||
enable_opsput_irq(M32R_IRQ_INT2);
|
||||
|
||||
//#if defined(CONFIG_VIDEO_M32R_AR)
|
||||
#if defined(CONFIG_VIDEO_M32R_AR)
|
||||
/*
|
||||
* INT3# is used for AR
|
||||
*/
|
||||
|
@ -449,9 +449,11 @@ void __init init_IRQ(void)
|
|||
irq_desc[M32R_IRQ_INT3].depth = 1;
|
||||
icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
|
||||
disable_opsput_irq(M32R_IRQ_INT3);
|
||||
//#endif /* CONFIG_VIDEO_M32R_AR */
|
||||
#endif /* CONFIG_VIDEO_M32R_AR */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SMC91X)
|
||||
|
||||
#define LAN_IOSTART 0x300
|
||||
#define LAN_IOEND 0x320
|
||||
static struct resource smc91x_resources[] = {
|
||||
|
@ -473,10 +475,55 @@ static struct platform_device smc91x_device = {
|
|||
.num_resources = ARRAY_SIZE(smc91x_resources),
|
||||
.resource = smc91x_resources,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FB_S1D13XXX)
|
||||
|
||||
#include <video/s1d13xxxfb.h>
|
||||
#include <asm/s1d13806.h>
|
||||
|
||||
static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
|
||||
.initregs = s1d13xxxfb_initregs,
|
||||
.initregssize = ARRAY_SIZE(s1d13xxxfb_initregs),
|
||||
.platform_init_video = NULL,
|
||||
#ifdef CONFIG_PM
|
||||
.platform_suspend_video = NULL,
|
||||
.platform_resume_video = NULL,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct resource s1d13xxxfb_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x10600000UL,
|
||||
.end = 0x1073FFFFUL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = 0x10400000UL,
|
||||
.end = 0x104001FFUL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device s1d13xxxfb_device = {
|
||||
.name = S1D_DEVICENAME,
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &s1d13xxxfb_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(s1d13xxxfb_resources),
|
||||
.resource = s1d13xxxfb_resources,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init platform_init(void)
|
||||
{
|
||||
#if defined(CONFIG_SMC91X)
|
||||
platform_device_register(&smc91x_device);
|
||||
#endif
|
||||
#if defined(CONFIG_FB_S1D13XXX)
|
||||
platform_device_register(&s1d13xxxfb_device);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(platform_init);
|
||||
|
|
|
@ -452,7 +452,7 @@ static u32 __pmac read_gpio(struct device_node *np)
|
|||
return offset;
|
||||
}
|
||||
|
||||
static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, u32 state)
|
||||
static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg)
|
||||
{
|
||||
/* Ok, this could be made a bit smarter, but let's be robust for now. We
|
||||
* always force a speed change to high speed before sleep, to make sure
|
||||
|
|
|
@ -49,160 +49,219 @@ extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);
|
|||
#endif
|
||||
|
||||
struct cpu_spec cpu_specs[] = {
|
||||
{ /* Power3 */
|
||||
0xffff0000, 0x00400000, "POWER3 (630)",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_IABR | CPU_FTR_PMC8,
|
||||
COMMON_USER_PPC64,
|
||||
128, 128,
|
||||
__setup_cpu_power3,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* Power3+ */
|
||||
0xffff0000, 0x00410000, "POWER3 (630+)",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_IABR | CPU_FTR_PMC8,
|
||||
COMMON_USER_PPC64,
|
||||
128, 128,
|
||||
__setup_cpu_power3,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* Northstar */
|
||||
0xffff0000, 0x00330000, "RS64-II (northstar)",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
COMMON_USER_PPC64,
|
||||
128, 128,
|
||||
__setup_cpu_power3,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* Pulsar */
|
||||
0xffff0000, 0x00340000, "RS64-III (pulsar)",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
COMMON_USER_PPC64,
|
||||
128, 128,
|
||||
__setup_cpu_power3,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* I-star */
|
||||
0xffff0000, 0x00360000, "RS64-III (icestar)",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
COMMON_USER_PPC64,
|
||||
128, 128,
|
||||
__setup_cpu_power3,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* S-star */
|
||||
0xffff0000, 0x00370000, "RS64-IV (sstar)",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
COMMON_USER_PPC64,
|
||||
128, 128,
|
||||
__setup_cpu_power3,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* Power4 */
|
||||
0xffff0000, 0x00350000, "POWER4 (gp)",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
COMMON_USER_PPC64,
|
||||
128, 128,
|
||||
__setup_cpu_power4,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* Power4+ */
|
||||
0xffff0000, 0x00380000, "POWER4+ (gq)",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
COMMON_USER_PPC64,
|
||||
128, 128,
|
||||
__setup_cpu_power4,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* PPC970 */
|
||||
0xffff0000, 0x00390000, "PPC970",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
|
||||
CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
|
||||
128, 128,
|
||||
__setup_cpu_ppc970,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* PPC970FX */
|
||||
0xffff0000, 0x003c0000, "PPC970FX",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
|
||||
CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
|
||||
128, 128,
|
||||
__setup_cpu_ppc970,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* Power5 */
|
||||
0xffff0000, 0x003a0000, "POWER5 (gr)",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
|
||||
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
|
||||
CPU_FTR_MMCRA_SIHV,
|
||||
COMMON_USER_PPC64,
|
||||
128, 128,
|
||||
__setup_cpu_power4,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* Power5 */
|
||||
0xffff0000, 0x003b0000, "POWER5 (gs)",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
|
||||
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
|
||||
CPU_FTR_MMCRA_SIHV,
|
||||
COMMON_USER_PPC64,
|
||||
128, 128,
|
||||
__setup_cpu_power4,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* BE DD1.x */
|
||||
0xffff0000, 0x00700000, "Broadband Engine",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
|
||||
CPU_FTR_SMT,
|
||||
COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
|
||||
128, 128,
|
||||
__setup_cpu_be,
|
||||
COMMON_PPC64_FW
|
||||
},
|
||||
{ /* default match */
|
||||
0x00000000, 0x00000000, "POWER4 (compatible)",
|
||||
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2,
|
||||
COMMON_USER_PPC64,
|
||||
128, 128,
|
||||
__setup_cpu_power4,
|
||||
COMMON_PPC64_FW
|
||||
}
|
||||
{ /* Power3 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00400000,
|
||||
.cpu_name = "POWER3 (630)",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
|
||||
CPU_FTR_PMC8,
|
||||
.cpu_user_features = COMMON_USER_PPC64,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power3,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* Power3+ */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00410000,
|
||||
.cpu_name = "POWER3 (630+)",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
|
||||
CPU_FTR_PMC8,
|
||||
.cpu_user_features = COMMON_USER_PPC64,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power3,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* Northstar */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00330000,
|
||||
.cpu_name = "RS64-II (northstar)",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
|
||||
CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
|
||||
.cpu_user_features = COMMON_USER_PPC64,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power3,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* Pulsar */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00340000,
|
||||
.cpu_name = "RS64-III (pulsar)",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
|
||||
CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
|
||||
.cpu_user_features = COMMON_USER_PPC64,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power3,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* I-star */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00360000,
|
||||
.cpu_name = "RS64-III (icestar)",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
|
||||
CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
|
||||
.cpu_user_features = COMMON_USER_PPC64,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power3,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* S-star */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00370000,
|
||||
.cpu_name = "RS64-IV (sstar)",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
|
||||
CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
|
||||
.cpu_user_features = COMMON_USER_PPC64,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power3,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* Power4 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00350000,
|
||||
.cpu_name = "POWER4 (gp)",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
.cpu_user_features = COMMON_USER_PPC64,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power4,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* Power4+ */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00380000,
|
||||
.cpu_name = "POWER4+ (gq)",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
.cpu_user_features = COMMON_USER_PPC64,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power4,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* PPC970 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00390000,
|
||||
.cpu_name = "PPC970",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
|
||||
CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
.cpu_user_features = COMMON_USER_PPC64 |
|
||||
PPC_FEATURE_HAS_ALTIVEC_COMP,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_ppc970,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* PPC970FX */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x003c0000,
|
||||
.cpu_name = "PPC970FX",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
|
||||
CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
|
||||
.cpu_user_features = COMMON_USER_PPC64 |
|
||||
PPC_FEATURE_HAS_ALTIVEC_COMP,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_ppc970,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* Power5 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x003a0000,
|
||||
.cpu_name = "POWER5 (gr)",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
|
||||
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
|
||||
CPU_FTR_MMCRA_SIHV,
|
||||
.cpu_user_features = COMMON_USER_PPC64,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power4,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* Power5 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x003b0000,
|
||||
.cpu_name = "POWER5 (gs)",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
|
||||
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
|
||||
CPU_FTR_MMCRA_SIHV,
|
||||
.cpu_user_features = COMMON_USER_PPC64,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power4,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* BE DD1.x */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00700000,
|
||||
.cpu_name = "Broadband Engine",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
|
||||
CPU_FTR_SMT,
|
||||
.cpu_user_features = COMMON_USER_PPC64 |
|
||||
PPC_FEATURE_HAS_ALTIVEC_COMP,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_be,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
},
|
||||
{ /* default match */
|
||||
.pvr_mask = 0x00000000,
|
||||
.pvr_value = 0x00000000,
|
||||
.cpu_name = "POWER4 (compatible)",
|
||||
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
|
||||
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
|
||||
CPU_FTR_PPCAS_ARCH_V2,
|
||||
.cpu_user_features = COMMON_USER_PPC64,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power4,
|
||||
.firmware_features = COMMON_PPC64_FW,
|
||||
}
|
||||
};
|
||||
|
||||
firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = {
|
||||
{FW_FEATURE_PFT, "hcall-pft"},
|
||||
{FW_FEATURE_TCE, "hcall-tce"},
|
||||
{FW_FEATURE_SPRG0, "hcall-sprg0"},
|
||||
{FW_FEATURE_DABR, "hcall-dabr"},
|
||||
{FW_FEATURE_COPY, "hcall-copy"},
|
||||
{FW_FEATURE_ASR, "hcall-asr"},
|
||||
{FW_FEATURE_DEBUG, "hcall-debug"},
|
||||
{FW_FEATURE_PERF, "hcall-perf"},
|
||||
{FW_FEATURE_DUMP, "hcall-dump"},
|
||||
{FW_FEATURE_INTERRUPT, "hcall-interrupt"},
|
||||
{FW_FEATURE_MIGRATE, "hcall-migrate"},
|
||||
{FW_FEATURE_PERFMON, "hcall-perfmon"},
|
||||
{FW_FEATURE_CRQ, "hcall-crq"},
|
||||
{FW_FEATURE_VIO, "hcall-vio"},
|
||||
{FW_FEATURE_RDMA, "hcall-rdma"},
|
||||
{FW_FEATURE_LLAN, "hcall-lLAN"},
|
||||
{FW_FEATURE_BULK, "hcall-bulk"},
|
||||
{FW_FEATURE_XDABR, "hcall-xdabr"},
|
||||
{FW_FEATURE_MULTITCE, "hcall-multi-tce"},
|
||||
{FW_FEATURE_SPLPAR, "hcall-splpar"},
|
||||
{FW_FEATURE_PFT, "hcall-pft"},
|
||||
{FW_FEATURE_TCE, "hcall-tce"},
|
||||
{FW_FEATURE_SPRG0, "hcall-sprg0"},
|
||||
{FW_FEATURE_DABR, "hcall-dabr"},
|
||||
{FW_FEATURE_COPY, "hcall-copy"},
|
||||
{FW_FEATURE_ASR, "hcall-asr"},
|
||||
{FW_FEATURE_DEBUG, "hcall-debug"},
|
||||
{FW_FEATURE_PERF, "hcall-perf"},
|
||||
{FW_FEATURE_DUMP, "hcall-dump"},
|
||||
{FW_FEATURE_INTERRUPT, "hcall-interrupt"},
|
||||
{FW_FEATURE_MIGRATE, "hcall-migrate"},
|
||||
{FW_FEATURE_PERFMON, "hcall-perfmon"},
|
||||
{FW_FEATURE_CRQ, "hcall-crq"},
|
||||
{FW_FEATURE_VIO, "hcall-vio"},
|
||||
{FW_FEATURE_RDMA, "hcall-rdma"},
|
||||
{FW_FEATURE_LLAN, "hcall-lLAN"},
|
||||
{FW_FEATURE_BULK, "hcall-bulk"},
|
||||
{FW_FEATURE_XDABR, "hcall-xdabr"},
|
||||
{FW_FEATURE_MULTITCE, "hcall-multi-tce"},
|
||||
{FW_FEATURE_SPLPAR, "hcall-splpar"},
|
||||
};
|
||||
|
|
|
@ -308,6 +308,7 @@ exception_marker:
|
|||
label##_pSeries: \
|
||||
HMT_MEDIUM; \
|
||||
mtspr SPRG1,r13; /* save r13 */ \
|
||||
RUNLATCH_ON(r13); \
|
||||
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
|
||||
|
||||
#define STD_EXCEPTION_ISERIES(n, label, area) \
|
||||
|
@ -315,6 +316,7 @@ label##_pSeries: \
|
|||
label##_iSeries: \
|
||||
HMT_MEDIUM; \
|
||||
mtspr SPRG1,r13; /* save r13 */ \
|
||||
RUNLATCH_ON(r13); \
|
||||
EXCEPTION_PROLOG_ISERIES_1(area); \
|
||||
EXCEPTION_PROLOG_ISERIES_2; \
|
||||
b label##_common
|
||||
|
@ -324,6 +326,7 @@ label##_iSeries: \
|
|||
label##_iSeries: \
|
||||
HMT_MEDIUM; \
|
||||
mtspr SPRG1,r13; /* save r13 */ \
|
||||
RUNLATCH_ON(r13); \
|
||||
EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \
|
||||
lbz r10,PACAPROCENABLED(r13); \
|
||||
cmpwi 0,r10,0; \
|
||||
|
@ -393,6 +396,7 @@ __start_interrupts:
|
|||
_machine_check_pSeries:
|
||||
HMT_MEDIUM
|
||||
mtspr SPRG1,r13 /* save r13 */
|
||||
RUNLATCH_ON(r13)
|
||||
EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
|
||||
|
||||
. = 0x300
|
||||
|
@ -419,6 +423,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
|
|||
data_access_slb_pSeries:
|
||||
HMT_MEDIUM
|
||||
mtspr SPRG1,r13
|
||||
RUNLATCH_ON(r13)
|
||||
mfspr r13,SPRG3 /* get paca address into r13 */
|
||||
std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
|
||||
std r10,PACA_EXSLB+EX_R10(r13)
|
||||
|
@ -439,6 +444,7 @@ data_access_slb_pSeries:
|
|||
instruction_access_slb_pSeries:
|
||||
HMT_MEDIUM
|
||||
mtspr SPRG1,r13
|
||||
RUNLATCH_ON(r13)
|
||||
mfspr r13,SPRG3 /* get paca address into r13 */
|
||||
std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */
|
||||
std r10,PACA_EXSLB+EX_R10(r13)
|
||||
|
@ -464,6 +470,7 @@ instruction_access_slb_pSeries:
|
|||
.globl system_call_pSeries
|
||||
system_call_pSeries:
|
||||
HMT_MEDIUM
|
||||
RUNLATCH_ON(r9)
|
||||
mr r9,r13
|
||||
mfmsr r10
|
||||
mfspr r13,SPRG3
|
||||
|
@ -707,11 +714,13 @@ fwnmi_data_area:
|
|||
system_reset_fwnmi:
|
||||
HMT_MEDIUM
|
||||
mtspr SPRG1,r13 /* save r13 */
|
||||
RUNLATCH_ON(r13)
|
||||
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
|
||||
.globl machine_check_fwnmi
|
||||
machine_check_fwnmi:
|
||||
HMT_MEDIUM
|
||||
mtspr SPRG1,r13 /* save r13 */
|
||||
RUNLATCH_ON(r13)
|
||||
EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
|
||||
|
||||
/*
|
||||
|
@ -848,6 +857,7 @@ unrecov_fer:
|
|||
.align 7
|
||||
.globl data_access_common
|
||||
data_access_common:
|
||||
RUNLATCH_ON(r10) /* It wont fit in the 0x300 handler */
|
||||
mfspr r10,DAR
|
||||
std r10,PACA_EXGEN+EX_DAR(r13)
|
||||
mfspr r10,DSISR
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <linux/module.h>
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/hvconsole.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
/**
|
||||
* hvc_get_chars - retrieve characters from firmware for denoted vterm adatper
|
||||
|
@ -42,29 +41,14 @@ int hvc_get_chars(uint32_t vtermno, char *buf, int count)
|
|||
unsigned long got;
|
||||
|
||||
if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
|
||||
(unsigned long *)buf, (unsigned long *)buf+1) == H_Success) {
|
||||
/*
|
||||
* Work around a HV bug where it gives us a null
|
||||
* after every \r. -- paulus
|
||||
*/
|
||||
if (got > 0) {
|
||||
int i;
|
||||
for (i = 1; i < got; ++i) {
|
||||
if (buf[i] == 0 && buf[i-1] == '\r') {
|
||||
--got;
|
||||
if (i < got)
|
||||
memmove(&buf[i], &buf[i+1],
|
||||
got - i);
|
||||
}
|
||||
}
|
||||
}
|
||||
(unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
|
||||
return got;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(hvc_get_chars);
|
||||
|
||||
|
||||
/**
|
||||
* hvc_put_chars: send characters to firmware for denoted vterm adapter
|
||||
* @vtermno: The vtermno or unit_address of the adapter from which the data
|
||||
|
@ -88,34 +72,3 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
|
|||
}
|
||||
|
||||
EXPORT_SYMBOL(hvc_put_chars);
|
||||
|
||||
/*
|
||||
* We hope/assume that the first vty found corresponds to the first console
|
||||
* device.
|
||||
*/
|
||||
int hvc_find_vtys(void)
|
||||
{
|
||||
struct device_node *vty;
|
||||
int num_found = 0;
|
||||
|
||||
for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
|
||||
vty = of_find_node_by_name(vty, "vty")) {
|
||||
uint32_t *vtermno;
|
||||
|
||||
/* We have statically defined space for only a certain number of
|
||||
* console adapters. */
|
||||
if (num_found >= MAX_NR_HVC_CONSOLES)
|
||||
break;
|
||||
|
||||
vtermno = (uint32_t *)get_property(vty, "reg", NULL);
|
||||
if (!vtermno)
|
||||
continue;
|
||||
|
||||
if (device_is_compatible(vty, "hvterm1")) {
|
||||
hvc_instantiate(*vtermno, num_found);
|
||||
++num_found;
|
||||
}
|
||||
}
|
||||
|
||||
return num_found;
|
||||
}
|
||||
|
|
|
@ -834,6 +834,92 @@ static int __init iSeries_src_init(void)
|
|||
|
||||
late_initcall(iSeries_src_init);
|
||||
|
||||
static inline void process_iSeries_events(void)
|
||||
{
|
||||
asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
|
||||
}
|
||||
|
||||
static void yield_shared_processor(void)
|
||||
{
|
||||
unsigned long tb;
|
||||
|
||||
HvCall_setEnabledInterrupts(HvCall_MaskIPI |
|
||||
HvCall_MaskLpEvent |
|
||||
HvCall_MaskLpProd |
|
||||
HvCall_MaskTimeout);
|
||||
|
||||
tb = get_tb();
|
||||
/* Compute future tb value when yield should expire */
|
||||
HvCall_yieldProcessor(HvCall_YieldTimed, tb+tb_ticks_per_jiffy);
|
||||
|
||||
/*
|
||||
* The decrementer stops during the yield. Force a fake decrementer
|
||||
* here and let the timer_interrupt code sort out the actual time.
|
||||
*/
|
||||
get_paca()->lppaca.int_dword.fields.decr_int = 1;
|
||||
process_iSeries_events();
|
||||
}
|
||||
|
||||
static int iseries_shared_idle(void)
|
||||
{
|
||||
while (1) {
|
||||
while (!need_resched() && !hvlpevent_is_pending()) {
|
||||
local_irq_disable();
|
||||
ppc64_runlatch_off();
|
||||
|
||||
/* Recheck with irqs off */
|
||||
if (!need_resched() && !hvlpevent_is_pending())
|
||||
yield_shared_processor();
|
||||
|
||||
HMT_medium();
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
ppc64_runlatch_on();
|
||||
|
||||
if (hvlpevent_is_pending())
|
||||
process_iSeries_events();
|
||||
|
||||
schedule();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iseries_dedicated_idle(void)
|
||||
{
|
||||
long oldval;
|
||||
|
||||
while (1) {
|
||||
oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
|
||||
|
||||
if (!oldval) {
|
||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||
|
||||
while (!need_resched()) {
|
||||
ppc64_runlatch_off();
|
||||
HMT_low();
|
||||
|
||||
if (hvlpevent_is_pending()) {
|
||||
HMT_medium();
|
||||
ppc64_runlatch_on();
|
||||
process_iSeries_events();
|
||||
}
|
||||
}
|
||||
|
||||
HMT_medium();
|
||||
clear_thread_flag(TIF_POLLING_NRFLAG);
|
||||
} else {
|
||||
set_need_resched();
|
||||
}
|
||||
|
||||
ppc64_runlatch_on();
|
||||
schedule();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PCI
|
||||
void __init iSeries_init_IRQ(void) { }
|
||||
#endif
|
||||
|
@ -859,5 +945,13 @@ void __init iSeries_early_setup(void)
|
|||
ppc_md.get_rtc_time = iSeries_get_rtc_time;
|
||||
ppc_md.calibrate_decr = iSeries_calibrate_decr;
|
||||
ppc_md.progress = iSeries_progress;
|
||||
|
||||
if (get_paca()->lppaca.shared_proc) {
|
||||
ppc_md.idle_loop = iseries_shared_idle;
|
||||
printk(KERN_INFO "Using shared processor idle loop\n");
|
||||
} else {
|
||||
ppc_md.idle_loop = iseries_dedicated_idle;
|
||||
printk(KERN_INFO "Using dedicated idle loop\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,109 +20,18 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/iSeries/HvCall.h>
|
||||
#include <asm/iSeries/ItLpQueue.h>
|
||||
#include <asm/plpar_wrappers.h>
|
||||
#include <asm/systemcfg.h>
|
||||
#include <asm/machdep.h>
|
||||
|
||||
extern void power4_idle(void);
|
||||
|
||||
static int (*idle_loop)(void);
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
static unsigned long maxYieldTime = 0;
|
||||
static unsigned long minYieldTime = 0xffffffffffffffffUL;
|
||||
|
||||
static inline void process_iSeries_events(void)
|
||||
{
|
||||
asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
|
||||
}
|
||||
|
||||
static void yield_shared_processor(void)
|
||||
{
|
||||
unsigned long tb;
|
||||
unsigned long yieldTime;
|
||||
|
||||
HvCall_setEnabledInterrupts(HvCall_MaskIPI |
|
||||
HvCall_MaskLpEvent |
|
||||
HvCall_MaskLpProd |
|
||||
HvCall_MaskTimeout);
|
||||
|
||||
tb = get_tb();
|
||||
/* Compute future tb value when yield should expire */
|
||||
HvCall_yieldProcessor(HvCall_YieldTimed, tb+tb_ticks_per_jiffy);
|
||||
|
||||
yieldTime = get_tb() - tb;
|
||||
if (yieldTime > maxYieldTime)
|
||||
maxYieldTime = yieldTime;
|
||||
|
||||
if (yieldTime < minYieldTime)
|
||||
minYieldTime = yieldTime;
|
||||
|
||||
/*
|
||||
* The decrementer stops during the yield. Force a fake decrementer
|
||||
* here and let the timer_interrupt code sort out the actual time.
|
||||
*/
|
||||
get_paca()->lppaca.int_dword.fields.decr_int = 1;
|
||||
process_iSeries_events();
|
||||
}
|
||||
|
||||
static int iSeries_idle(void)
|
||||
{
|
||||
struct paca_struct *lpaca;
|
||||
long oldval;
|
||||
|
||||
/* ensure iSeries run light will be out when idle */
|
||||
ppc64_runlatch_off();
|
||||
|
||||
lpaca = get_paca();
|
||||
|
||||
while (1) {
|
||||
if (lpaca->lppaca.shared_proc) {
|
||||
if (hvlpevent_is_pending())
|
||||
process_iSeries_events();
|
||||
if (!need_resched())
|
||||
yield_shared_processor();
|
||||
} else {
|
||||
oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
|
||||
|
||||
if (!oldval) {
|
||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||
|
||||
while (!need_resched()) {
|
||||
HMT_medium();
|
||||
if (hvlpevent_is_pending())
|
||||
process_iSeries_events();
|
||||
HMT_low();
|
||||
}
|
||||
|
||||
HMT_medium();
|
||||
clear_thread_flag(TIF_POLLING_NRFLAG);
|
||||
} else {
|
||||
set_need_resched();
|
||||
}
|
||||
}
|
||||
|
||||
ppc64_runlatch_on();
|
||||
schedule();
|
||||
ppc64_runlatch_off();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int default_idle(void)
|
||||
int default_idle(void)
|
||||
{
|
||||
long oldval;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
@ -134,7 +43,8 @@ static int default_idle(void)
|
|||
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||
|
||||
while (!need_resched() && !cpu_is_offline(cpu)) {
|
||||
barrier();
|
||||
ppc64_runlatch_off();
|
||||
|
||||
/*
|
||||
* Go into low thread priority and possibly
|
||||
* low power mode.
|
||||
|
@ -149,6 +59,7 @@ static int default_idle(void)
|
|||
set_need_resched();
|
||||
}
|
||||
|
||||
ppc64_runlatch_on();
|
||||
schedule();
|
||||
if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
|
||||
cpu_die();
|
||||
|
@ -157,127 +68,19 @@ static int default_idle(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
|
||||
DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
|
||||
|
||||
int dedicated_idle(void)
|
||||
int native_idle(void)
|
||||
{
|
||||
long oldval;
|
||||
struct paca_struct *lpaca = get_paca(), *ppaca;
|
||||
unsigned long start_snooze;
|
||||
unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
ppaca = &paca[cpu ^ 1];
|
||||
|
||||
while (1) {
|
||||
/*
|
||||
* Indicate to the HV that we are idle. Now would be
|
||||
* a good time to find other work to dispatch.
|
||||
*/
|
||||
lpaca->lppaca.idle = 1;
|
||||
ppc64_runlatch_off();
|
||||
|
||||
oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
|
||||
if (!oldval) {
|
||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||
start_snooze = __get_tb() +
|
||||
*smt_snooze_delay * tb_ticks_per_usec;
|
||||
while (!need_resched() && !cpu_is_offline(cpu)) {
|
||||
/*
|
||||
* Go into low thread priority and possibly
|
||||
* low power mode.
|
||||
*/
|
||||
HMT_low();
|
||||
HMT_very_low();
|
||||
if (!need_resched())
|
||||
power4_idle();
|
||||
|
||||
if (*smt_snooze_delay == 0 ||
|
||||
__get_tb() < start_snooze)
|
||||
continue;
|
||||
|
||||
HMT_medium();
|
||||
|
||||
if (!(ppaca->lppaca.idle)) {
|
||||
local_irq_disable();
|
||||
|
||||
/*
|
||||
* We are about to sleep the thread
|
||||
* and so wont be polling any
|
||||
* more.
|
||||
*/
|
||||
clear_thread_flag(TIF_POLLING_NRFLAG);
|
||||
|
||||
/*
|
||||
* SMT dynamic mode. Cede will result
|
||||
* in this thread going dormant, if the
|
||||
* partner thread is still doing work.
|
||||
* Thread wakes up if partner goes idle,
|
||||
* an interrupt is presented, or a prod
|
||||
* occurs. Returning from the cede
|
||||
* enables external interrupts.
|
||||
*/
|
||||
if (!need_resched())
|
||||
cede_processor();
|
||||
else
|
||||
local_irq_enable();
|
||||
} else {
|
||||
/*
|
||||
* Give the HV an opportunity at the
|
||||
* processor, since we are not doing
|
||||
* any work.
|
||||
*/
|
||||
poll_pending();
|
||||
}
|
||||
}
|
||||
|
||||
clear_thread_flag(TIF_POLLING_NRFLAG);
|
||||
} else {
|
||||
set_need_resched();
|
||||
if (need_resched()) {
|
||||
ppc64_runlatch_on();
|
||||
schedule();
|
||||
}
|
||||
|
||||
HMT_medium();
|
||||
lpaca->lppaca.idle = 0;
|
||||
schedule();
|
||||
if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
|
||||
cpu_die();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shared_idle(void)
|
||||
{
|
||||
struct paca_struct *lpaca = get_paca();
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
while (1) {
|
||||
/*
|
||||
* Indicate to the HV that we are idle. Now would be
|
||||
* a good time to find other work to dispatch.
|
||||
*/
|
||||
lpaca->lppaca.idle = 1;
|
||||
|
||||
while (!need_resched() && !cpu_is_offline(cpu)) {
|
||||
local_irq_disable();
|
||||
|
||||
/*
|
||||
* Yield the processor to the hypervisor. We return if
|
||||
* an external interrupt occurs (which are driven prior
|
||||
* to returning here) or if a prod occurs from another
|
||||
* processor. When returning here, external interrupts
|
||||
* are enabled.
|
||||
*
|
||||
* Check need_resched() again with interrupts disabled
|
||||
* to avoid a race.
|
||||
*/
|
||||
if (!need_resched())
|
||||
cede_processor();
|
||||
else
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
HMT_medium();
|
||||
lpaca->lppaca.idle = 0;
|
||||
schedule();
|
||||
if (cpu_is_offline(smp_processor_id()) &&
|
||||
system_state == SYSTEM_RUNNING)
|
||||
cpu_die();
|
||||
|
@ -286,29 +89,10 @@ static int shared_idle(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PPC_PSERIES */
|
||||
|
||||
static int native_idle(void)
|
||||
{
|
||||
while(1) {
|
||||
/* check CPU type here */
|
||||
if (!need_resched())
|
||||
power4_idle();
|
||||
if (need_resched())
|
||||
schedule();
|
||||
|
||||
if (cpu_is_offline(raw_smp_processor_id()) &&
|
||||
system_state == SYSTEM_RUNNING)
|
||||
cpu_die();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
|
||||
void cpu_idle(void)
|
||||
{
|
||||
idle_loop();
|
||||
BUG_ON(NULL == ppc_md.idle_loop);
|
||||
ppc_md.idle_loop();
|
||||
}
|
||||
|
||||
int powersave_nap;
|
||||
|
@ -342,42 +126,3 @@ register_powersave_nap_sysctl(void)
|
|||
}
|
||||
__initcall(register_powersave_nap_sysctl);
|
||||
#endif
|
||||
|
||||
int idle_setup(void)
|
||||
{
|
||||
/*
|
||||
* Move that junk to each platform specific file, eventually define
|
||||
* a pSeries_idle for shared processor stuff
|
||||
*/
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
idle_loop = iSeries_idle;
|
||||
return 1;
|
||||
#else
|
||||
idle_loop = default_idle;
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
if (systemcfg->platform & PLATFORM_PSERIES) {
|
||||
if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
|
||||
if (get_paca()->lppaca.shared_proc) {
|
||||
printk(KERN_INFO "Using shared processor idle loop\n");
|
||||
idle_loop = shared_idle;
|
||||
} else {
|
||||
printk(KERN_INFO "Using dedicated idle loop\n");
|
||||
idle_loop = dedicated_idle;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_INFO "Using default idle loop\n");
|
||||
idle_loop = default_idle;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_PPC_PSERIES */
|
||||
#ifndef CONFIG_PPC_ISERIES
|
||||
if (systemcfg->platform == PLATFORM_POWERMAC ||
|
||||
systemcfg->platform == PLATFORM_MAPLE) {
|
||||
printk(KERN_INFO "Using native/NAP idle loop\n");
|
||||
idle_loop = native_idle;
|
||||
}
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -177,6 +177,8 @@ void __init maple_setup_arch(void)
|
|||
#ifdef CONFIG_DUMMY_CONSOLE
|
||||
conswitchp = &dummy_con;
|
||||
#endif
|
||||
|
||||
printk(KERN_INFO "Using native/NAP idle loop\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -297,4 +299,5 @@ struct machdep_calls __initdata maple_md = {
|
|||
.get_rtc_time = maple_get_rtc_time,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = maple_progress,
|
||||
.idle_loop = native_idle,
|
||||
};
|
||||
|
|
|
@ -1124,9 +1124,11 @@ _GLOBAL(sys_call_table32)
|
|||
.llong .compat_sys_mq_getsetattr
|
||||
.llong .compat_sys_kexec_load
|
||||
.llong .sys32_add_key
|
||||
.llong .sys32_request_key
|
||||
.llong .sys32_request_key /* 270 */
|
||||
.llong .compat_sys_keyctl
|
||||
.llong .compat_sys_waitid
|
||||
.llong .sys32_ioprio_set
|
||||
.llong .sys32_ioprio_get
|
||||
|
||||
.balign 8
|
||||
_GLOBAL(sys_call_table)
|
||||
|
@ -1403,3 +1405,5 @@ _GLOBAL(sys_call_table)
|
|||
.llong .sys_request_key /* 270 */
|
||||
.llong .sys_keyctl
|
||||
.llong .sys_waitid
|
||||
.llong .sys_ioprio_set
|
||||
.llong .sys_ioprio_get
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#undef DEBUG
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -82,6 +83,9 @@ int fwnmi_active; /* TRUE if an FWNMI handler is present */
|
|||
extern void pSeries_system_reset_exception(struct pt_regs *regs);
|
||||
extern int pSeries_machine_check_exception(struct pt_regs *regs);
|
||||
|
||||
static int pseries_shared_idle(void);
|
||||
static int pseries_dedicated_idle(void);
|
||||
|
||||
static volatile void __iomem * chrp_int_ack_special;
|
||||
struct mpic *pSeries_mpic;
|
||||
|
||||
|
@ -229,6 +233,20 @@ static void __init pSeries_setup_arch(void)
|
|||
|
||||
if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
|
||||
vpa_init(boot_cpuid);
|
||||
|
||||
/* Choose an idle loop */
|
||||
if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
|
||||
if (get_paca()->lppaca.shared_proc) {
|
||||
printk(KERN_INFO "Using shared processor idle loop\n");
|
||||
ppc_md.idle_loop = pseries_shared_idle;
|
||||
} else {
|
||||
printk(KERN_INFO "Using dedicated idle loop\n");
|
||||
ppc_md.idle_loop = pseries_dedicated_idle;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_INFO "Using default idle loop\n");
|
||||
ppc_md.idle_loop = default_idle;
|
||||
}
|
||||
}
|
||||
|
||||
static int __init pSeries_init_panel(void)
|
||||
|
@ -418,6 +436,144 @@ static int __init pSeries_probe(int platform)
|
|||
return 1;
|
||||
}
|
||||
|
||||
DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
|
||||
|
||||
static inline void dedicated_idle_sleep(unsigned int cpu)
|
||||
{
|
||||
struct paca_struct *ppaca = &paca[cpu ^ 1];
|
||||
|
||||
/* Only sleep if the other thread is not idle */
|
||||
if (!(ppaca->lppaca.idle)) {
|
||||
local_irq_disable();
|
||||
|
||||
/*
|
||||
* We are about to sleep the thread and so wont be polling any
|
||||
* more.
|
||||
*/
|
||||
clear_thread_flag(TIF_POLLING_NRFLAG);
|
||||
|
||||
/*
|
||||
* SMT dynamic mode. Cede will result in this thread going
|
||||
* dormant, if the partner thread is still doing work. Thread
|
||||
* wakes up if partner goes idle, an interrupt is presented, or
|
||||
* a prod occurs. Returning from the cede enables external
|
||||
* interrupts.
|
||||
*/
|
||||
if (!need_resched())
|
||||
cede_processor();
|
||||
else
|
||||
local_irq_enable();
|
||||
} else {
|
||||
/*
|
||||
* Give the HV an opportunity at the processor, since we are
|
||||
* not doing any work.
|
||||
*/
|
||||
poll_pending();
|
||||
}
|
||||
}
|
||||
|
||||
static int pseries_dedicated_idle(void)
|
||||
{
|
||||
long oldval;
|
||||
struct paca_struct *lpaca = get_paca();
|
||||
unsigned int cpu = smp_processor_id();
|
||||
unsigned long start_snooze;
|
||||
unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
|
||||
|
||||
while (1) {
|
||||
/*
|
||||
* Indicate to the HV that we are idle. Now would be
|
||||
* a good time to find other work to dispatch.
|
||||
*/
|
||||
lpaca->lppaca.idle = 1;
|
||||
|
||||
oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
|
||||
if (!oldval) {
|
||||
set_thread_flag(TIF_POLLING_NRFLAG);
|
||||
|
||||
start_snooze = __get_tb() +
|
||||
*smt_snooze_delay * tb_ticks_per_usec;
|
||||
|
||||
while (!need_resched() && !cpu_is_offline(cpu)) {
|
||||
ppc64_runlatch_off();
|
||||
|
||||
/*
|
||||
* Go into low thread priority and possibly
|
||||
* low power mode.
|
||||
*/
|
||||
HMT_low();
|
||||
HMT_very_low();
|
||||
|
||||
if (*smt_snooze_delay != 0 &&
|
||||
__get_tb() > start_snooze) {
|
||||
HMT_medium();
|
||||
dedicated_idle_sleep(cpu);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HMT_medium();
|
||||
clear_thread_flag(TIF_POLLING_NRFLAG);
|
||||
} else {
|
||||
set_need_resched();
|
||||
}
|
||||
|
||||
lpaca->lppaca.idle = 0;
|
||||
ppc64_runlatch_on();
|
||||
|
||||
schedule();
|
||||
|
||||
if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
|
||||
cpu_die();
|
||||
}
|
||||
}
|
||||
|
||||
static int pseries_shared_idle(void)
|
||||
{
|
||||
struct paca_struct *lpaca = get_paca();
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
while (1) {
|
||||
/*
|
||||
* Indicate to the HV that we are idle. Now would be
|
||||
* a good time to find other work to dispatch.
|
||||
*/
|
||||
lpaca->lppaca.idle = 1;
|
||||
|
||||
while (!need_resched() && !cpu_is_offline(cpu)) {
|
||||
local_irq_disable();
|
||||
ppc64_runlatch_off();
|
||||
|
||||
/*
|
||||
* Yield the processor to the hypervisor. We return if
|
||||
* an external interrupt occurs (which are driven prior
|
||||
* to returning here) or if a prod occurs from another
|
||||
* processor. When returning here, external interrupts
|
||||
* are enabled.
|
||||
*
|
||||
* Check need_resched() again with interrupts disabled
|
||||
* to avoid a race.
|
||||
*/
|
||||
if (!need_resched())
|
||||
cede_processor();
|
||||
else
|
||||
local_irq_enable();
|
||||
|
||||
HMT_medium();
|
||||
}
|
||||
|
||||
lpaca->lppaca.idle = 0;
|
||||
ppc64_runlatch_on();
|
||||
|
||||
schedule();
|
||||
|
||||
if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
|
||||
cpu_die();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct machdep_calls __initdata pSeries_md = {
|
||||
.probe = pSeries_probe,
|
||||
.setup_arch = pSeries_setup_arch,
|
||||
|
|
|
@ -186,6 +186,8 @@ void __init pmac_setup_arch(void)
|
|||
#ifdef CONFIG_DUMMY_CONSOLE
|
||||
conswitchp = &dummy_con;
|
||||
#endif
|
||||
|
||||
printk(KERN_INFO "Using native/NAP idle loop\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCSI
|
||||
|
@ -507,5 +509,6 @@ struct machdep_calls __initdata pmac_md = {
|
|||
.calibrate_decr = pmac_calibrate_decr,
|
||||
.feature_call = pmac_do_feature_call,
|
||||
.progress = pmac_progress,
|
||||
.check_legacy_ioport = pmac_check_legacy_ioport
|
||||
.check_legacy_ioport = pmac_check_legacy_ioport,
|
||||
.idle_loop = native_idle,
|
||||
};
|
||||
|
|
|
@ -96,7 +96,6 @@ extern void udbg_init_maple_realmode(void);
|
|||
extern unsigned long klimit;
|
||||
|
||||
extern void mm_init_ppc64(void);
|
||||
extern int idle_setup(void);
|
||||
extern void stab_initialize(unsigned long stab);
|
||||
extern void htab_initialize(void);
|
||||
extern void early_init_devtree(void *flat_dt);
|
||||
|
@ -1081,8 +1080,11 @@ void __init setup_arch(char **cmdline_p)
|
|||
|
||||
ppc_md.setup_arch();
|
||||
|
||||
/* Select the correct idle loop for the platform. */
|
||||
idle_setup();
|
||||
/* Use the default idle loop if the platform hasn't provided one. */
|
||||
if (NULL == ppc_md.idle_loop) {
|
||||
ppc_md.idle_loop = default_idle;
|
||||
printk(KERN_INFO "Using default idle loop\n");
|
||||
}
|
||||
|
||||
paging_init();
|
||||
ppc64_boot_msg(0x15, "Setup Done");
|
||||
|
|
|
@ -30,47 +30,26 @@
|
|||
#include <linux/sem.h>
|
||||
#include <linux/msg.h>
|
||||
#include <linux/shm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/nfs_fs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sunrpc/svc.h>
|
||||
#include <linux/nfsd/nfsd.h>
|
||||
#include <linux/nfsd/cache.h>
|
||||
#include <linux/nfsd/xdr.h>
|
||||
#include <linux/nfsd/syscall.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/highuid.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/dnotify.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/aio_abi.h>
|
||||
#include <linux/elf.h>
|
||||
|
||||
#include <net/scm.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/ipc.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <asm/ppcdebug.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/systemcfg.h>
|
||||
|
@ -350,8 +329,6 @@ asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* These are here just in case some old sparc32 binary calls it. */
|
||||
asmlinkage long sys32_pause(void)
|
||||
{
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
|
@ -360,8 +337,6 @@ asmlinkage long sys32_pause(void)
|
|||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
|
||||
{
|
||||
long usec;
|
||||
|
@ -847,16 +822,6 @@ asmlinkage long sys32_getpgid(u32 pid)
|
|||
}
|
||||
|
||||
|
||||
/* Note: it is necessary to treat which and who as unsigned ints,
|
||||
* with the corresponding cast to a signed int to insure that the
|
||||
* proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
|
||||
* and the register representation of a signed int (msr in 64-bit mode) is performed.
|
||||
*/
|
||||
asmlinkage long sys32_getpriority(u32 which, u32 who)
|
||||
{
|
||||
return sys_getpriority((int)which, (int)who);
|
||||
}
|
||||
|
||||
|
||||
/* Note: it is necessary to treat pid as an unsigned int,
|
||||
* with the corresponding cast to a signed int to insure that the
|
||||
|
@ -1048,6 +1013,11 @@ asmlinkage long sys32_setpgid(u32 pid, u32 pgid)
|
|||
return sys_setpgid((int)pid, (int)pgid);
|
||||
}
|
||||
|
||||
long sys32_getpriority(u32 which, u32 who)
|
||||
{
|
||||
/* sign extend which and who */
|
||||
return sys_getpriority((int)which, (int)who);
|
||||
}
|
||||
|
||||
long sys32_setpriority(u32 which, u32 who, u32 niceval)
|
||||
{
|
||||
|
@ -1055,6 +1025,18 @@ long sys32_setpriority(u32 which, u32 who, u32 niceval)
|
|||
return sys_setpriority((int)which, (int)who, (int)niceval);
|
||||
}
|
||||
|
||||
long sys32_ioprio_get(u32 which, u32 who)
|
||||
{
|
||||
/* sign extend which and who */
|
||||
return sys_ioprio_get((int)which, (int)who);
|
||||
}
|
||||
|
||||
long sys32_ioprio_set(u32 which, u32 who, u32 ioprio)
|
||||
{
|
||||
/* sign extend which, who and ioprio */
|
||||
return sys_ioprio_set((int)which, (int)who, (int)ioprio);
|
||||
}
|
||||
|
||||
/* Note: it is necessary to treat newmask as an unsigned int,
|
||||
* with the corresponding cast to a signed int to insure that the
|
||||
* proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
|
||||
|
@ -1273,8 +1255,6 @@ long ppc32_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
|
|||
(u64)len_high << 32 | len_low, advice);
|
||||
}
|
||||
|
||||
extern asmlinkage long sys_timer_create(clockid_t, sigevent_t __user *, timer_t __user *);
|
||||
|
||||
long ppc32_timer_create(clockid_t clock,
|
||||
struct compat_sigevent __user *ev32,
|
||||
timer_t __user *timer_id)
|
||||
|
|
|
@ -112,7 +112,6 @@ void ppc64_enable_pmcs(void)
|
|||
unsigned long hid0;
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
unsigned long set, reset;
|
||||
int ret;
|
||||
#endif /* CONFIG_PPC_PSERIES */
|
||||
|
||||
/* Only need to enable them once */
|
||||
|
@ -145,11 +144,7 @@ void ppc64_enable_pmcs(void)
|
|||
case PLATFORM_PSERIES_LPAR:
|
||||
set = 1UL << 63;
|
||||
reset = 0;
|
||||
ret = plpar_hcall_norets(H_PERFMON, set, reset);
|
||||
if (ret)
|
||||
printk(KERN_ERR "H_PERFMON call on cpu %u "
|
||||
"returned %d\n",
|
||||
smp_processor_id(), ret);
|
||||
plpar_hcall_norets(H_PERFMON, set, reset);
|
||||
break;
|
||||
#endif /* CONFIG_PPC_PSERIES */
|
||||
|
||||
|
@ -161,13 +156,6 @@ void ppc64_enable_pmcs(void)
|
|||
/* instruct hypervisor to maintain PMCs */
|
||||
if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
|
||||
get_paca()->lppaca.pmcregs_in_use = 1;
|
||||
|
||||
/*
|
||||
* On SMT machines we have to set the run latch in the ctrl register
|
||||
* in order to make PMC6 spin.
|
||||
*/
|
||||
if (cpu_has_feature(CPU_FTR_SMT))
|
||||
ppc64_runlatch_on();
|
||||
#endif /* CONFIG_PPC_PSERIES */
|
||||
}
|
||||
|
||||
|
|
|
@ -40,9 +40,9 @@ SECTIONS
|
|||
.gcc_except_table : { *(.gcc_except_table) }
|
||||
.fixup : { *(.fixup) }
|
||||
|
||||
.got ALIGN(4) : { *(.got.plt) *(.got) }
|
||||
|
||||
.dynamic : { *(.dynamic) } :text :dynamic
|
||||
.got : { *(.got) }
|
||||
.plt : { *(.plt) }
|
||||
|
||||
_end = .;
|
||||
__end = .;
|
||||
|
|
|
@ -128,7 +128,6 @@ config HOSTFS
|
|||
|
||||
config HPPFS
|
||||
tristate "HoneyPot ProcFS (EXPERIMENTAL)"
|
||||
depends on BROKEN
|
||||
help
|
||||
hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
|
||||
entries to be overridden, removed, or fabricated from the host.
|
||||
|
@ -141,8 +140,9 @@ 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 ask for it to be fixed. In this
|
||||
moment, it does not work on 2.6 (it works somehow on 2.4).
|
||||
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"
|
||||
|
|
|
@ -19,6 +19,18 @@ config 3_LEVEL_PGTABLES
|
|||
memory. All the memory that can't be mapped directly will be treated
|
||||
as high memory.
|
||||
|
||||
config STUB_CODE
|
||||
hex
|
||||
default 0xbfffe000
|
||||
|
||||
config STUB_DATA
|
||||
hex
|
||||
default 0xbffff000
|
||||
|
||||
config STUB_START
|
||||
hex
|
||||
default STUB_CODE
|
||||
|
||||
config ARCH_HAS_SC_SIGNALS
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -14,6 +14,18 @@ config 3_LEVEL_PGTABLES
|
|||
bool
|
||||
default y
|
||||
|
||||
config STUB_CODE
|
||||
hex
|
||||
default 0x7fbfffe000
|
||||
|
||||
config STUB_DATA
|
||||
hex
|
||||
default 0x7fbffff000
|
||||
|
||||
config STUB_START
|
||||
hex
|
||||
default STUB_CODE
|
||||
|
||||
config ARCH_HAS_SC_SIGNALS
|
||||
bool
|
||||
default n
|
||||
|
|
|
@ -8,7 +8,7 @@ ifeq ($(CONFIG_MODE_SKAS),y)
|
|||
endif
|
||||
endif
|
||||
|
||||
CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH)
|
||||
CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) $(STUB_CFLAGS)
|
||||
ARCH_USER_CFLAGS :=
|
||||
|
||||
ifneq ($(CONFIG_GPROF),y)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
SUBARCH_LIBS := arch/um/sys-x86_64/
|
||||
START := 0x60000000
|
||||
|
||||
CFLAGS += -U__$(SUBARCH)__ -fno-builtin
|
||||
CFLAGS += -U__$(SUBARCH)__ -fno-builtin $(STUB_CFLAGS)
|
||||
ARCH_USER_CFLAGS := -D__x86_64__
|
||||
|
||||
ELF_ARCH := i386:x86-64
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.12-rc3-skas3-v9-pre2
|
||||
# Sun Apr 24 19:46:10 2005
|
||||
# Linux kernel version: 2.6.12-rc6-mm1
|
||||
# Tue Jun 14 18:22:21 2005
|
||||
#
|
||||
CONFIG_GENERIC_HARDIRQS=y
|
||||
CONFIG_UML=y
|
||||
|
@ -13,23 +13,32 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
|
|||
#
|
||||
# UML-specific options
|
||||
#
|
||||
CONFIG_MODE_TT=y
|
||||
# CONFIG_MODE_TT is not set
|
||||
# CONFIG_STATIC_LINK is not set
|
||||
CONFIG_MODE_SKAS=y
|
||||
CONFIG_UML_X86=y
|
||||
# CONFIG_64BIT is not set
|
||||
CONFIG_TOP_ADDR=0xc0000000
|
||||
# CONFIG_3_LEVEL_PGTABLES is not set
|
||||
CONFIG_STUB_CODE=0xbfffe000
|
||||
CONFIG_STUB_DATA=0xbffff000
|
||||
CONFIG_STUB_START=0xbfffe000
|
||||
CONFIG_ARCH_HAS_SC_SIGNALS=y
|
||||
CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
|
||||
CONFIG_LD_SCRIPT_STATIC=y
|
||||
CONFIG_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_FLATMEM_MANUAL=y
|
||||
# CONFIG_DISCONTIGMEM_MANUAL is not set
|
||||
# CONFIG_SPARSEMEM_MANUAL is not set
|
||||
CONFIG_FLATMEM=y
|
||||
CONFIG_FLAT_NODE_MEM_MAP=y
|
||||
CONFIG_LD_SCRIPT_DYN=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_BINFMT_ELF=y
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_HOSTFS=y
|
||||
# CONFIG_HOSTFS is not set
|
||||
CONFIG_MCONSOLE=y
|
||||
# CONFIG_MAGIC_SYSRQ is not set
|
||||
# CONFIG_HOST_2G_2G is not set
|
||||
# CONFIG_SMP is not set
|
||||
CONFIG_NEST_LEVEL=0
|
||||
CONFIG_KERNEL_HALF_GIGS=1
|
||||
# CONFIG_HIGHMEM is not set
|
||||
|
@ -63,6 +72,8 @@ CONFIG_IKCONFIG_PROC=y
|
|||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_ALL is not set
|
||||
CONFIG_KALLSYMS_EXTRA_PASS=y
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
CONFIG_EPOLL=y
|
||||
|
@ -81,6 +92,7 @@ CONFIG_MODULES=y
|
|||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
CONFIG_OBSOLETE_MODPARM=y
|
||||
# CONFIG_MODVERSIONS is not set
|
||||
# CONFIG_MODULE_SRCVERSION_ALL is not set
|
||||
CONFIG_KMOD=y
|
||||
|
||||
|
@ -115,6 +127,7 @@ CONFIG_UML_SOUND=m
|
|||
CONFIG_SOUND=m
|
||||
CONFIG_HOSTAUDIO=m
|
||||
CONFIG_UML_RANDOM=y
|
||||
# CONFIG_MMAPPER is not set
|
||||
|
||||
#
|
||||
# Block devices
|
||||
|
@ -176,6 +189,17 @@ CONFIG_INET=y
|
|||
# CONFIG_INET_TUNNEL is not set
|
||||
CONFIG_IP_TCPDIAG=y
|
||||
# CONFIG_IP_TCPDIAG_IPV6 is not set
|
||||
|
||||
#
|
||||
# TCP congestion control
|
||||
#
|
||||
CONFIG_TCP_CONG_BIC=y
|
||||
CONFIG_TCP_CONG_WESTWOOD=y
|
||||
CONFIG_TCP_CONG_HTCP=y
|
||||
# CONFIG_TCP_CONG_HSTCP is not set
|
||||
# CONFIG_TCP_CONG_HYBLA is not set
|
||||
# CONFIG_TCP_CONG_VEGAS is not set
|
||||
# CONFIG_TCP_CONG_SCALABLE is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_NETFILTER is not set
|
||||
|
||||
|
@ -206,11 +230,15 @@ CONFIG_IP_TCPDIAG=y
|
|||
# Network testing
|
||||
#
|
||||
# CONFIG_NET_PKTGEN is not set
|
||||
# CONFIG_KGDBOE is not set
|
||||
# CONFIG_NETPOLL is not set
|
||||
# CONFIG_NETPOLL_RX is not set
|
||||
# CONFIG_NETPOLL_TRAP is not set
|
||||
# CONFIG_NET_POLL_CONTROLLER is not set
|
||||
# CONFIG_HAMRADIO is not set
|
||||
# CONFIG_IRDA is not set
|
||||
# CONFIG_BT is not set
|
||||
# CONFIG_IEEE80211 is not set
|
||||
CONFIG_DUMMY=m
|
||||
# CONFIG_BONDING is not set
|
||||
# CONFIG_EQUALIZER is not set
|
||||
|
@ -227,6 +255,7 @@ CONFIG_PPP=m
|
|||
# CONFIG_PPP_SYNC_TTY is not set
|
||||
# CONFIG_PPP_DEFLATE is not set
|
||||
# CONFIG_PPP_BSDCOMP is not set
|
||||
# CONFIG_PPP_MPPE is not set
|
||||
# CONFIG_PPPOE is not set
|
||||
CONFIG_SLIP=m
|
||||
# CONFIG_SLIP_COMPRESSED is not set
|
||||
|
@ -240,10 +269,12 @@ CONFIG_SLIP=m
|
|||
#
|
||||
CONFIG_EXT2_FS=y
|
||||
# CONFIG_EXT2_FS_XATTR is not set
|
||||
# CONFIG_EXT2_FS_XIP is not set
|
||||
CONFIG_EXT3_FS=y
|
||||
# CONFIG_EXT3_FS_XATTR is not set
|
||||
CONFIG_JBD=y
|
||||
# CONFIG_JBD_DEBUG is not set
|
||||
# CONFIG_REISER4_FS is not set
|
||||
CONFIG_REISERFS_FS=y
|
||||
# CONFIG_REISERFS_CHECK is not set
|
||||
# CONFIG_REISERFS_PROC_INFO is not set
|
||||
|
@ -256,6 +287,7 @@ CONFIG_REISERFS_FS=y
|
|||
# CONFIG_XFS_FS is not set
|
||||
# CONFIG_MINIX_FS is not set
|
||||
# CONFIG_ROMFS_FS is not set
|
||||
CONFIG_INOTIFY=y
|
||||
CONFIG_QUOTA=y
|
||||
# CONFIG_QFMT_V1 is not set
|
||||
# CONFIG_QFMT_V2 is not set
|
||||
|
@ -264,6 +296,12 @@ CONFIG_DNOTIFY=y
|
|||
CONFIG_AUTOFS_FS=m
|
||||
CONFIG_AUTOFS4_FS=m
|
||||
|
||||
#
|
||||
# Caches
|
||||
#
|
||||
# CONFIG_FSCACHE is not set
|
||||
# CONFIG_FUSE_FS is not set
|
||||
|
||||
#
|
||||
# CD-ROM/DVD Filesystems
|
||||
#
|
||||
|
@ -291,6 +329,8 @@ CONFIG_TMPFS=y
|
|||
# CONFIG_TMPFS_XATTR is not set
|
||||
# CONFIG_HUGETLB_PAGE is not set
|
||||
CONFIG_RAMFS=y
|
||||
# CONFIG_CONFIGFS_FS is not set
|
||||
# CONFIG_RELAYFS_FS is not set
|
||||
|
||||
#
|
||||
# Miscellaneous filesystems
|
||||
|
@ -319,6 +359,7 @@ CONFIG_RAMFS=y
|
|||
# CONFIG_NCP_FS is not set
|
||||
# CONFIG_CODA_FS is not set
|
||||
# CONFIG_AFS_FS is not set
|
||||
# CONFIG_9P_FS is not set
|
||||
|
||||
#
|
||||
# Partition Types
|
||||
|
@ -404,14 +445,15 @@ CONFIG_CRC32=m
|
|||
# CONFIG_PRINTK_TIME is not set
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
CONFIG_DETECT_SOFTLOCKUP=y
|
||||
# CONFIG_SCHEDSTATS is not set
|
||||
# CONFIG_DEBUG_SLAB is not set
|
||||
CONFIG_DEBUG_SLAB=y
|
||||
# CONFIG_DEBUG_SPINLOCK is not set
|
||||
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
|
||||
# CONFIG_DEBUG_KOBJECT is not set
|
||||
CONFIG_DEBUG_INFO=y
|
||||
# CONFIG_DEBUG_FS is not set
|
||||
CONFIG_FRAME_POINTER=y
|
||||
CONFIG_PT_PROXY=y
|
||||
# CONFIG_GPROF is not set
|
||||
# CONFIG_GCOV is not set
|
||||
# CONFIG_SYSCALL_DEBUG is not set
|
||||
|
|
|
@ -663,11 +663,15 @@ struct tty_driver *line_register_devfs(struct lines *set,
|
|||
return driver;
|
||||
}
|
||||
|
||||
static spinlock_t winch_handler_lock;
|
||||
LIST_HEAD(winch_handlers);
|
||||
|
||||
void lines_init(struct line *lines, int nlines)
|
||||
{
|
||||
struct line *line;
|
||||
int i;
|
||||
|
||||
spin_lock_init(&winch_handler_lock);
|
||||
for(i = 0; i < nlines; i++){
|
||||
line = &lines[i];
|
||||
INIT_LIST_HEAD(&line->chan_list);
|
||||
|
@ -724,31 +728,30 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
DECLARE_MUTEX(winch_handler_sem);
|
||||
LIST_HEAD(winch_handlers);
|
||||
|
||||
void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
|
||||
{
|
||||
struct winch *winch;
|
||||
|
||||
down(&winch_handler_sem);
|
||||
winch = kmalloc(sizeof(*winch), GFP_KERNEL);
|
||||
if (winch == NULL) {
|
||||
printk("register_winch_irq - kmalloc failed\n");
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
*winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list),
|
||||
.fd = fd,
|
||||
.tty_fd = tty_fd,
|
||||
.pid = pid,
|
||||
.tty = tty });
|
||||
|
||||
spin_lock(&winch_handler_lock);
|
||||
list_add(&winch->list, &winch_handlers);
|
||||
spin_unlock(&winch_handler_lock);
|
||||
|
||||
if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
|
||||
SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
|
||||
"winch", winch) < 0)
|
||||
printk("register_winch_irq - failed to register IRQ\n");
|
||||
out:
|
||||
up(&winch_handler_sem);
|
||||
}
|
||||
|
||||
static void unregister_winch(struct tty_struct *tty)
|
||||
|
@ -756,7 +759,7 @@ static void unregister_winch(struct tty_struct *tty)
|
|||
struct list_head *ele;
|
||||
struct winch *winch, *found = NULL;
|
||||
|
||||
down(&winch_handler_sem);
|
||||
spin_lock(&winch_handler_lock);
|
||||
list_for_each(ele, &winch_handlers){
|
||||
winch = list_entry(ele, struct winch, list);
|
||||
if(winch->tty == tty){
|
||||
|
@ -764,20 +767,25 @@ static void unregister_winch(struct tty_struct *tty)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(found == NULL)
|
||||
goto out;
|
||||
goto err;
|
||||
|
||||
list_del(&winch->list);
|
||||
spin_unlock(&winch_handler_lock);
|
||||
|
||||
if(winch->pid != -1)
|
||||
os_kill_process(winch->pid, 1);
|
||||
|
||||
free_irq(WINCH_IRQ, winch);
|
||||
list_del(&winch->list);
|
||||
kfree(winch);
|
||||
out:
|
||||
up(&winch_handler_sem);
|
||||
|
||||
return;
|
||||
err:
|
||||
spin_unlock(&winch_handler_lock);
|
||||
}
|
||||
|
||||
/* XXX: No lock as it's an exitcall... is this valid? Depending on cleanup
|
||||
* order... are we sure that nothing else is done on the list? */
|
||||
static void winch_cleanup(void)
|
||||
{
|
||||
struct list_head *ele;
|
||||
|
@ -786,6 +794,9 @@ static void winch_cleanup(void)
|
|||
list_for_each(ele, &winch_handlers){
|
||||
winch = list_entry(ele, struct winch, list);
|
||||
if(winch->fd != -1){
|
||||
/* Why is this different from the above free_irq(),
|
||||
* which deactivates SIGIO? This searches the FD
|
||||
* somewhere else and removes it from the list... */
|
||||
deactivate_fd(winch->fd, WINCH_IRQ);
|
||||
os_close_file(winch->fd);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
|
|||
extern int is_remapped(void *virt);
|
||||
extern int physmem_remove_mapping(void *virt);
|
||||
extern void physmem_forget_descriptor(int fd);
|
||||
extern unsigned long to_phys(void *virt);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ extern int restore_fp_registers(int pid, unsigned long *fp_regs);
|
|||
extern void save_registers(int pid, union uml_pt_regs *regs);
|
||||
extern void restore_registers(int pid, union uml_pt_regs *regs);
|
||||
extern void init_registers(int pid);
|
||||
extern void get_safe_registers(unsigned long * regs);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -20,11 +20,24 @@
|
|||
#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX)
|
||||
#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI)
|
||||
#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI)
|
||||
#define PT_SYSCALL_ARG6_OFFSET PT_OFFSET(EBP)
|
||||
|
||||
#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX)
|
||||
|
||||
#define REGS_SYSCALL_NR EAX /* This is used before a system call */
|
||||
#define REGS_SYSCALL_ARG1 EBX
|
||||
#define REGS_SYSCALL_ARG2 ECX
|
||||
#define REGS_SYSCALL_ARG3 EDX
|
||||
#define REGS_SYSCALL_ARG4 ESI
|
||||
#define REGS_SYSCALL_ARG5 EDI
|
||||
#define REGS_SYSCALL_ARG6 EBP
|
||||
|
||||
#define REGS_IP_INDEX EIP
|
||||
#define REGS_SP_INDEX UESP
|
||||
|
||||
#define PT_IP_OFFSET PT_OFFSET(EIP)
|
||||
#define PT_IP(regs) ((regs)[EIP])
|
||||
#define PT_SP_OFFSET PT_OFFSET(UESP)
|
||||
#define PT_SP(regs) ((regs)[UESP])
|
||||
|
||||
#ifndef FRAME_SIZE
|
||||
|
|
65
arch/um/include/sysdep-i386/stub.h
Normal file
65
arch/um/include/sysdep-i386/stub.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __SYSDEP_STUB_H
|
||||
#define __SYSDEP_STUB_H
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
extern void stub_segv_handler(int sig);
|
||||
extern void stub_clone_handler(void);
|
||||
|
||||
#define STUB_SYSCALL_RET EAX
|
||||
#define STUB_MMAP_NR __NR_mmap2
|
||||
#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT)
|
||||
|
||||
static inline long stub_syscall2(long syscall, long arg1, long arg2)
|
||||
{
|
||||
long ret;
|
||||
|
||||
__asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
|
||||
__asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
|
||||
__asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
|
||||
__asm__("int $0x80;" : : : "%eax");
|
||||
__asm__ __volatile__("movl %%eax, %0; " : "=g" (ret) :);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
|
||||
{
|
||||
__asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
|
||||
return(stub_syscall2(syscall, arg1, arg2));
|
||||
}
|
||||
|
||||
static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
|
||||
long arg4)
|
||||
{
|
||||
__asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
|
||||
return(stub_syscall3(syscall, arg1, arg2, arg3));
|
||||
}
|
||||
|
||||
static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
|
||||
long arg4, long arg5, long arg6)
|
||||
{
|
||||
long ret;
|
||||
__asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
|
||||
__asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
|
||||
__asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
|
||||
__asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
|
||||
__asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
|
||||
__asm__("movl %0, %%edi; " : : "g" (arg5) : "%edi");
|
||||
__asm__ __volatile__("pushl %%ebp ; movl %1, %%ebp; "
|
||||
"int $0x80; popl %%ebp ; "
|
||||
"movl %%eax, %0; " : "=g" (ret) : "g" (arg6) : "%eax");
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static inline void trap_myself(void)
|
||||
{
|
||||
__asm("int3");
|
||||
}
|
||||
|
||||
#endif
|
|
@ -55,6 +55,20 @@
|
|||
#define PTRACE_OLDSETOPTIONS 21
|
||||
#endif
|
||||
|
||||
/* These are before the system call, so the the system call number is RAX
|
||||
* rather than ORIG_RAX, and arg4 is R10 rather than RCX
|
||||
*/
|
||||
#define REGS_SYSCALL_NR PT_INDEX(RAX)
|
||||
#define REGS_SYSCALL_ARG1 PT_INDEX(RDI)
|
||||
#define REGS_SYSCALL_ARG2 PT_INDEX(RSI)
|
||||
#define REGS_SYSCALL_ARG3 PT_INDEX(RDX)
|
||||
#define REGS_SYSCALL_ARG4 PT_INDEX(R10)
|
||||
#define REGS_SYSCALL_ARG5 PT_INDEX(R8)
|
||||
#define REGS_SYSCALL_ARG6 PT_INDEX(R9)
|
||||
|
||||
#define REGS_IP_INDEX PT_INDEX(RIP)
|
||||
#define REGS_SP_INDEX PT_INDEX(RSP)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
58
arch/um/include/sysdep-x86_64/stub.h
Normal file
58
arch/um/include/sysdep-x86_64/stub.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __SYSDEP_STUB_H
|
||||
#define __SYSDEP_STUB_H
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <sysdep/ptrace_user.h>
|
||||
|
||||
extern void stub_segv_handler(int sig);
|
||||
extern void stub_clone_handler(void);
|
||||
|
||||
#define STUB_SYSCALL_RET PT_INDEX(RAX)
|
||||
#define STUB_MMAP_NR __NR_mmap
|
||||
#define MMAP_OFFSET(o) (o)
|
||||
|
||||
static inline long stub_syscall2(long syscall, long arg1, long arg2)
|
||||
{
|
||||
long ret;
|
||||
|
||||
__asm__("movq %0, %%rsi; " : : "g" (arg2) : "%rsi");
|
||||
__asm__("movq %0, %%rdi; " : : "g" (arg1) : "%rdi");
|
||||
__asm__("movq %0, %%rax; " : : "g" (syscall) : "%rax");
|
||||
__asm__("syscall;" : : : "%rax", "%r11", "%rcx");
|
||||
__asm__ __volatile__("movq %%rax, %0; " : "=g" (ret) :);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
|
||||
{
|
||||
__asm__("movq %0, %%rdx; " : : "g" (arg3) : "%rdx");
|
||||
return(stub_syscall2(syscall, arg1, arg2));
|
||||
}
|
||||
|
||||
static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
|
||||
long arg4)
|
||||
{
|
||||
__asm__("movq %0, %%r10; " : : "g" (arg4) : "%r10");
|
||||
return(stub_syscall3(syscall, arg1, arg2, arg3));
|
||||
}
|
||||
|
||||
static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
|
||||
long arg4, long arg5, long arg6)
|
||||
{
|
||||
__asm__("movq %0, %%r9; " : : "g" (arg6) : "%r9");
|
||||
__asm__("movq %0, %%r8; " : : "g" (arg5) : "%r8");
|
||||
return(stub_syscall4(syscall, arg1, arg2, arg3, arg4));
|
||||
}
|
||||
|
||||
static inline void trap_myself(void)
|
||||
{
|
||||
__asm("int3");
|
||||
}
|
||||
|
||||
#endif
|
|
@ -10,6 +10,7 @@ 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);
|
||||
|
|
|
@ -37,31 +37,25 @@ struct host_vm_op {
|
|||
extern void mprotect_kernel_vm(int w);
|
||||
extern void force_flush_all(void);
|
||||
extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
|
||||
unsigned long end_addr, int force, int data,
|
||||
void (*do_ops)(int, struct host_vm_op *, int));
|
||||
unsigned long end_addr, int force,
|
||||
void (*do_ops)(union mm_context *,
|
||||
struct host_vm_op *, int));
|
||||
extern int flush_tlb_kernel_range_common(unsigned long start,
|
||||
unsigned long end);
|
||||
|
||||
extern int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
|
||||
int r, int w, int x, struct host_vm_op *ops, int index,
|
||||
int last_filled, int data,
|
||||
void (*do_ops)(int, struct host_vm_op *, int));
|
||||
int last_filled, union mm_context *mmu,
|
||||
void (*do_ops)(union mm_context *, struct host_vm_op *,
|
||||
int));
|
||||
extern int add_munmap(unsigned long addr, unsigned long len,
|
||||
struct host_vm_op *ops, int index, int last_filled,
|
||||
int data, void (*do_ops)(int, struct host_vm_op *, int));
|
||||
union mm_context *mmu,
|
||||
void (*do_ops)(union mm_context *, struct host_vm_op *,
|
||||
int));
|
||||
extern int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
|
||||
int x, struct host_vm_op *ops, int index,
|
||||
int last_filled, int data,
|
||||
void (*do_ops)(int, struct host_vm_op *, int));
|
||||
int last_filled, union mm_context *mmu,
|
||||
void (*do_ops)(union mm_context *, struct host_vm_op *,
|
||||
int));
|
||||
#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:
|
||||
*/
|
||||
|
|
|
@ -67,6 +67,12 @@ SECTIONS
|
|||
*(.stub .text.* .gnu.linkonce.t.*)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
|
||||
. = ALIGN(4096);
|
||||
__syscall_stub_start = .;
|
||||
*(.__syscall_stub*)
|
||||
__syscall_stub_end = .;
|
||||
. = ALIGN(4096);
|
||||
} =0x90909090
|
||||
.fini : {
|
||||
KEEP (*(.fini))
|
||||
|
|
|
@ -353,6 +353,8 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
|
|||
|
||||
#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
|
||||
|
||||
extern int __syscall_stub_start, __binary_start;
|
||||
|
||||
void setup_physmem(unsigned long start, unsigned long reserve_end,
|
||||
unsigned long len, unsigned long highmem)
|
||||
{
|
||||
|
@ -371,6 +373,12 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
|
|||
exit(1);
|
||||
}
|
||||
|
||||
/* Special kludge - This page will be mapped in to userspace processes
|
||||
* from physmem_fd, so it needs to be written out there.
|
||||
*/
|
||||
os_seek_file(physmem_fd, __pa(&__syscall_stub_start));
|
||||
os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE);
|
||||
|
||||
bootmap_size = init_bootmem(pfn, pfn + delta);
|
||||
free_bootmem(__pa(reserve_end) + bootmap_size,
|
||||
len - bootmap_size - reserve);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "uml-config.h"
|
||||
#include "choose-mode.h"
|
||||
#include "mode.h"
|
||||
#include "tempfile.h"
|
||||
#ifdef UML_CONFIG_MODE_SKAS
|
||||
#include "skas.h"
|
||||
#include "skas_ptrace.h"
|
||||
|
@ -358,11 +359,16 @@ void forward_pending_sigio(int target)
|
|||
kill(target, SIGIO);
|
||||
}
|
||||
|
||||
int ptrace_faultinfo = 0;
|
||||
int proc_mm = 1;
|
||||
|
||||
extern void *__syscall_stub_start, __syscall_stub_end;
|
||||
|
||||
#ifdef UML_CONFIG_MODE_SKAS
|
||||
static inline int check_skas3_ptrace_support(void)
|
||||
static inline void check_skas3_ptrace_support(void)
|
||||
{
|
||||
struct ptrace_faultinfo fi;
|
||||
int pid, n, ret = 1;
|
||||
int pid, n;
|
||||
|
||||
printf("Checking for the skas3 patch in the host...");
|
||||
pid = start_ptraced_child();
|
||||
|
@ -374,33 +380,31 @@ static inline int check_skas3_ptrace_support(void)
|
|||
else {
|
||||
perror("not found");
|
||||
}
|
||||
ret = 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ptrace_faultinfo = 1;
|
||||
printf("found\n");
|
||||
}
|
||||
|
||||
init_registers(pid);
|
||||
stop_ptraced_child(pid, 1, 1);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int can_do_skas(void)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
printf("Checking for /proc/mm...");
|
||||
if (os_access("/proc/mm", OS_ACC_W_OK) < 0) {
|
||||
proc_mm = 0;
|
||||
printf("not found\n");
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
printf("found\n");
|
||||
}
|
||||
|
||||
ret = check_skas3_ptrace_support();
|
||||
out:
|
||||
return ret;
|
||||
check_skas3_ptrace_support();
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
int can_do_skas(void)
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
# Licensed under the GPL
|
||||
#
|
||||
|
||||
obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
|
||||
obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
|
||||
syscall_kern.o syscall_user.o tlb.o trap_user.o uaccess.o \
|
||||
|
||||
subdir- := util
|
||||
|
||||
USER_OBJS := process.o
|
||||
USER_OBJS := process.o clone.o
|
||||
|
||||
include arch/um/scripts/Makefile.rules
|
||||
|
||||
# clone.o is in the stub, so it can't be built with profiling
|
||||
$(obj)/clone.o : c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
|
||||
|
|
44
arch/um/kernel/skas/clone.c
Normal file
44
arch/um/kernel/skas/clone.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/page.h>
|
||||
#include "ptrace_user.h"
|
||||
#include "skas.h"
|
||||
#include "stub-data.h"
|
||||
#include "uml-config.h"
|
||||
#include "sysdep/stub.h"
|
||||
|
||||
/* This is in a separate file because it needs to be compiled with any
|
||||
* extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
|
||||
*/
|
||||
void __attribute__ ((__section__ (".__syscall_stub")))
|
||||
stub_clone_handler(void)
|
||||
{
|
||||
long err;
|
||||
struct stub_data *from = (struct stub_data *) UML_CONFIG_STUB_DATA;
|
||||
|
||||
err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
|
||||
UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 -
|
||||
sizeof(void *));
|
||||
if(err != 0)
|
||||
goto out;
|
||||
|
||||
err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
|
||||
if(err)
|
||||
goto out;
|
||||
|
||||
err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
|
||||
(long) &from->timer, 0);
|
||||
if(err)
|
||||
goto out;
|
||||
|
||||
err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
|
||||
from->fd, from->offset);
|
||||
out:
|
||||
/* save current result. Parent: pid; child: retcode of mmap */
|
||||
from->err = err;
|
||||
trap_myself();
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
void flush_thread_skas(void)
|
||||
{
|
||||
force_flush_all();
|
||||
switch_mm_skas(current->mm->context.skas.mm_fd);
|
||||
switch_mm_skas(¤t->mm->context.skas.id);
|
||||
}
|
||||
|
||||
void start_thread_skas(struct pt_regs *regs, unsigned long eip,
|
||||
|
|
17
arch/um/kernel/skas/include/mm_id.h
Normal file
17
arch/um/kernel/skas/include/mm_id.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __MM_ID_H
|
||||
#define __MM_ID_H
|
||||
|
||||
struct mm_id {
|
||||
union {
|
||||
int mm_fd;
|
||||
int pid;
|
||||
} u;
|
||||
unsigned long stack;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -6,10 +6,15 @@
|
|||
#ifndef __SKAS_MMU_H
|
||||
#define __SKAS_MMU_H
|
||||
|
||||
#include "mm_id.h"
|
||||
|
||||
struct mmu_context_skas {
|
||||
int mm_fd;
|
||||
struct mm_id id;
|
||||
unsigned long last_page_table;
|
||||
};
|
||||
|
||||
extern void switch_mm_skas(struct mm_id * mm_idp);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
#ifndef __SKAS_H
|
||||
#define __SKAS_H
|
||||
|
||||
#include "mm_id.h"
|
||||
#include "sysdep/ptrace.h"
|
||||
|
||||
extern int userspace_pid[];
|
||||
extern int proc_mm, ptrace_faultinfo;
|
||||
|
||||
extern void switch_threads(void *me, void *next);
|
||||
extern void thread_wait(void *sw, void *fb);
|
||||
|
@ -22,16 +24,18 @@ extern void new_thread_proc(void *stack, void (*handler)(int sig));
|
|||
extern void remove_sigstack(void);
|
||||
extern void new_thread_handler(int sig);
|
||||
extern void handle_syscall(union uml_pt_regs *regs);
|
||||
extern void map(int fd, unsigned long virt, unsigned long len, int r, int w,
|
||||
int x, int phys_fd, unsigned long long offset);
|
||||
extern int unmap(int fd, void *addr, unsigned long len);
|
||||
extern int protect(int fd, unsigned long addr, unsigned long len,
|
||||
int r, int w, int x);
|
||||
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);
|
||||
extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len);
|
||||
extern int protect(struct mm_id * mm_idp, unsigned long addr,
|
||||
unsigned long len, int r, int w, int x);
|
||||
extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
|
||||
extern int new_mm(int from);
|
||||
extern void start_userspace(int cpu);
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
18
arch/um/kernel/skas/include/stub-data.h
Normal file
18
arch/um/kernel/skas/include/stub-data.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __STUB_DATA_H
|
||||
#define __STUB_DATA_H
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
struct stub_data {
|
||||
long offset;
|
||||
int fd;
|
||||
struct itimerval timer;
|
||||
long err;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -5,7 +5,9 @@
|
|||
|
||||
#include "linux/config.h"
|
||||
#include "linux/mm.h"
|
||||
#include "asm/pgtable.h"
|
||||
#include "mem_user.h"
|
||||
#include "skas.h"
|
||||
|
||||
unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
|
||||
unsigned long *task_size_out)
|
||||
|
@ -18,7 +20,9 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
|
|||
*task_size_out = CONFIG_HOST_TASK_SIZE;
|
||||
#else
|
||||
*host_size_out = top;
|
||||
*task_size_out = top;
|
||||
if (proc_mm && ptrace_faultinfo)
|
||||
*task_size_out = top;
|
||||
else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
|
||||
#endif
|
||||
return(((unsigned long) set_task_sizes_skas) & ~0xffffff);
|
||||
}
|
||||
|
|
|
@ -3,100 +3,171 @@
|
|||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/unistd.h>
|
||||
#include "mem_user.h"
|
||||
#include "mem.h"
|
||||
#include "mm_id.h"
|
||||
#include "user.h"
|
||||
#include "os.h"
|
||||
#include "proc_mm.h"
|
||||
#include "ptrace_user.h"
|
||||
#include "user_util.h"
|
||||
#include "kern_util.h"
|
||||
#include "task.h"
|
||||
#include "registers.h"
|
||||
#include "uml-config.h"
|
||||
#include "sysdep/ptrace.h"
|
||||
#include "sysdep/stub.h"
|
||||
#include "skas.h"
|
||||
|
||||
void map(int fd, unsigned long virt, unsigned long len, int r, int w,
|
||||
int x, int phys_fd, unsigned long long offset)
|
||||
extern unsigned long syscall_stub, __syscall_stub_start;
|
||||
|
||||
extern void wait_stub_done(int pid, int sig, char * fname);
|
||||
|
||||
static long run_syscall_stub(struct mm_id * mm_idp, int syscall,
|
||||
unsigned long *args)
|
||||
{
|
||||
struct proc_mm_op map;
|
||||
int prot, n;
|
||||
int n, pid = mm_idp->u.pid;
|
||||
unsigned long regs[MAX_REG_NR];
|
||||
|
||||
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
|
||||
(x ? PROT_EXEC : 0);
|
||||
get_safe_registers(regs);
|
||||
regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
|
||||
((unsigned long) &syscall_stub -
|
||||
(unsigned long) &__syscall_stub_start);
|
||||
/* XXX Don't have a define for starting a syscall */
|
||||
regs[REGS_SYSCALL_NR] = syscall;
|
||||
regs[REGS_SYSCALL_ARG1] = args[0];
|
||||
regs[REGS_SYSCALL_ARG2] = args[1];
|
||||
regs[REGS_SYSCALL_ARG3] = args[2];
|
||||
regs[REGS_SYSCALL_ARG4] = args[3];
|
||||
regs[REGS_SYSCALL_ARG5] = args[4];
|
||||
regs[REGS_SYSCALL_ARG6] = args[5];
|
||||
n = ptrace_setregs(pid, regs);
|
||||
if(n < 0){
|
||||
printk("run_syscall_stub : PTRACE_SETREGS failed, "
|
||||
"errno = %d\n", n);
|
||||
return(n);
|
||||
}
|
||||
|
||||
map = ((struct proc_mm_op) { .op = MM_MMAP,
|
||||
.u =
|
||||
{ .mmap =
|
||||
{ .addr = virt,
|
||||
.len = len,
|
||||
.prot = prot,
|
||||
.flags = MAP_SHARED |
|
||||
MAP_FIXED,
|
||||
.fd = phys_fd,
|
||||
.offset = offset
|
||||
} } } );
|
||||
n = os_write_file(fd, &map, sizeof(map));
|
||||
if(n != sizeof(map))
|
||||
printk("map : /proc/mm map failed, err = %d\n", -n);
|
||||
wait_stub_done(pid, 0, "run_syscall_stub");
|
||||
|
||||
return(*((unsigned long *) mm_idp->stack));
|
||||
}
|
||||
|
||||
int unmap(int fd, void *addr, unsigned long len)
|
||||
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)
|
||||
{
|
||||
struct proc_mm_op unmap;
|
||||
int n;
|
||||
int prot, n;
|
||||
|
||||
unmap = ((struct proc_mm_op) { .op = MM_MUNMAP,
|
||||
.u =
|
||||
{ .munmap =
|
||||
{ .addr = (unsigned long) addr,
|
||||
.len = len } } } );
|
||||
n = os_write_file(fd, &unmap, sizeof(unmap));
|
||||
if(n != sizeof(unmap)) {
|
||||
if(n < 0)
|
||||
return(n);
|
||||
else if(n > 0)
|
||||
return(-EIO);
|
||||
}
|
||||
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
|
||||
(x ? PROT_EXEC : 0);
|
||||
|
||||
return(0);
|
||||
if(proc_mm){
|
||||
struct proc_mm_op map;
|
||||
int fd = mm_idp->u.mm_fd;
|
||||
map = ((struct proc_mm_op) { .op = MM_MMAP,
|
||||
.u =
|
||||
{ .mmap =
|
||||
{ .addr = virt,
|
||||
.len = len,
|
||||
.prot = prot,
|
||||
.flags = MAP_SHARED |
|
||||
MAP_FIXED,
|
||||
.fd = phys_fd,
|
||||
.offset= offset
|
||||
} } } );
|
||||
n = os_write_file(fd, &map, sizeof(map));
|
||||
if(n != sizeof(map))
|
||||
printk("map : /proc/mm map failed, err = %d\n", -n);
|
||||
}
|
||||
else {
|
||||
long res;
|
||||
unsigned long args[] = { virt, len, prot,
|
||||
MAP_SHARED | MAP_FIXED, phys_fd,
|
||||
MMAP_OFFSET(offset) };
|
||||
|
||||
res = run_syscall_stub(mm_idp, STUB_MMAP_NR, args);
|
||||
if((void *) res == MAP_FAILED)
|
||||
printk("mmap stub failed, errno = %d\n", res);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int protect(int fd, unsigned long addr, unsigned long len, int r, int w,
|
||||
int x, int must_succeed)
|
||||
int unmap(struct mm_id *mm_idp, void *addr, unsigned long len)
|
||||
{
|
||||
struct proc_mm_op protect;
|
||||
int prot, n;
|
||||
int n;
|
||||
|
||||
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
|
||||
(x ? PROT_EXEC : 0);
|
||||
if(proc_mm){
|
||||
struct proc_mm_op unmap;
|
||||
int fd = mm_idp->u.mm_fd;
|
||||
unmap = ((struct proc_mm_op) { .op = MM_MUNMAP,
|
||||
.u =
|
||||
{ .munmap =
|
||||
{ .addr =
|
||||
(unsigned long) addr,
|
||||
.len = len } } } );
|
||||
n = os_write_file(fd, &unmap, sizeof(unmap));
|
||||
if(n != sizeof(unmap)) {
|
||||
if(n < 0)
|
||||
return(n);
|
||||
else if(n > 0)
|
||||
return(-EIO);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int res;
|
||||
unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
|
||||
0 };
|
||||
|
||||
protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
|
||||
.u =
|
||||
{ .mprotect =
|
||||
{ .addr = (unsigned long) addr,
|
||||
.len = len,
|
||||
.prot = prot } } } );
|
||||
res = run_syscall_stub(mm_idp, __NR_munmap, args);
|
||||
if(res < 0)
|
||||
printk("munmap stub failed, errno = %d\n", res);
|
||||
}
|
||||
|
||||
n = os_write_file(fd, &protect, sizeof(protect));
|
||||
if(n != sizeof(protect)) {
|
||||
if(n == 0) return(0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(must_succeed)
|
||||
panic("protect failed, err = %d", -n);
|
||||
int protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len,
|
||||
int r, int w, int x)
|
||||
{
|
||||
struct proc_mm_op protect;
|
||||
int prot, n;
|
||||
|
||||
return(-EIO);
|
||||
}
|
||||
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
|
||||
(x ? PROT_EXEC : 0);
|
||||
|
||||
return(0);
|
||||
if(proc_mm){
|
||||
int fd = mm_idp->u.mm_fd;
|
||||
protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
|
||||
.u =
|
||||
{ .mprotect =
|
||||
{ .addr =
|
||||
(unsigned long) addr,
|
||||
.len = len,
|
||||
.prot = prot } } } );
|
||||
|
||||
n = os_write_file(fd, &protect, sizeof(protect));
|
||||
if(n != sizeof(protect))
|
||||
panic("protect failed, err = %d", -n);
|
||||
}
|
||||
else {
|
||||
int res;
|
||||
unsigned long args[] = { addr, len, prot, 0, 0, 0 };
|
||||
|
||||
res = run_syscall_stub(mm_idp, __NR_mprotect, args);
|
||||
if(res < 0)
|
||||
panic("mprotect stub failed, errno = %d\n", res);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void before_mem_skas(unsigned long unused)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
||||
|
|
|
@ -3,46 +3,143 @@
|
|||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include "linux/config.h"
|
||||
#include "linux/sched.h"
|
||||
#include "linux/list.h"
|
||||
#include "linux/spinlock.h"
|
||||
#include "linux/slab.h"
|
||||
#include "linux/errno.h"
|
||||
#include "linux/mm.h"
|
||||
#include "asm/current.h"
|
||||
#include "asm/segment.h"
|
||||
#include "asm/mmu.h"
|
||||
#include "asm/pgalloc.h"
|
||||
#include "asm/pgtable.h"
|
||||
#include "os.h"
|
||||
#include "skas.h"
|
||||
|
||||
extern int __syscall_stub_start;
|
||||
|
||||
static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
|
||||
unsigned long kernel)
|
||||
{
|
||||
pgd_t *pgd;
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
|
||||
spin_lock(&mm->page_table_lock);
|
||||
pgd = pgd_offset(mm, proc);
|
||||
pud = pud_alloc(mm, pgd, proc);
|
||||
if (!pud)
|
||||
goto out;
|
||||
|
||||
pmd = pmd_alloc(mm, pud, proc);
|
||||
if (!pmd)
|
||||
goto out_pmd;
|
||||
|
||||
pte = pte_alloc_map(mm, pmd, proc);
|
||||
if (!pte)
|
||||
goto out_pte;
|
||||
|
||||
/* There's an interaction between the skas0 stub pages, stack
|
||||
* randomization, and the BUG at the end of exit_mmap. exit_mmap
|
||||
* checks that the number of page tables freed is the same as had
|
||||
* been allocated. If the stack is on the last page table page,
|
||||
* then the stack pte page will be freed, and if not, it won't. To
|
||||
* avoid having to know where the stack is, or if the process mapped
|
||||
* something at the top of its address space for some other reason,
|
||||
* we set TASK_SIZE to end at the start of the last page table.
|
||||
* This keeps exit_mmap off the last page, but introduces a leak
|
||||
* of that page. So, we hang onto it here and free it in
|
||||
* destroy_context_skas.
|
||||
*/
|
||||
|
||||
mm->context.skas.last_page_table = pmd_page_kernel(*pmd);
|
||||
|
||||
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
|
||||
*pte = pte_mkexec(*pte);
|
||||
*pte = pte_wrprotect(*pte);
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
return(0);
|
||||
|
||||
out_pmd:
|
||||
pud_free(pud);
|
||||
out_pte:
|
||||
pmd_free(pmd);
|
||||
out:
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
return(-ENOMEM);
|
||||
}
|
||||
|
||||
int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
|
||||
{
|
||||
int from;
|
||||
struct mm_struct *cur_mm = current->mm;
|
||||
struct mm_id *cur_mm_id = &cur_mm->context.skas.id;
|
||||
struct mm_id *mm_id = &mm->context.skas.id;
|
||||
unsigned long stack;
|
||||
int from, ret;
|
||||
|
||||
if((current->mm != NULL) && (current->mm != &init_mm))
|
||||
from = current->mm->context.skas.mm_fd;
|
||||
else from = -1;
|
||||
if(proc_mm){
|
||||
if((cur_mm != NULL) && (cur_mm != &init_mm))
|
||||
from = cur_mm->context.skas.id.u.mm_fd;
|
||||
else from = -1;
|
||||
|
||||
mm->context.skas.mm_fd = new_mm(from);
|
||||
if(mm->context.skas.mm_fd < 0){
|
||||
printk("init_new_context_skas - new_mm failed, errno = %d\n",
|
||||
mm->context.skas.mm_fd);
|
||||
return(mm->context.skas.mm_fd);
|
||||
ret = new_mm(from);
|
||||
if(ret < 0){
|
||||
printk("init_new_context_skas - new_mm failed, "
|
||||
"errno = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mm_id->u.mm_fd = ret;
|
||||
}
|
||||
else {
|
||||
/* This zeros the entry that pgd_alloc didn't, needed since
|
||||
* we are about to reinitialize it, and want mm.nr_ptes to
|
||||
* be accurate.
|
||||
*/
|
||||
mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);
|
||||
|
||||
ret = init_stub_pte(mm, CONFIG_STUB_CODE,
|
||||
(unsigned long) &__syscall_stub_start);
|
||||
if(ret)
|
||||
goto out;
|
||||
|
||||
ret = -ENOMEM;
|
||||
stack = get_zeroed_page(GFP_KERNEL);
|
||||
if(stack == 0)
|
||||
goto out;
|
||||
mm_id->stack = stack;
|
||||
|
||||
ret = init_stub_pte(mm, CONFIG_STUB_DATA, stack);
|
||||
if(ret)
|
||||
goto out_free;
|
||||
|
||||
mm->nr_ptes--;
|
||||
|
||||
if((cur_mm != NULL) && (cur_mm != &init_mm))
|
||||
mm_id->u.pid = copy_context_skas0(stack,
|
||||
cur_mm_id->u.pid);
|
||||
else mm_id->u.pid = start_userspace(stack);
|
||||
}
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
free_page(mm_id->stack);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void destroy_context_skas(struct mm_struct *mm)
|
||||
{
|
||||
os_close_file(mm->context.skas.mm_fd);
|
||||
}
|
||||
struct mmu_context_skas *mmu = &mm->context.skas;
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
||||
if(proc_mm)
|
||||
os_close_file(mmu->id.u.mm_fd);
|
||||
else {
|
||||
os_kill_ptraced_process(mmu->id.u.pid, 1);
|
||||
free_page(mmu->id.stack);
|
||||
free_page(mmu->last_page_table);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
|
@ -13,7 +13,9 @@
|
|||
#include <sys/wait.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/time.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/types.h>
|
||||
#include "user.h"
|
||||
#include "ptrace_user.h"
|
||||
#include "time_user.h"
|
||||
|
@ -21,13 +23,18 @@
|
|||
#include "user_util.h"
|
||||
#include "kern_util.h"
|
||||
#include "skas.h"
|
||||
#include "stub-data.h"
|
||||
#include "mm_id.h"
|
||||
#include "sysdep/sigcontext.h"
|
||||
#include "sysdep/stub.h"
|
||||
#include "os.h"
|
||||
#include "proc_mm.h"
|
||||
#include "skas_ptrace.h"
|
||||
#include "chan_user.h"
|
||||
#include "signal_user.h"
|
||||
#include "registers.h"
|
||||
#include "mem.h"
|
||||
#include "uml-config.h"
|
||||
#include "process.h"
|
||||
|
||||
int is_skas_winch(int pid, int fd, void *data)
|
||||
|
@ -39,20 +46,55 @@ int is_skas_winch(int pid, int fd, void *data)
|
|||
return(1);
|
||||
}
|
||||
|
||||
void wait_stub_done(int pid, int sig, char * fname)
|
||||
{
|
||||
int n, status, err;
|
||||
|
||||
do {
|
||||
if ( sig != -1 ) {
|
||||
err = ptrace(PTRACE_CONT, pid, 0, sig);
|
||||
if(err)
|
||||
panic("%s : continue failed, errno = %d\n",
|
||||
fname, errno);
|
||||
}
|
||||
sig = 0;
|
||||
|
||||
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
|
||||
} while((n >= 0) && WIFSTOPPED(status) &&
|
||||
(WSTOPSIG(status) == SIGVTALRM));
|
||||
|
||||
if((n < 0) || !WIFSTOPPED(status) ||
|
||||
(WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status != SIGTRAP))){
|
||||
panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
|
||||
"pid = %d, n = %d, errno = %d, status = 0x%x\n",
|
||||
fname, pid, n, errno, status);
|
||||
}
|
||||
}
|
||||
|
||||
void get_skas_faultinfo(int pid, struct faultinfo * fi)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
|
||||
err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
|
||||
if(err)
|
||||
panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
|
||||
"errno = %d\n", errno);
|
||||
if(ptrace_faultinfo){
|
||||
err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
|
||||
if(err)
|
||||
panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
|
||||
"errno = %d\n", errno);
|
||||
|
||||
/* Special handling for i386, which has different structs */
|
||||
if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
|
||||
memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
|
||||
sizeof(struct faultinfo) -
|
||||
sizeof(struct ptrace_faultinfo));
|
||||
/* Special handling for i386, which has different structs */
|
||||
if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
|
||||
memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
|
||||
sizeof(struct faultinfo) -
|
||||
sizeof(struct ptrace_faultinfo));
|
||||
}
|
||||
else {
|
||||
wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo");
|
||||
|
||||
/* faultinfo is prepared by the stub-segv-handler at start of
|
||||
* the stub stack page. We just have to copy it.
|
||||
*/
|
||||
memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_segv(int pid, union uml_pt_regs * regs)
|
||||
|
@ -91,11 +133,56 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
|
|||
handle_syscall(regs);
|
||||
}
|
||||
|
||||
static int userspace_tramp(void *arg)
|
||||
extern int __syscall_stub_start;
|
||||
|
||||
static int userspace_tramp(void *stack)
|
||||
{
|
||||
init_new_thread_signals(0);
|
||||
enable_timer();
|
||||
void *addr;
|
||||
|
||||
ptrace(PTRACE_TRACEME, 0, 0, 0);
|
||||
|
||||
init_new_thread_signals(1);
|
||||
enable_timer();
|
||||
|
||||
if(!proc_mm){
|
||||
/* This has a pte, but it can't be mapped in with the usual
|
||||
* tlb_flush mechanism because this is part of that mechanism
|
||||
*/
|
||||
int fd;
|
||||
__u64 offset;
|
||||
|
||||
fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
|
||||
addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(),
|
||||
PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
|
||||
if(addr == MAP_FAILED){
|
||||
printk("mapping mmap stub failed, errno = %d\n",
|
||||
errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(stack != NULL){
|
||||
fd = phys_mapping(to_phys(stack), &offset);
|
||||
addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(),
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_SHARED, fd, offset);
|
||||
if(addr == MAP_FAILED){
|
||||
printk("mapping segfault stack failed, "
|
||||
"errno = %d\n", errno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!ptrace_faultinfo && (stack != NULL)){
|
||||
unsigned long v = UML_CONFIG_STUB_CODE +
|
||||
(unsigned long) stub_segv_handler -
|
||||
(unsigned long) &__syscall_stub_start;
|
||||
|
||||
set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
|
||||
set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
|
||||
SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
|
||||
SIGUSR1, -1);
|
||||
}
|
||||
|
||||
os_stop_process(os_getpid());
|
||||
return(0);
|
||||
}
|
||||
|
@ -105,11 +192,11 @@ static int userspace_tramp(void *arg)
|
|||
#define NR_CPUS 1
|
||||
int userspace_pid[NR_CPUS];
|
||||
|
||||
void start_userspace(int cpu)
|
||||
int start_userspace(unsigned long stub_stack)
|
||||
{
|
||||
void *stack;
|
||||
unsigned long sp;
|
||||
int pid, status, n;
|
||||
int pid, status, n, flags;
|
||||
|
||||
stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
@ -117,8 +204,9 @@ void start_userspace(int cpu)
|
|||
panic("start_userspace : mmap failed, errno = %d", errno);
|
||||
sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
|
||||
|
||||
pid = clone(userspace_tramp, (void *) sp,
|
||||
CLONE_FILES | CLONE_VM | SIGCHLD, NULL);
|
||||
flags = CLONE_FILES | SIGCHLD;
|
||||
if(proc_mm) flags |= CLONE_VM;
|
||||
pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
|
||||
if(pid < 0)
|
||||
panic("start_userspace : clone failed, errno = %d", errno);
|
||||
|
||||
|
@ -140,7 +228,7 @@ void start_userspace(int cpu)
|
|||
if(munmap(stack, PAGE_SIZE) < 0)
|
||||
panic("start_userspace : munmap failed, errno = %d\n", errno);
|
||||
|
||||
userspace_pid[cpu] = pid;
|
||||
return(pid);
|
||||
}
|
||||
|
||||
void userspace(union uml_pt_regs *regs)
|
||||
|
@ -174,7 +262,9 @@ void userspace(union uml_pt_regs *regs)
|
|||
if(WIFSTOPPED(status)){
|
||||
switch(WSTOPSIG(status)){
|
||||
case SIGSEGV:
|
||||
handle_segv(pid, regs);
|
||||
if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo)
|
||||
user_signal(SIGSEGV, regs, pid);
|
||||
else handle_segv(pid, regs);
|
||||
break;
|
||||
case SIGTRAP + 0x80:
|
||||
handle_trap(pid, regs, local_using_sysemu);
|
||||
|
@ -194,6 +284,7 @@ void userspace(union uml_pt_regs *regs)
|
|||
printk("userspace - child stopped with signal "
|
||||
"%d\n", WSTOPSIG(status));
|
||||
}
|
||||
pid = userspace_pid[0];
|
||||
interrupt_end();
|
||||
|
||||
/* Avoid -ERESTARTSYS handling in host */
|
||||
|
@ -207,6 +298,67 @@ void userspace(union uml_pt_regs *regs)
|
|||
#define INIT_JMP_HALT 3
|
||||
#define INIT_JMP_REBOOT 4
|
||||
|
||||
|
||||
int copy_context_skas0(unsigned long new_stack, int pid)
|
||||
{
|
||||
int err;
|
||||
unsigned long regs[MAX_REG_NR];
|
||||
unsigned long current_stack = current_stub_stack();
|
||||
struct stub_data *data = (struct stub_data *) current_stack;
|
||||
struct stub_data *child_data = (struct stub_data *) new_stack;
|
||||
__u64 new_offset;
|
||||
int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
|
||||
|
||||
/* prepare offset and fd of child's stack as argument for parent's
|
||||
* and child's mmap2 calls
|
||||
*/
|
||||
*data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset),
|
||||
.fd = new_fd,
|
||||
.timer = ((struct itimerval)
|
||||
{ { 0, 1000000 / hz() },
|
||||
{ 0, 1000000 / hz() }})});
|
||||
get_safe_registers(regs);
|
||||
|
||||
/* Set parent's instruction pointer to start of clone-stub */
|
||||
regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
|
||||
(unsigned long) stub_clone_handler -
|
||||
(unsigned long) &__syscall_stub_start;
|
||||
regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
|
||||
sizeof(void *);
|
||||
err = ptrace_setregs(pid, regs);
|
||||
if(err < 0)
|
||||
panic("copy_context_skas0 : PTRACE_SETREGS failed, "
|
||||
"pid = %d, errno = %d\n", pid, errno);
|
||||
|
||||
/* set a well known return code for detection of child write failure */
|
||||
child_data->err = 12345678;
|
||||
|
||||
/* Wait, until parent has finished its work: read child's pid from
|
||||
* parent's stack, and check, if bad result.
|
||||
*/
|
||||
wait_stub_done(pid, 0, "copy_context_skas0");
|
||||
|
||||
pid = data->err;
|
||||
if(pid < 0)
|
||||
panic("copy_context_skas0 - stub-parent reports error %d\n",
|
||||
pid);
|
||||
|
||||
/* Wait, until child has finished too: read child's result from
|
||||
* child's stack and check it.
|
||||
*/
|
||||
wait_stub_done(pid, -1, "copy_context_skas0");
|
||||
if (child_data->err != UML_CONFIG_STUB_DATA)
|
||||
panic("copy_context_skas0 - stub-child reports error %d\n",
|
||||
child_data->err);
|
||||
|
||||
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
|
||||
(void *)PTRACE_O_TRACESYSGOOD) < 0)
|
||||
panic("copy_context_skas0 : PTRACE_SETOPTIONS failed, "
|
||||
"errno = %d\n", errno);
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
|
||||
void (*handler)(int))
|
||||
{
|
||||
|
@ -334,21 +486,19 @@ void reboot_skas(void)
|
|||
siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT);
|
||||
}
|
||||
|
||||
void switch_mm_skas(int mm_fd)
|
||||
void switch_mm_skas(struct mm_id *mm_idp)
|
||||
{
|
||||
int err;
|
||||
|
||||
#warning need cpu pid in switch_mm_skas
|
||||
err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd);
|
||||
if(err)
|
||||
panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n",
|
||||
errno);
|
||||
}
|
||||
|
||||
void kill_off_processes_skas(void)
|
||||
{
|
||||
#warning need to loop over userspace_pids in kill_off_processes_skas
|
||||
os_kill_ptraced_process(userspace_pid[0], 1);
|
||||
if(proc_mm){
|
||||
err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
|
||||
mm_idp->u.mm_fd);
|
||||
if(err)
|
||||
panic("switch_mm_skas - PTRACE_SWITCH_MM failed, "
|
||||
"errno = %d\n", errno);
|
||||
}
|
||||
else userspace_pid[0] = mm_idp->u.pid;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -175,9 +175,12 @@ static int start_kernel_proc(void *unused)
|
|||
return(0);
|
||||
}
|
||||
|
||||
extern int userspace_pid[];
|
||||
|
||||
int start_uml_skas(void)
|
||||
{
|
||||
start_userspace(0);
|
||||
if(proc_mm)
|
||||
userspace_pid[0] = start_userspace(0);
|
||||
|
||||
init_new_thread_signals(1);
|
||||
|
||||
|
@ -199,3 +202,31 @@ int thread_pid_skas(struct task_struct *task)
|
|||
#warning Need to look up userspace_pid by cpu
|
||||
return(userspace_pid[0]);
|
||||
}
|
||||
|
||||
void kill_off_processes_skas(void)
|
||||
{
|
||||
if(proc_mm)
|
||||
#warning need to loop over userspace_pids in kill_off_processes_skas
|
||||
os_kill_ptraced_process(userspace_pid[0], 1);
|
||||
else {
|
||||
struct task_struct *p;
|
||||
int pid, me;
|
||||
|
||||
me = os_getpid();
|
||||
for_each_process(p){
|
||||
if(p->mm == NULL)
|
||||
continue;
|
||||
|
||||
pid = p->mm->context.skas.id.u.pid;
|
||||
os_kill_ptraced_process(pid, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long current_stub_stack(void)
|
||||
{
|
||||
if(current->mm == NULL)
|
||||
return(0);
|
||||
|
||||
return(current->mm->context.skas.id.stack);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "linux/stddef.h"
|
||||
#include "linux/sched.h"
|
||||
#include "linux/config.h"
|
||||
#include "linux/mm.h"
|
||||
#include "asm/page.h"
|
||||
#include "asm/pgtable.h"
|
||||
|
@ -17,7 +18,7 @@
|
|||
#include "os.h"
|
||||
#include "tlb.h"
|
||||
|
||||
static void do_ops(int fd, struct host_vm_op *ops, int last)
|
||||
static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last)
|
||||
{
|
||||
struct host_vm_op *op;
|
||||
int i;
|
||||
|
@ -26,18 +27,18 @@ static void do_ops(int fd, struct host_vm_op *ops, int last)
|
|||
op = &ops[i];
|
||||
switch(op->type){
|
||||
case MMAP:
|
||||
map(fd, op->u.mmap.addr, op->u.mmap.len,
|
||||
map(&mmu->skas.id, op->u.mmap.addr, op->u.mmap.len,
|
||||
op->u.mmap.r, op->u.mmap.w, op->u.mmap.x,
|
||||
op->u.mmap.fd, op->u.mmap.offset);
|
||||
break;
|
||||
case MUNMAP:
|
||||
unmap(fd, (void *) op->u.munmap.addr,
|
||||
unmap(&mmu->skas.id, (void *) op->u.munmap.addr,
|
||||
op->u.munmap.len);
|
||||
break;
|
||||
case MPROTECT:
|
||||
protect(fd, op->u.mprotect.addr, op->u.mprotect.len,
|
||||
op->u.mprotect.r, op->u.mprotect.w,
|
||||
op->u.mprotect.x);
|
||||
protect(&mmu->skas.id, op->u.mprotect.addr,
|
||||
op->u.mprotect.len, op->u.mprotect.r,
|
||||
op->u.mprotect.w, op->u.mprotect.x);
|
||||
break;
|
||||
default:
|
||||
printk("Unknown op type %d in do_ops\n", op->type);
|
||||
|
@ -46,12 +47,15 @@ static void do_ops(int fd, struct host_vm_op *ops, int last)
|
|||
}
|
||||
}
|
||||
|
||||
extern int proc_mm;
|
||||
|
||||
static void fix_range(struct mm_struct *mm, unsigned long start_addr,
|
||||
unsigned long end_addr, int force)
|
||||
{
|
||||
int fd = mm->context.skas.mm_fd;
|
||||
if(!proc_mm && (end_addr > CONFIG_STUB_START))
|
||||
end_addr = CONFIG_STUB_START;
|
||||
|
||||
fix_range_common(mm, start_addr, end_addr, force, fd, do_ops);
|
||||
fix_range_common(mm, start_addr, end_addr, force, do_ops);
|
||||
}
|
||||
|
||||
void __flush_tlb_one_skas(unsigned long addr)
|
||||
|
@ -69,17 +73,20 @@ void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start,
|
|||
|
||||
void flush_tlb_mm_skas(struct mm_struct *mm)
|
||||
{
|
||||
unsigned long end;
|
||||
|
||||
/* Don't bother flushing if this address space is about to be
|
||||
* destroyed.
|
||||
*/
|
||||
if(atomic_read(&mm->mm_users) == 0)
|
||||
return;
|
||||
|
||||
fix_range(mm, 0, host_task_size, 0);
|
||||
flush_tlb_kernel_range_common(start_vm, end_vm);
|
||||
end = proc_mm ? task_size : CONFIG_STUB_START;
|
||||
fix_range(mm, 0, end, 0);
|
||||
}
|
||||
|
||||
void force_flush_all_skas(void)
|
||||
{
|
||||
fix_range(current->mm, 0, host_task_size, 1);
|
||||
unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
|
||||
fix_range(current->mm, 0, end, 1);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,13 @@ void enable_timer(void)
|
|||
set_interval(ITIMER_VIRTUAL);
|
||||
}
|
||||
|
||||
void prepare_timer(void * ptr)
|
||||
{
|
||||
int usec = 1000000/hz();
|
||||
*(struct itimerval *)ptr = ((struct itimerval) { { 0, usec },
|
||||
{ 0, usec }});
|
||||
}
|
||||
|
||||
void disable_timer(void)
|
||||
{
|
||||
struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
|
||||
|
|
|
@ -18,13 +18,15 @@
|
|||
#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
|
||||
|
||||
void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
|
||||
unsigned long end_addr, int force, int data,
|
||||
void (*do_ops)(int, struct host_vm_op *, int))
|
||||
unsigned long end_addr, int force,
|
||||
void (*do_ops)(union mm_context *, struct host_vm_op *,
|
||||
int))
|
||||
{
|
||||
pgd_t *npgd;
|
||||
pud_t *npud;
|
||||
pmd_t *npmd;
|
||||
pte_t *npte;
|
||||
union mm_context *mmu = &mm->context;
|
||||
unsigned long addr, end;
|
||||
int r, w, x;
|
||||
struct host_vm_op ops[16];
|
||||
|
@ -40,7 +42,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
|
|||
end = end_addr;
|
||||
if(force || pgd_newpage(*npgd)){
|
||||
op_index = add_munmap(addr, end - addr, ops,
|
||||
op_index, last_op, data,
|
||||
op_index, last_op, mmu,
|
||||
do_ops);
|
||||
pgd_mkuptodate(*npgd);
|
||||
}
|
||||
|
@ -55,7 +57,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
|
|||
end = end_addr;
|
||||
if(force || pud_newpage(*npud)){
|
||||
op_index = add_munmap(addr, end - addr, ops,
|
||||
op_index, last_op, data,
|
||||
op_index, last_op, mmu,
|
||||
do_ops);
|
||||
pud_mkuptodate(*npud);
|
||||
}
|
||||
|
@ -70,7 +72,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
|
|||
end = end_addr;
|
||||
if(force || pmd_newpage(*npmd)){
|
||||
op_index = add_munmap(addr, end - addr, ops,
|
||||
op_index, last_op, data,
|
||||
op_index, last_op, mmu,
|
||||
do_ops);
|
||||
pmd_mkuptodate(*npmd);
|
||||
}
|
||||
|
@ -93,21 +95,21 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
|
|||
op_index = add_mmap(addr,
|
||||
pte_val(*npte) & PAGE_MASK,
|
||||
PAGE_SIZE, r, w, x, ops,
|
||||
op_index, last_op, data,
|
||||
op_index, last_op, mmu,
|
||||
do_ops);
|
||||
else op_index = add_munmap(addr, PAGE_SIZE, ops,
|
||||
op_index, last_op, data,
|
||||
op_index, last_op, mmu,
|
||||
do_ops);
|
||||
}
|
||||
else if(pte_newprot(*npte))
|
||||
op_index = add_mprotect(addr, PAGE_SIZE, r, w, x, ops,
|
||||
op_index, last_op, data,
|
||||
op_index, last_op, mmu,
|
||||
do_ops);
|
||||
|
||||
*npte = pte_mkuptodate(*npte);
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
(*do_ops)(data, ops, op_index);
|
||||
(*do_ops)(mmu, ops, op_index);
|
||||
}
|
||||
|
||||
int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
|
||||
|
@ -195,51 +197,6 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
|
|||
return(updated);
|
||||
}
|
||||
|
||||
void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
|
||||
{
|
||||
address &= PAGE_MASK;
|
||||
flush_tlb_range(vma, address, address + PAGE_SIZE);
|
||||
}
|
||||
|
||||
void flush_tlb_all(void)
|
||||
{
|
||||
flush_tlb_mm(current->mm);
|
||||
}
|
||||
|
||||
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
|
||||
flush_tlb_kernel_range_common, start, end);
|
||||
}
|
||||
|
||||
void flush_tlb_kernel_vm(void)
|
||||
{
|
||||
CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
|
||||
flush_tlb_kernel_range_common(start_vm, end_vm));
|
||||
}
|
||||
|
||||
void __flush_tlb_one(unsigned long addr)
|
||||
{
|
||||
CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
|
||||
}
|
||||
|
||||
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
|
||||
end);
|
||||
}
|
||||
|
||||
void flush_tlb_mm(struct mm_struct *mm)
|
||||
{
|
||||
CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
|
||||
}
|
||||
|
||||
void force_flush_all(void)
|
||||
{
|
||||
CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
|
||||
}
|
||||
|
||||
pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
|
||||
{
|
||||
return(pgd_offset(mm, address));
|
||||
|
@ -270,9 +227,9 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
|
|||
}
|
||||
|
||||
int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
|
||||
int r, int w, int x, struct host_vm_op *ops, int index,
|
||||
int last_filled, int data,
|
||||
void (*do_ops)(int, struct host_vm_op *, int))
|
||||
int r, int w, int x, struct host_vm_op *ops, int index,
|
||||
int last_filled, union mm_context *mmu,
|
||||
void (*do_ops)(union mm_context *, struct host_vm_op *, int))
|
||||
{
|
||||
__u64 offset;
|
||||
struct host_vm_op *last;
|
||||
|
@ -292,7 +249,7 @@ int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
|
|||
}
|
||||
|
||||
if(index == last_filled){
|
||||
(*do_ops)(data, ops, last_filled);
|
||||
(*do_ops)(mmu, ops, last_filled);
|
||||
index = -1;
|
||||
}
|
||||
|
||||
|
@ -310,8 +267,8 @@ int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
|
|||
}
|
||||
|
||||
int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
|
||||
int index, int last_filled, int data,
|
||||
void (*do_ops)(int, struct host_vm_op *, int))
|
||||
int index, int last_filled, union mm_context *mmu,
|
||||
void (*do_ops)(union mm_context *, struct host_vm_op *, int))
|
||||
{
|
||||
struct host_vm_op *last;
|
||||
|
||||
|
@ -325,7 +282,7 @@ int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
|
|||
}
|
||||
|
||||
if(index == last_filled){
|
||||
(*do_ops)(data, ops, last_filled);
|
||||
(*do_ops)(mmu, ops, last_filled);
|
||||
index = -1;
|
||||
}
|
||||
|
||||
|
@ -337,8 +294,9 @@ int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
|
|||
}
|
||||
|
||||
int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
|
||||
struct host_vm_op *ops, int index, int last_filled, int data,
|
||||
void (*do_ops)(int, struct host_vm_op *, int))
|
||||
struct host_vm_op *ops, int index, int last_filled,
|
||||
union mm_context *mmu,
|
||||
void (*do_ops)(union mm_context *, struct host_vm_op *, int))
|
||||
{
|
||||
struct host_vm_op *last;
|
||||
|
||||
|
@ -354,7 +312,7 @@ int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
|
|||
}
|
||||
|
||||
if(index == last_filled){
|
||||
(*do_ops)(data, ops, last_filled);
|
||||
(*do_ops)(mmu, ops, last_filled);
|
||||
index = -1;
|
||||
}
|
||||
|
||||
|
@ -367,3 +325,49 @@ int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
|
|||
.x = x } } });
|
||||
return(index);
|
||||
}
|
||||
|
||||
void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
|
||||
{
|
||||
address &= PAGE_MASK;
|
||||
flush_tlb_range(vma, address, address + PAGE_SIZE);
|
||||
}
|
||||
|
||||
void flush_tlb_all(void)
|
||||
{
|
||||
flush_tlb_mm(current->mm);
|
||||
}
|
||||
|
||||
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
|
||||
flush_tlb_kernel_range_common, start, end);
|
||||
}
|
||||
|
||||
void flush_tlb_kernel_vm(void)
|
||||
{
|
||||
CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
|
||||
flush_tlb_kernel_range_common(start_vm, end_vm));
|
||||
}
|
||||
|
||||
void __flush_tlb_one(unsigned long addr)
|
||||
{
|
||||
CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
|
||||
}
|
||||
|
||||
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
|
||||
end);
|
||||
}
|
||||
|
||||
void flush_tlb_mm(struct mm_struct *mm)
|
||||
{
|
||||
CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
|
||||
}
|
||||
|
||||
void force_flush_all(void)
|
||||
{
|
||||
CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "os.h"
|
||||
#include "tlb.h"
|
||||
|
||||
static void do_ops(int unused, struct host_vm_op *ops, int last)
|
||||
static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last)
|
||||
{
|
||||
struct host_vm_op *op;
|
||||
int i;
|
||||
|
@ -55,7 +55,7 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
|
|||
panic("fix_range fixing wrong address space, current = 0x%p",
|
||||
current);
|
||||
|
||||
fix_range_common(mm, start_addr, end_addr, force, 0, do_ops);
|
||||
fix_range_common(mm, start_addr, end_addr, force, do_ops);
|
||||
}
|
||||
|
||||
atomic_t vmchange_seq = ATOMIC_INIT(1);
|
||||
|
|
|
@ -30,6 +30,7 @@ SECTIONS
|
|||
_einittext = .;
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
|
@ -39,6 +40,12 @@ SECTIONS
|
|||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.gnu.linkonce.t*)
|
||||
|
||||
. = ALIGN(4096);
|
||||
__syscall_stub_start = .;
|
||||
*(.__syscall_stub*)
|
||||
__syscall_stub_end = .;
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
|
||||
#include "asm/common.lds.S"
|
||||
|
|
|
@ -121,6 +121,11 @@ void init_registers(int pid)
|
|||
err);
|
||||
}
|
||||
|
||||
void get_safe_registers(unsigned long *regs)
|
||||
{
|
||||
memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long));
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
|
|
|
@ -69,6 +69,11 @@ void init_registers(int pid)
|
|||
err);
|
||||
}
|
||||
|
||||
void get_safe_registers(unsigned long *regs)
|
||||
{
|
||||
memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long));
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
|
|
|
@ -16,6 +16,11 @@ define unprofile
|
|||
endef
|
||||
|
||||
|
||||
# The stubs and unmap.o can't try to call mcount or update basic block data
|
||||
define unprofile
|
||||
$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
|
||||
endef
|
||||
|
||||
quiet_cmd_make_link = SYMLINK $@
|
||||
cmd_make_link = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
obj-y = bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
|
||||
ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o \
|
||||
sys_call_table.o
|
||||
ptrace_user.o semaphore.o signal.o sigcontext.o stub.o stub_segv.o \
|
||||
syscalls.o sysrq.o sys_call_table.o
|
||||
|
||||
obj-$(CONFIG_HIGHMEM) += highmem.o
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
|
@ -16,6 +16,14 @@ semaphore.c-dir = kernel
|
|||
highmem.c-dir = mm
|
||||
module.c-dir = kernel
|
||||
|
||||
STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
|
||||
|
||||
# _cflags works with kernel files, not with userspace ones, but c_flags does,
|
||||
# why ask why?
|
||||
$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS)
|
||||
|
||||
$(obj)/stub.o : a_flags = $(STUB_CFLAGS)
|
||||
|
||||
subdir- := util
|
||||
|
||||
include arch/um/scripts/Makefile.unmap
|
||||
|
|
8
arch/um/sys-i386/stub.S
Normal file
8
arch/um/sys-i386/stub.S
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include "uml-config.h"
|
||||
|
||||
.globl syscall_stub
|
||||
.section .__syscall_stub, "x"
|
||||
syscall_stub:
|
||||
int $0x80
|
||||
mov %eax, UML_CONFIG_STUB_DATA
|
||||
int3
|
30
arch/um/sys-i386/stub_segv.c
Normal file
30
arch/um/sys-i386/stub_segv.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <asm/sigcontext.h>
|
||||
#include <asm/unistd.h>
|
||||
#include "uml-config.h"
|
||||
#include "sysdep/sigcontext.h"
|
||||
#include "sysdep/faultinfo.h"
|
||||
|
||||
void __attribute__ ((__section__ (".__syscall_stub")))
|
||||
stub_segv_handler(int sig)
|
||||
{
|
||||
struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
|
||||
|
||||
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
|
||||
sc);
|
||||
|
||||
__asm__("movl %0, %%eax ; int $0x80": : "g" (__NR_getpid));
|
||||
__asm__("movl %%eax, %%ebx ; movl %0, %%eax ; movl %1, %%ecx ;"
|
||||
"int $0x80": : "g" (__NR_kill), "g" (SIGUSR1));
|
||||
/* Pop the frame pointer and return address since we need to leave
|
||||
* the stack in its original form when we do the sigreturn here, by
|
||||
* hand.
|
||||
*/
|
||||
__asm__("popl %%eax ; popl %%eax ; popl %%eax ; movl %0, %%eax ; "
|
||||
"int $0x80" : : "g" (__NR_sigreturn));
|
||||
}
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#XXX: why into lib-y?
|
||||
lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \
|
||||
ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \
|
||||
syscalls.o sysrq.o thunk.o syscall_table.o
|
||||
ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o stub.o \
|
||||
stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o
|
||||
|
||||
obj-y := ksyms.o
|
||||
obj-$(CONFIG_MODULES) += module.o um_module.o
|
||||
|
@ -28,6 +28,14 @@ semaphore.c-dir = kernel
|
|||
thunk.S-dir = lib
|
||||
module.c-dir = kernel
|
||||
|
||||
STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
|
||||
|
||||
# _cflags works with kernel files, not with userspace ones, but c_flags does,
|
||||
# why ask why?
|
||||
$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS)
|
||||
|
||||
$(obj)/stub.o : a_flags = $(STUB_CFLAGS)
|
||||
|
||||
subdir- := util
|
||||
|
||||
include arch/um/scripts/Makefile.unmap
|
||||
|
|
15
arch/um/sys-x86_64/stub.S
Normal file
15
arch/um/sys-x86_64/stub.S
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include "uml-config.h"
|
||||
|
||||
.globl syscall_stub
|
||||
.section .__syscall_stub, "x"
|
||||
syscall_stub:
|
||||
syscall
|
||||
/* We don't have 64-bit constants, so this constructs the address
|
||||
* we need.
|
||||
*/
|
||||
movq $(UML_CONFIG_STUB_DATA >> 32), %rbx
|
||||
salq $32, %rbx
|
||||
movq $(UML_CONFIG_STUB_DATA & 0xffffffff), %rcx
|
||||
or %rcx, %rbx
|
||||
movq %rax, (%rbx)
|
||||
int3
|
31
arch/um/sys-x86_64/stub_segv.c
Normal file
31
arch/um/sys-x86_64/stub_segv.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/unistd.h>
|
||||
#include "uml-config.h"
|
||||
#include "sysdep/sigcontext.h"
|
||||
#include "sysdep/faultinfo.h"
|
||||
|
||||
void __attribute__ ((__section__ (".__syscall_stub")))
|
||||
stub_segv_handler(int sig)
|
||||
{
|
||||
struct ucontext *uc;
|
||||
|
||||
__asm__("movq %%rdx, %0" : "=g" (uc) :);
|
||||
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
|
||||
&uc->uc_mcontext);
|
||||
|
||||
__asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid));
|
||||
__asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;"
|
||||
"syscall": : "g" (__NR_kill), "g" (SIGUSR1));
|
||||
/* Two popqs to restore the stack to the state just before entering
|
||||
* the handler, one pops the return address, the other pops the frame
|
||||
* pointer.
|
||||
*/
|
||||
__asm__("popq %%rax ; popq %%rax ; movq %0, %%rax ; syscall" : : "g"
|
||||
(__NR_rt_sigreturn));
|
||||
}
|
|
@ -1076,6 +1076,10 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
|
|||
#ifdef CONFIG_X86_MCE
|
||||
mcheck_init(c);
|
||||
#endif
|
||||
if (c == &boot_cpu_data)
|
||||
mtrr_bp_init();
|
||||
else
|
||||
mtrr_ap_init();
|
||||
#ifdef CONFIG_NUMA
|
||||
if (c != &boot_cpu_data)
|
||||
numa_add_cpu(c - cpu_data);
|
||||
|
|
|
@ -119,6 +119,7 @@ void __restore_processor_state(struct saved_context *ctxt)
|
|||
fix_processor_context();
|
||||
|
||||
do_fpu_end();
|
||||
mtrr_ap_init();
|
||||
}
|
||||
|
||||
void restore_processor_state(void)
|
||||
|
|
|
@ -56,6 +56,10 @@ SECTIONS
|
|||
.data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
|
||||
*(.data.cacheline_aligned)
|
||||
}
|
||||
. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
|
||||
.data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
|
||||
*(.data.read_mostly)
|
||||
}
|
||||
|
||||
#define VSYSCALL_ADDR (-10*1024*1024)
|
||||
#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095))
|
||||
|
|
|
@ -46,8 +46,6 @@
|
|||
|
||||
extern void do_syscall_trace(void);
|
||||
typedef int (*syscall_t)(void *a0,...);
|
||||
extern int (*do_syscalls)(struct pt_regs *regs, syscall_t fun,
|
||||
int narg);
|
||||
extern syscall_t sys_call_table[];
|
||||
extern unsigned char sys_narg_table[];
|
||||
|
||||
|
@ -72,10 +70,8 @@ int sys_pipe(int __user *userfds)
|
|||
/*
|
||||
* Common code for old and new mmaps.
|
||||
*/
|
||||
|
||||
static inline long do_mmap2(unsigned long addr, unsigned long len,
|
||||
unsigned long prot, unsigned long flags,
|
||||
unsigned long fd, unsigned long pgoff)
|
||||
long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
|
||||
unsigned long flags, unsigned long fd, unsigned long pgoff)
|
||||
{
|
||||
int error = -EBADF;
|
||||
struct file * file = NULL;
|
||||
|
@ -97,29 +93,6 @@ static inline long do_mmap2(unsigned long addr, unsigned long len,
|
|||
return error;
|
||||
}
|
||||
|
||||
unsigned long old_mmap(unsigned long addr, size_t len, int prot,
|
||||
int flags, int fd, off_t offset)
|
||||
{
|
||||
return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
|
||||
unsigned long flags, unsigned long fd, unsigned long pgoff)
|
||||
{
|
||||
return do_mmap2(addr, len, prot, flags, fd, pgoff);
|
||||
}
|
||||
|
||||
int sys_fork(struct pt_regs *regs)
|
||||
{
|
||||
return do_fork(SIGCHLD, regs->areg[1], regs, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
int sys_vfork(struct pt_regs *regs)
|
||||
{
|
||||
return do_fork(CLONE_VFORK|CLONE_VM|SIGCHLD, regs->areg[1],
|
||||
regs, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
int sys_clone(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long clone_flags;
|
||||
|
@ -162,30 +135,6 @@ int sys_uname(struct old_utsname * name)
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
int sys_olduname(struct oldold_utsname * name)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!name)
|
||||
return -EFAULT;
|
||||
if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
|
||||
return -EFAULT;
|
||||
|
||||
error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
|
||||
error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
|
||||
error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
|
||||
error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
|
||||
error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
|
||||
error -= __put_user(0,name->release+__OLD_UTS_LEN);
|
||||
error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
|
||||
error -= __put_user(0,name->version+__OLD_UTS_LEN);
|
||||
error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
|
||||
error -= __put_user(0,name->machine+__OLD_UTS_LEN);
|
||||
|
||||
return error ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Build the string table for the builtin "poor man's strace".
|
||||
*/
|
||||
|
@ -319,100 +268,3 @@ void system_call (struct pt_regs *regs)
|
|||
regs->areg[2] = res;
|
||||
do_syscall_trace();
|
||||
}
|
||||
|
||||
/*
|
||||
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
|
||||
*
|
||||
* This is really horribly ugly.
|
||||
*/
|
||||
|
||||
int sys_ipc (uint call, int first, int second,
|
||||
int third, void __user *ptr, long fifth)
|
||||
{
|
||||
int version, ret;
|
||||
|
||||
version = call >> 16; /* hack for backward compatibility */
|
||||
call &= 0xffff;
|
||||
ret = -ENOSYS;
|
||||
|
||||
switch (call) {
|
||||
case SEMOP:
|
||||
ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
|
||||
second, NULL);
|
||||
break;
|
||||
|
||||
case SEMTIMEDOP:
|
||||
ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
|
||||
second, (const struct timespec *) fifth);
|
||||
break;
|
||||
|
||||
case SEMGET:
|
||||
ret = sys_semget (first, second, third);
|
||||
break;
|
||||
|
||||
case SEMCTL: {
|
||||
union semun fourth;
|
||||
|
||||
if (ptr && !get_user(fourth.__pad, (void *__user *) ptr))
|
||||
ret = sys_semctl (first, second, third, fourth);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSGSND:
|
||||
ret = sys_msgsnd (first, (struct msgbuf __user*) ptr,
|
||||
second, third);
|
||||
break;
|
||||
|
||||
case MSGRCV:
|
||||
switch (version) {
|
||||
case 0: {
|
||||
struct ipc_kludge tmp;
|
||||
|
||||
if (ptr && !copy_from_user(&tmp,
|
||||
(struct ipc_kludge *) ptr,
|
||||
sizeof (tmp)))
|
||||
ret = sys_msgrcv (first, tmp.msgp, second,
|
||||
tmp.msgtyp, third);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ret = sys_msgrcv (first, (struct msgbuf __user *) ptr,
|
||||
second, 0, third);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGGET:
|
||||
ret = sys_msgget ((key_t) first, second);
|
||||
break;
|
||||
|
||||
case MSGCTL:
|
||||
ret = sys_msgctl (first, second, (struct msqid_ds __user*) ptr);
|
||||
break;
|
||||
|
||||
case SHMAT: {
|
||||
ulong raddr;
|
||||
ret = do_shmat (first, (char __user *) ptr, second, &raddr);
|
||||
|
||||
if (!ret)
|
||||
ret = put_user (raddr, (ulong __user *) third);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SHMDT:
|
||||
ret = sys_shmdt ((char __user *)ptr);
|
||||
break;
|
||||
|
||||
case SHMGET:
|
||||
ret = sys_shmget (first, second, third);
|
||||
break;
|
||||
|
||||
case SHMCTL:
|
||||
ret = sys_shmctl (first, second, (struct shmid_ds __user*) ptr);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,20 +25,19 @@
|
|||
*/
|
||||
|
||||
SYSCALL(0, 0) /* 00 */
|
||||
|
||||
SYSCALL(sys_exit, 1)
|
||||
SYSCALL(sys_fork, 0)
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_read, 3)
|
||||
SYSCALL(sys_write, 3)
|
||||
SYSCALL(sys_open, 3) /* 05 */
|
||||
SYSCALL(sys_close, 1)
|
||||
SYSCALL(sys_waitpid, 3)
|
||||
SYSCALL(sys_ni_syscall, 3)
|
||||
SYSCALL(sys_creat, 2)
|
||||
SYSCALL(sys_link, 2)
|
||||
SYSCALL(sys_unlink, 1) /* 10 */
|
||||
SYSCALL(sys_execve, 0)
|
||||
SYSCALL(sys_chdir, 1)
|
||||
SYSCALL(sys_time, 1)
|
||||
SYSCALL(sys_ni_syscall, 1)
|
||||
SYSCALL(sys_mknod, 3)
|
||||
SYSCALL(sys_chmod, 2) /* 15 */
|
||||
SYSCALL(sys_lchown, 3)
|
||||
|
@ -47,19 +46,19 @@ SYSCALL(sys_stat, 2)
|
|||
SYSCALL(sys_lseek, 3)
|
||||
SYSCALL(sys_getpid, 0) /* 20 */
|
||||
SYSCALL(sys_mount, 5)
|
||||
SYSCALL(sys_oldumount, 1)
|
||||
SYSCALL(sys_ni_syscall, 1)
|
||||
SYSCALL(sys_setuid, 1)
|
||||
SYSCALL(sys_getuid, 0)
|
||||
SYSCALL(sys_stime, 1) /* 25 */
|
||||
SYSCALL(sys_ni_syscall, 1) /* 25 */
|
||||
SYSCALL(sys_ptrace, 4)
|
||||
SYSCALL(sys_alarm, 1)
|
||||
SYSCALL(sys_ni_syscall, 1)
|
||||
SYSCALL(sys_fstat, 2)
|
||||
SYSCALL(sys_pause, 0)
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_utime, 2) /* 30 */
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_access, 2)
|
||||
SYSCALL(sys_nice, 1)
|
||||
SYSCALL(sys_ni_syscall, 1)
|
||||
SYSCALL(sys_ni_syscall, 0) /* 35 */
|
||||
SYSCALL(sys_sync, 0)
|
||||
SYSCALL(sys_kill, 2)
|
||||
|
@ -73,7 +72,7 @@ SYSCALL(sys_ni_syscall, 0)
|
|||
SYSCALL(sys_brk, 1) /* 45 */
|
||||
SYSCALL(sys_setgid, 1)
|
||||
SYSCALL(sys_getgid, 0)
|
||||
SYSCALL(sys_ni_syscall, 0) /* was signal(2) */
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_geteuid, 0)
|
||||
SYSCALL(sys_getegid, 0) /* 50 */
|
||||
SYSCALL(sys_acct, 1)
|
||||
|
@ -84,21 +83,21 @@ SYSCALL(sys_fcntl, 3) /* 55 */
|
|||
SYSCALL(sys_ni_syscall, 2)
|
||||
SYSCALL(sys_setpgid, 2)
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_olduname, 1)
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_umask, 1) /* 60 */
|
||||
SYSCALL(sys_chroot, 1)
|
||||
SYSCALL(sys_ustat, 2)
|
||||
SYSCALL(sys_dup2, 2)
|
||||
SYSCALL(sys_getppid, 0)
|
||||
SYSCALL(sys_getpgrp, 0) /* 65 */
|
||||
SYSCALL(sys_ni_syscall, 0) /* 65 */
|
||||
SYSCALL(sys_setsid, 0)
|
||||
SYSCALL(sys_sigaction, 3)
|
||||
SYSCALL(sys_sgetmask, 0)
|
||||
SYSCALL(sys_ssetmask, 1)
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_ni_syscall, 1)
|
||||
SYSCALL(sys_setreuid, 2) /* 70 */
|
||||
SYSCALL(sys_setregid, 2)
|
||||
SYSCALL(sys_sigsuspend, 0)
|
||||
SYSCALL(sys_sigpending, 1)
|
||||
SYSCALL(sys_ni_syscall, 1)
|
||||
SYSCALL(sys_sethostname, 2)
|
||||
SYSCALL(sys_setrlimit, 2) /* 75 */
|
||||
SYSCALL(sys_getrlimit, 2)
|
||||
|
@ -107,15 +106,15 @@ SYSCALL(sys_gettimeofday, 2)
|
|||
SYSCALL(sys_settimeofday, 2)
|
||||
SYSCALL(sys_getgroups, 2) /* 80 */
|
||||
SYSCALL(sys_setgroups, 2)
|
||||
SYSCALL(sys_ni_syscall, 0) /* old_select */
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_symlink, 2)
|
||||
SYSCALL(sys_lstat, 2)
|
||||
SYSCALL(sys_readlink, 3) /* 85 */
|
||||
SYSCALL(sys_uselib, 1)
|
||||
SYSCALL(sys_swapon, 2)
|
||||
SYSCALL(sys_reboot, 3)
|
||||
SYSCALL(old_readdir, 3)
|
||||
SYSCALL(old_mmap, 6) /* 90 */
|
||||
SYSCALL(sys_ni_syscall, 3)
|
||||
SYSCALL(sys_ni_syscall, 6) /* 90 */
|
||||
SYSCALL(sys_munmap, 2)
|
||||
SYSCALL(sys_truncate, 2)
|
||||
SYSCALL(sys_ftruncate, 2)
|
||||
|
@ -127,7 +126,7 @@ SYSCALL(sys_ni_syscall, 0)
|
|||
SYSCALL(sys_statfs, 2)
|
||||
SYSCALL(sys_fstatfs, 2) /* 100 */
|
||||
SYSCALL(sys_ni_syscall, 3)
|
||||
SYSCALL(sys_socketcall, 2)
|
||||
SYSCALL(sys_ni_syscall, 2)
|
||||
SYSCALL(sys_syslog, 3)
|
||||
SYSCALL(sys_setitimer, 3)
|
||||
SYSCALL(sys_getitimer, 2) /* 105 */
|
||||
|
@ -137,32 +136,32 @@ SYSCALL(sys_newfstat, 2)
|
|||
SYSCALL(sys_uname, 1)
|
||||
SYSCALL(sys_ni_syscall, 0) /* 110 */
|
||||
SYSCALL(sys_vhangup, 0)
|
||||
SYSCALL(sys_ni_syscall, 0) /* was sys_idle() */
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_wait4, 4)
|
||||
SYSCALL(sys_swapoff, 1) /* 115 */
|
||||
SYSCALL(sys_sysinfo, 1)
|
||||
SYSCALL(sys_ipc, 5) /* 6 really, but glibc uses only 5) */
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_fsync, 1)
|
||||
SYSCALL(sys_sigreturn, 0)
|
||||
SYSCALL(sys_clone, 0) /* 120 */
|
||||
SYSCALL(sys_setdomainname, 2)
|
||||
SYSCALL(sys_newuname, 1)
|
||||
SYSCALL(sys_ni_syscall, 0) /* sys_modify_ldt */
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_adjtimex, 1)
|
||||
SYSCALL(sys_mprotect, 3) /* 125 */
|
||||
SYSCALL(sys_sigprocmask, 3)
|
||||
SYSCALL(sys_ni_syscall, 2) /* old sys_create_module */
|
||||
SYSCALL(sys_ni_syscall, 3)
|
||||
SYSCALL(sys_ni_syscall, 2)
|
||||
SYSCALL(sys_init_module, 2)
|
||||
SYSCALL(sys_delete_module, 1)
|
||||
SYSCALL(sys_ni_syscall, 1) /* old sys_get_kernel_sysm */ /* 130 */
|
||||
SYSCALL(sys_ni_syscall, 1) /* 130 */
|
||||
SYSCALL(sys_quotactl, 0)
|
||||
SYSCALL(sys_getpgid, 1)
|
||||
SYSCALL(sys_fchdir, 1)
|
||||
SYSCALL(sys_bdflush, 2)
|
||||
SYSCALL(sys_sysfs, 3) /* 135 */
|
||||
SYSCALL(sys_personality, 1)
|
||||
SYSCALL(sys_ni_syscall, 0) /* for afs_syscall */
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_setfsuid, 1)
|
||||
SYSCALL(sys_setfsgid, 1)
|
||||
SYSCALL(sys_llseek, 5) /* 140 */
|
||||
|
@ -212,7 +211,7 @@ SYSCALL(sys_socket, 3)
|
|||
SYSCALL(sys_socketpair, 4)
|
||||
SYSCALL(sys_setresuid, 3) /* 185 */
|
||||
SYSCALL(sys_getresuid, 3)
|
||||
SYSCALL(sys_ni_syscall, 5) /* old sys_query_module */
|
||||
SYSCALL(sys_ni_syscall, 5)
|
||||
SYSCALL(sys_poll, 3)
|
||||
SYSCALL(sys_nfsservctl, 3)
|
||||
SYSCALL(sys_setresgid, 3) /* 190 */
|
||||
|
@ -235,7 +234,7 @@ SYSCALL(sys_sigaltstack, 0)
|
|||
SYSCALL(sys_sendfile, 4)
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_ni_syscall, 0)
|
||||
SYSCALL(sys_mmap2, 6) /* 210 */
|
||||
SYSCALL(sys_mmap, 6) /* 210 */
|
||||
SYSCALL(sys_truncate64, 2)
|
||||
SYSCALL(sys_ftruncate64, 2)
|
||||
SYSCALL(sys_stat64, 2)
|
||||
|
@ -245,4 +244,4 @@ SYSCALL(sys_pivot_root, 2)
|
|||
SYSCALL(sys_mincore, 3)
|
||||
SYSCALL(sys_madvise, 3)
|
||||
SYSCALL(sys_getdents64, 3)
|
||||
SYSCALL(sys_vfork, 0) /* 220 */
|
||||
SYSCALL(sys_ni_syscall, 0) /* 220 */
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
|
@ -895,11 +894,6 @@ static dev_link_t *bluecard_attach(void)
|
|||
link->next = dev_list;
|
||||
dev_list = link;
|
||||
client_reg.dev_info = &dev_info;
|
||||
client_reg.EventMask =
|
||||
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
|
||||
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
|
||||
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||
client_reg.event_handler = &bluecard_event;
|
||||
client_reg.Version = 0x0210;
|
||||
client_reg.event_callback_args.client_data = link;
|
||||
|
||||
|
@ -1103,6 +1097,7 @@ static struct pcmcia_driver bluecard_driver = {
|
|||
.name = "bluecard_cs",
|
||||
},
|
||||
.attach = bluecard_attach,
|
||||
.event = bluecard_event,
|
||||
.detach = bluecard_detach,
|
||||
.id_table = bluecard_ids,
|
||||
};
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
|
@ -696,11 +695,6 @@ static dev_link_t *bt3c_attach(void)
|
|||
link->next = dev_list;
|
||||
dev_list = link;
|
||||
client_reg.dev_info = &dev_info;
|
||||
client_reg.EventMask =
|
||||
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
|
||||
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
|
||||
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||
client_reg.event_handler = &bt3c_event;
|
||||
client_reg.Version = 0x0210;
|
||||
client_reg.event_callback_args.client_data = link;
|
||||
|
||||
|
@ -947,6 +941,7 @@ static struct pcmcia_driver bt3c_driver = {
|
|||
.name = "bt3c_cs",
|
||||
},
|
||||
.attach = bt3c_attach,
|
||||
.event = bt3c_event,
|
||||
.detach = bt3c_detach,
|
||||
.id_table = bt3c_ids,
|
||||
};
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
|
@ -615,11 +614,6 @@ static dev_link_t *btuart_attach(void)
|
|||
link->next = dev_list;
|
||||
dev_list = link;
|
||||
client_reg.dev_info = &dev_info;
|
||||
client_reg.EventMask =
|
||||
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
|
||||
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
|
||||
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||
client_reg.event_handler = &btuart_event;
|
||||
client_reg.Version = 0x0210;
|
||||
client_reg.event_callback_args.client_data = link;
|
||||
|
||||
|
@ -867,6 +861,7 @@ static struct pcmcia_driver btuart_driver = {
|
|||
.name = "btuart_cs",
|
||||
},
|
||||
.attach = btuart_attach,
|
||||
.event = btuart_event,
|
||||
.detach = btuart_detach,
|
||||
.id_table = btuart_ids,
|
||||
};
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
|
@ -594,11 +593,6 @@ static dev_link_t *dtl1_attach(void)
|
|||
link->next = dev_list;
|
||||
dev_list = link;
|
||||
client_reg.dev_info = &dev_info;
|
||||
client_reg.EventMask =
|
||||
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
|
||||
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
|
||||
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||
client_reg.event_handler = &dtl1_event;
|
||||
client_reg.Version = 0x0210;
|
||||
client_reg.event_callback_args.client_data = link;
|
||||
|
||||
|
@ -820,6 +814,7 @@ static struct pcmcia_driver dtl1_driver = {
|
|||
.name = "dtl1_cs",
|
||||
},
|
||||
.attach = dtl1_attach,
|
||||
.event = dtl1_event,
|
||||
.detach = dtl1_detach,
|
||||
.id_table = dtl1_ids,
|
||||
};
|
||||
|
|
|
@ -40,7 +40,7 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o
|
|||
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
|
||||
obj-$(CONFIG_SX) += sx.o generic_serial.o
|
||||
obj-$(CONFIG_RIO) += rio/ generic_serial.o
|
||||
obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvsi.o
|
||||
obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o
|
||||
obj-$(CONFIG_RAW_DRIVER) += raw.o
|
||||
obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
|
||||
obj-$(CONFIG_MMTIMER) += mmtimer.o
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -40,7 +41,6 @@
|
|||
#include <linux/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/hvconsole.h>
|
||||
#include <asm/vio.h>
|
||||
|
||||
#define HVC_MAJOR 229
|
||||
#define HVC_MINOR 0
|
||||
|
@ -61,16 +61,21 @@
|
|||
*/
|
||||
#define HVC_ALLOC_TTY_ADAPTERS 8
|
||||
|
||||
static struct tty_driver *hvc_driver;
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
static int sysrq_pressed;
|
||||
#endif
|
||||
|
||||
#define N_OUTBUF 16
|
||||
#define N_INBUF 16
|
||||
|
||||
#define __ALIGNED__ __attribute__((__aligned__(8)))
|
||||
|
||||
static struct tty_driver *hvc_driver;
|
||||
static struct task_struct *hvc_task;
|
||||
|
||||
/* Picks up late kicks after list walk but before schedule() */
|
||||
static int hvc_kicked;
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
static int sysrq_pressed;
|
||||
#endif
|
||||
|
||||
struct hvc_struct {
|
||||
spinlock_t lock;
|
||||
int index;
|
||||
|
@ -80,11 +85,11 @@ struct hvc_struct {
|
|||
char outbuf[N_OUTBUF] __ALIGNED__;
|
||||
int n_outbuf;
|
||||
uint32_t vtermno;
|
||||
struct hv_ops *ops;
|
||||
int irq_requested;
|
||||
int irq;
|
||||
struct list_head next;
|
||||
struct kobject kobj; /* ref count & hvc_struct lifetime */
|
||||
struct vio_dev *vdev;
|
||||
};
|
||||
|
||||
/* dynamic list of hvc_struct instances */
|
||||
|
@ -97,48 +102,11 @@ static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs);
|
|||
static DEFINE_SPINLOCK(hvc_structs_lock);
|
||||
|
||||
/*
|
||||
* Initial console vtermnos for console API usage prior to full console
|
||||
* initialization. Any vty adapter outside this range will not have usable
|
||||
* console interfaces but can still be used as a tty device. This has to be
|
||||
* static because kmalloc will not work during early console init.
|
||||
* This value is used to assign a tty->index value to a hvc_struct based
|
||||
* upon order of exposure via hvc_probe(), when we can not match it to
|
||||
* a console canidate registered with hvc_instantiate().
|
||||
*/
|
||||
static uint32_t vtermnos[MAX_NR_HVC_CONSOLES];
|
||||
|
||||
/* Used for accounting purposes */
|
||||
static int num_vterms = 0;
|
||||
|
||||
static struct task_struct *hvc_task;
|
||||
|
||||
/*
|
||||
* This value is used to associate a tty->index value to a hvc_struct based
|
||||
* upon order of exposure via hvc_probe().
|
||||
*/
|
||||
static int hvc_count = -1;
|
||||
|
||||
/* Picks up late kicks after list walk but before schedule() */
|
||||
static int hvc_kicked;
|
||||
|
||||
/* Wake the sleeping khvcd */
|
||||
static void hvc_kick(void)
|
||||
{
|
||||
hvc_kicked = 1;
|
||||
wake_up_process(hvc_task);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: This API isn't used if the console adapter doesn't support interrupts.
|
||||
* In this case the console is poll driven.
|
||||
*/
|
||||
static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
|
||||
{
|
||||
hvc_kick();
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void hvc_unthrottle(struct tty_struct *tty)
|
||||
{
|
||||
hvc_kick();
|
||||
}
|
||||
static int last_hvc = -1;
|
||||
|
||||
/*
|
||||
* Do not call this function with either the hvc_strucst_lock or the hvc_struct
|
||||
|
@ -168,6 +136,178 @@ struct hvc_struct *hvc_get_by_index(int index)
|
|||
return hp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initial console vtermnos for console API usage prior to full console
|
||||
* initialization. Any vty adapter outside this range will not have usable
|
||||
* console interfaces but can still be used as a tty device. This has to be
|
||||
* static because kmalloc will not work during early console init.
|
||||
*/
|
||||
static struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES];
|
||||
static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
|
||||
{[0 ... MAX_NR_HVC_CONSOLES - 1] = -1};
|
||||
|
||||
/*
|
||||
* Console APIs, NOT TTY. These APIs are available immediately when
|
||||
* hvc_console_setup() finds adapters.
|
||||
*/
|
||||
|
||||
void hvc_console_print(struct console *co, const char *b, unsigned count)
|
||||
{
|
||||
char c[16] __ALIGNED__;
|
||||
unsigned i = 0, n = 0;
|
||||
int r, donecr = 0, index = co->index;
|
||||
|
||||
/* Console access attempt outside of acceptable console range. */
|
||||
if (index >= MAX_NR_HVC_CONSOLES)
|
||||
return;
|
||||
|
||||
/* This console adapter was removed so it is not useable. */
|
||||
if (vtermnos[index] < 0)
|
||||
return;
|
||||
|
||||
while (count > 0 || i > 0) {
|
||||
if (count > 0 && i < sizeof(c)) {
|
||||
if (b[n] == '\n' && !donecr) {
|
||||
c[i++] = '\r';
|
||||
donecr = 1;
|
||||
} else {
|
||||
c[i++] = b[n++];
|
||||
donecr = 0;
|
||||
--count;
|
||||
}
|
||||
} else {
|
||||
r = cons_ops[index]->put_chars(vtermnos[index], c, i);
|
||||
if (r < 0) {
|
||||
/* throw away chars on error */
|
||||
i = 0;
|
||||
} else if (r > 0) {
|
||||
i -= r;
|
||||
if (i > 0)
|
||||
memmove(c, c+r, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct tty_driver *hvc_console_device(struct console *c, int *index)
|
||||
{
|
||||
if (vtermnos[c->index] == -1)
|
||||
return NULL;
|
||||
|
||||
*index = c->index;
|
||||
return hvc_driver;
|
||||
}
|
||||
|
||||
static int __init hvc_console_setup(struct console *co, char *options)
|
||||
{
|
||||
if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
|
||||
return -ENODEV;
|
||||
|
||||
if (vtermnos[co->index] == -1)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct console hvc_con_driver = {
|
||||
.name = "hvc",
|
||||
.write = hvc_console_print,
|
||||
.device = hvc_console_device,
|
||||
.setup = hvc_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
};
|
||||
|
||||
/*
|
||||
* Early console initialization. Preceeds driver initialization.
|
||||
*
|
||||
* (1) we are first, and the user specified another driver
|
||||
* -- index will remain -1
|
||||
* (2) we are first and the user specified no driver
|
||||
* -- index will be set to 0, then we will fail setup.
|
||||
* (3) we are first and the user specified our driver
|
||||
* -- index will be set to user specified driver, and we will fail
|
||||
* (4) we are after driver, and this initcall will register us
|
||||
* -- if the user didn't specify a driver then the console will match
|
||||
*
|
||||
* Note that for cases 2 and 3, we will match later when the io driver
|
||||
* calls hvc_instantiate() and call register again.
|
||||
*/
|
||||
static int __init hvc_console_init(void)
|
||||
{
|
||||
register_console(&hvc_con_driver);
|
||||
return 0;
|
||||
}
|
||||
console_initcall(hvc_console_init);
|
||||
|
||||
/*
|
||||
* hvc_instantiate() is an early console discovery method which locates
|
||||
* consoles * prior to the vio subsystem discovering them. Hotplugged
|
||||
* vty adapters do NOT get an hvc_instantiate() callback since they
|
||||
* appear after early console init.
|
||||
*/
|
||||
int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
|
||||
{
|
||||
struct hvc_struct *hp;
|
||||
|
||||
if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
|
||||
return -1;
|
||||
|
||||
if (vtermnos[index] != -1)
|
||||
return -1;
|
||||
|
||||
/* make sure no no tty has been registerd in this index */
|
||||
hp = hvc_get_by_index(index);
|
||||
if (hp) {
|
||||
kobject_put(&hp->kobj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vtermnos[index] = vtermno;
|
||||
cons_ops[index] = ops;
|
||||
|
||||
/* reserve all indices upto and including this index */
|
||||
if (last_hvc < index)
|
||||
last_hvc = index;
|
||||
|
||||
/* if this index is what the user requested, then register
|
||||
* now (setup won't fail at this point). It's ok to just
|
||||
* call register again if previously .setup failed.
|
||||
*/
|
||||
if (index == hvc_con_driver.index)
|
||||
register_console(&hvc_con_driver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hvc_instantiate);
|
||||
|
||||
/* Wake the sleeping khvcd */
|
||||
static void hvc_kick(void)
|
||||
{
|
||||
hvc_kicked = 1;
|
||||
wake_up_process(hvc_task);
|
||||
}
|
||||
|
||||
static int hvc_poll(struct hvc_struct *hp);
|
||||
|
||||
/*
|
||||
* NOTE: This API isn't used if the console adapter doesn't support interrupts.
|
||||
* In this case the console is poll driven.
|
||||
*/
|
||||
static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
|
||||
{
|
||||
/* if hvc_poll request a repoll, then kick the hvcd thread */
|
||||
if (hvc_poll(dev_instance))
|
||||
hvc_kick();
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void hvc_unthrottle(struct tty_struct *tty)
|
||||
{
|
||||
hvc_kick();
|
||||
}
|
||||
|
||||
/*
|
||||
* The TTY interface won't be used until after the vio layer has exposed the vty
|
||||
* adapter to the kernel.
|
||||
|
@ -329,7 +469,7 @@ static void hvc_push(struct hvc_struct *hp)
|
|||
{
|
||||
int n;
|
||||
|
||||
n = hvc_put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
|
||||
n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
|
||||
if (n <= 0) {
|
||||
if (n == 0)
|
||||
return;
|
||||
|
@ -467,7 +607,7 @@ static int hvc_poll(struct hvc_struct *hp)
|
|||
break;
|
||||
}
|
||||
|
||||
n = hvc_get_chars(hp->vtermno, buf, count);
|
||||
n = hp->ops->get_chars(hp->vtermno, buf, count);
|
||||
if (n <= 0) {
|
||||
/* Hangup the tty when disconnected from host */
|
||||
if (n == -EPIPE) {
|
||||
|
@ -479,14 +619,17 @@ static int hvc_poll(struct hvc_struct *hp)
|
|||
}
|
||||
for (i = 0; i < n; ++i) {
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
/* Handle the SysRq Hack */
|
||||
if (buf[i] == '\x0f') { /* ^O -- should support a sequence */
|
||||
sysrq_pressed = 1;
|
||||
continue;
|
||||
} else if (sysrq_pressed) {
|
||||
handle_sysrq(buf[i], NULL, tty);
|
||||
sysrq_pressed = 0;
|
||||
continue;
|
||||
if (hp->index == hvc_con_driver.index) {
|
||||
/* Handle the SysRq Hack */
|
||||
/* XXX should support a sequence */
|
||||
if (buf[i] == '\x0f') { /* ^O */
|
||||
sysrq_pressed = 1;
|
||||
continue;
|
||||
} else if (sysrq_pressed) {
|
||||
handle_sysrq(buf[i], NULL, tty);
|
||||
sysrq_pressed = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MAGIC_SYSRQ */
|
||||
tty_insert_flip_char(tty, buf[i], 0);
|
||||
|
@ -497,8 +640,8 @@ static int hvc_poll(struct hvc_struct *hp)
|
|||
|
||||
/*
|
||||
* Account for the total amount read in one loop, and if above
|
||||
* 64 bytes, we do a quick schedule loop to let the tty grok the
|
||||
* data and eventually throttle us.
|
||||
* 64 bytes, we do a quick schedule loop to let the tty grok
|
||||
* the data and eventually throttle us.
|
||||
*/
|
||||
read_total += n;
|
||||
if (read_total >= 64) {
|
||||
|
@ -542,7 +685,6 @@ int khvcd(void *unused)
|
|||
if (cpus_empty(cpus_in_xmon)) {
|
||||
spin_lock(&hvc_structs_lock);
|
||||
list_for_each_entry(hp, &hvc_structs, next) {
|
||||
/*hp = list_entry(node, struct hvc_struct, * next); */
|
||||
poll_mask |= hvc_poll(hp);
|
||||
}
|
||||
spin_unlock(&hvc_structs_lock);
|
||||
|
@ -577,14 +719,6 @@ static struct tty_operations hvc_ops = {
|
|||
.chars_in_buffer = hvc_chars_in_buffer,
|
||||
};
|
||||
|
||||
char hvc_driver_name[] = "hvc_console";
|
||||
|
||||
static struct vio_device_id hvc_driver_table[] __devinitdata= {
|
||||
{"serial", "hvterm1"},
|
||||
{ NULL, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(vio, hvc_driver_table);
|
||||
|
||||
/* callback when the kboject ref count reaches zero. */
|
||||
static void destroy_hvc_struct(struct kobject *kobj)
|
||||
{
|
||||
|
@ -606,41 +740,51 @@ static struct kobj_type hvc_kobj_type = {
|
|||
.release = destroy_hvc_struct,
|
||||
};
|
||||
|
||||
static int __devinit hvc_probe(
|
||||
struct vio_dev *dev,
|
||||
const struct vio_device_id *id)
|
||||
struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
|
||||
struct hv_ops *ops)
|
||||
{
|
||||
struct hvc_struct *hp;
|
||||
|
||||
/* probed with invalid parameters. */
|
||||
if (!dev || !id)
|
||||
return -EPERM;
|
||||
int i;
|
||||
|
||||
hp = kmalloc(sizeof(*hp), GFP_KERNEL);
|
||||
if (!hp)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memset(hp, 0x00, sizeof(*hp));
|
||||
hp->vtermno = dev->unit_address;
|
||||
hp->vdev = dev;
|
||||
hp->vdev->dev.driver_data = hp;
|
||||
hp->irq = dev->irq;
|
||||
|
||||
hp->vtermno = vtermno;
|
||||
hp->irq = irq;
|
||||
hp->ops = ops;
|
||||
|
||||
kobject_init(&hp->kobj);
|
||||
hp->kobj.ktype = &hvc_kobj_type;
|
||||
|
||||
spin_lock_init(&hp->lock);
|
||||
spin_lock(&hvc_structs_lock);
|
||||
hp->index = ++hvc_count;
|
||||
|
||||
/*
|
||||
* find index to use:
|
||||
* see if this vterm id matches one registered for console.
|
||||
*/
|
||||
for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
|
||||
if (vtermnos[i] == hp->vtermno)
|
||||
break;
|
||||
|
||||
/* no matching slot, just use a counter */
|
||||
if (i >= MAX_NR_HVC_CONSOLES)
|
||||
i = ++last_hvc;
|
||||
|
||||
hp->index = i;
|
||||
|
||||
list_add_tail(&(hp->next), &hvc_structs);
|
||||
spin_unlock(&hvc_structs_lock);
|
||||
|
||||
return 0;
|
||||
return hp;
|
||||
}
|
||||
EXPORT_SYMBOL(hvc_alloc);
|
||||
|
||||
static int __devexit hvc_remove(struct vio_dev *dev)
|
||||
int __devexit hvc_remove(struct hvc_struct *hp)
|
||||
{
|
||||
struct hvc_struct *hp = dev->dev.driver_data;
|
||||
unsigned long flags;
|
||||
struct kobject *kobjp;
|
||||
struct tty_struct *tty;
|
||||
|
@ -673,23 +817,14 @@ static int __devexit hvc_remove(struct vio_dev *dev)
|
|||
tty_hangup(tty);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vio_driver hvc_vio_driver = {
|
||||
.name = hvc_driver_name,
|
||||
.id_table = hvc_driver_table,
|
||||
.probe = hvc_probe,
|
||||
.remove = hvc_remove,
|
||||
};
|
||||
EXPORT_SYMBOL(hvc_remove);
|
||||
|
||||
/* Driver initialization. Follow console initialization. This is where the TTY
|
||||
* interfaces start to become available. */
|
||||
int __init hvc_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* We need more than num_vterms adapters due to hotplug additions. */
|
||||
/* We need more than hvc_count adapters due to hotplug additions. */
|
||||
hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
|
||||
/* hvc_driver = alloc_tty_driver(num_vterms); */
|
||||
if (!hvc_driver)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -716,116 +851,20 @@ int __init hvc_init(void)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/* Register as a vio device to receive callbacks */
|
||||
rc = vio_register_driver(&hvc_vio_driver);
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
module_init(hvc_init);
|
||||
|
||||
/* This isn't particularily necessary due to this being a console driver but it
|
||||
* is nice to be thorough */
|
||||
/* This isn't particularily necessary due to this being a console driver
|
||||
* but it is nice to be thorough.
|
||||
*/
|
||||
static void __exit hvc_exit(void)
|
||||
{
|
||||
kthread_stop(hvc_task);
|
||||
|
||||
vio_unregister_driver(&hvc_vio_driver);
|
||||
tty_unregister_driver(hvc_driver);
|
||||
/* return tty_struct instances allocated in hvc_init(). */
|
||||
put_tty_driver(hvc_driver);
|
||||
unregister_console(&hvc_con_driver);
|
||||
}
|
||||
|
||||
/*
|
||||
* Console APIs, NOT TTY. These APIs are available immediately when
|
||||
* hvc_console_setup() finds adapters.
|
||||
*/
|
||||
|
||||
/*
|
||||
* hvc_instantiate() is an early console discovery method which locates consoles
|
||||
* prior to the vio subsystem discovering them. Hotplugged vty adapters do NOT
|
||||
* get an hvc_instantiate() callback since the appear after early console init.
|
||||
*/
|
||||
int hvc_instantiate(uint32_t vtermno, int index)
|
||||
{
|
||||
if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
|
||||
return -1;
|
||||
|
||||
if (vtermnos[index] != -1)
|
||||
return -1;
|
||||
|
||||
vtermnos[index] = vtermno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hvc_console_print(struct console *co, const char *b, unsigned count)
|
||||
{
|
||||
char c[16] __ALIGNED__;
|
||||
unsigned i = 0, n = 0;
|
||||
int r, donecr = 0;
|
||||
|
||||
/* Console access attempt outside of acceptable console range. */
|
||||
if (co->index >= MAX_NR_HVC_CONSOLES)
|
||||
return;
|
||||
|
||||
/* This console adapter was removed so it is not useable. */
|
||||
if (vtermnos[co->index] < 0)
|
||||
return;
|
||||
|
||||
while (count > 0 || i > 0) {
|
||||
if (count > 0 && i < sizeof(c)) {
|
||||
if (b[n] == '\n' && !donecr) {
|
||||
c[i++] = '\r';
|
||||
donecr = 1;
|
||||
} else {
|
||||
c[i++] = b[n++];
|
||||
donecr = 0;
|
||||
--count;
|
||||
}
|
||||
} else {
|
||||
r = hvc_put_chars(vtermnos[co->index], c, i);
|
||||
if (r < 0) {
|
||||
/* throw away chars on error */
|
||||
i = 0;
|
||||
} else if (r > 0) {
|
||||
i -= r;
|
||||
if (i > 0)
|
||||
memmove(c, c+r, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct tty_driver *hvc_console_device(struct console *c, int *index)
|
||||
{
|
||||
*index = c->index;
|
||||
return hvc_driver;
|
||||
}
|
||||
|
||||
static int __init hvc_console_setup(struct console *co, char *options)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct console hvc_con_driver = {
|
||||
.name = "hvc",
|
||||
.write = hvc_console_print,
|
||||
.device = hvc_console_device,
|
||||
.setup = hvc_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
};
|
||||
|
||||
/* Early console initialization. Preceeds driver initialization. */
|
||||
static int __init hvc_console_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<MAX_NR_HVC_CONSOLES; i++)
|
||||
vtermnos[i] = -1;
|
||||
num_vterms = hvc_find_vtys();
|
||||
register_console(&hvc_con_driver);
|
||||
return 0;
|
||||
}
|
||||
console_initcall(hvc_console_init);
|
||||
|
||||
module_init(hvc_init);
|
||||
module_exit(hvc_exit);
|
||||
|
|
152
drivers/char/hvc_vio.c
Normal file
152
drivers/char/hvc_vio.c
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* vio driver interface to hvc_console.c
|
||||
*
|
||||
* This code was moved here to allow the remaing code to be reused as a
|
||||
* generic polling mode with semi-reliable transport driver core to the
|
||||
* console and tty subsystems.
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
|
||||
* Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM
|
||||
* Copyright (C) 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
|
||||
* Copyright (C) 2004 IBM Corporation
|
||||
*
|
||||
* Additional Author(s):
|
||||
* Ryan S. Arnold <rsa@us.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/hvconsole.h>
|
||||
#include <asm/vio.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
char hvc_driver_name[] = "hvc_console";
|
||||
|
||||
static struct vio_device_id hvc_driver_table[] __devinitdata = {
|
||||
{"serial", "hvterm1"},
|
||||
{ NULL, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(vio, hvc_driver_table);
|
||||
|
||||
static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
|
||||
{
|
||||
unsigned long got;
|
||||
int i;
|
||||
|
||||
got = hvc_get_chars(vtermno, buf, count);
|
||||
|
||||
/*
|
||||
* Work around a HV bug where it gives us a null
|
||||
* after every \r. -- paulus
|
||||
*/
|
||||
for (i = 1; i < got; ++i) {
|
||||
if (buf[i] == 0 && buf[i-1] == '\r') {
|
||||
--got;
|
||||
if (i < got)
|
||||
memmove(&buf[i], &buf[i+1],
|
||||
got - i);
|
||||
}
|
||||
}
|
||||
return got;
|
||||
}
|
||||
|
||||
static struct hv_ops hvc_get_put_ops = {
|
||||
.get_chars = filtered_get_chars,
|
||||
.put_chars = hvc_put_chars,
|
||||
};
|
||||
|
||||
static int __devinit hvc_vio_probe(struct vio_dev *vdev,
|
||||
const struct vio_device_id *id)
|
||||
{
|
||||
struct hvc_struct *hp;
|
||||
|
||||
/* probed with invalid parameters. */
|
||||
if (!vdev || !id)
|
||||
return -EPERM;
|
||||
|
||||
hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops);
|
||||
if (IS_ERR(hp))
|
||||
return PTR_ERR(hp);
|
||||
dev_set_drvdata(&vdev->dev, hp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit hvc_vio_remove(struct vio_dev *vdev)
|
||||
{
|
||||
struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
|
||||
|
||||
return hvc_remove(hp);
|
||||
}
|
||||
|
||||
static struct vio_driver hvc_vio_driver = {
|
||||
.name = hvc_driver_name,
|
||||
.id_table = hvc_driver_table,
|
||||
.probe = hvc_vio_probe,
|
||||
.remove = hvc_vio_remove,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
static int hvc_vio_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Register as a vio device to receive callbacks */
|
||||
rc = vio_register_driver(&hvc_vio_driver);
|
||||
|
||||
return rc;
|
||||
}
|
||||
module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */
|
||||
|
||||
static void hvc_vio_exit(void)
|
||||
{
|
||||
vio_unregister_driver(&hvc_vio_driver);
|
||||
}
|
||||
module_exit(hvc_vio_exit);
|
||||
|
||||
/* the device tree order defines our numbering */
|
||||
static int hvc_find_vtys(void)
|
||||
{
|
||||
struct device_node *vty;
|
||||
int num_found = 0;
|
||||
|
||||
for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
|
||||
vty = of_find_node_by_name(vty, "vty")) {
|
||||
uint32_t *vtermno;
|
||||
|
||||
/* We have statically defined space for only a certain number
|
||||
* of console adapters.
|
||||
*/
|
||||
if (num_found >= MAX_NR_HVC_CONSOLES)
|
||||
break;
|
||||
|
||||
vtermno = (uint32_t *)get_property(vty, "reg", NULL);
|
||||
if (!vtermno)
|
||||
continue;
|
||||
|
||||
if (device_is_compatible(vty, "hvterm1")) {
|
||||
hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops);
|
||||
++num_found;
|
||||
}
|
||||
}
|
||||
|
||||
return num_found;
|
||||
}
|
||||
console_initcall(hvc_find_vtys);
|
|
@ -291,15 +291,13 @@ static void dump_packet(uint8_t *packet)
|
|||
dump_hex(packet, header->len);
|
||||
}
|
||||
|
||||
/* can't use hvc_get_chars because that strips CRs */
|
||||
static int hvsi_read(struct hvsi_struct *hp, char *buf, int count)
|
||||
{
|
||||
unsigned long got;
|
||||
|
||||
if (plpar_hcall(H_GET_TERM_CHAR, hp->vtermno, 0, 0, 0, &got,
|
||||
(unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
|
||||
return got;
|
||||
return 0;
|
||||
got = hvc_get_chars(hp->vtermno, buf, count);
|
||||
|
||||
return got;
|
||||
}
|
||||
|
||||
static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet,
|
||||
|
|
|
@ -770,10 +770,8 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
|
|||
}
|
||||
if (c == '\n') {
|
||||
if (L_ECHO(tty) || L_ECHONL(tty)) {
|
||||
if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
|
||||
if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
|
||||
put_char('\a', tty);
|
||||
return;
|
||||
}
|
||||
opost('\n', tty);
|
||||
}
|
||||
goto handle_newline;
|
||||
|
@ -790,10 +788,8 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
|
|||
* XXX are EOL_CHAR and EOL2_CHAR echoed?!?
|
||||
*/
|
||||
if (L_ECHO(tty)) {
|
||||
if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
|
||||
if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
|
||||
put_char('\a', tty);
|
||||
return;
|
||||
}
|
||||
/* Record the column of first canon char. */
|
||||
if (tty->canon_head == tty->read_head)
|
||||
tty->canon_column = tty->column;
|
||||
|
@ -862,12 +858,9 @@ static int n_tty_receive_room(struct tty_struct *tty)
|
|||
* that erase characters will be handled. Other excess
|
||||
* characters will be beeped.
|
||||
*/
|
||||
if (tty->icanon && !tty->canon_data)
|
||||
return N_TTY_BUF_SIZE;
|
||||
|
||||
if (left > 0)
|
||||
return left;
|
||||
return 0;
|
||||
if (left <= 0)
|
||||
left = tty->icanon && !tty->canon_data;
|
||||
return left;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1473,13 +1466,17 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file,
|
|||
if (tty->driver->flush_chars)
|
||||
tty->driver->flush_chars(tty);
|
||||
} else {
|
||||
c = tty->driver->write(tty, b, nr);
|
||||
if (c < 0) {
|
||||
retval = c;
|
||||
goto break_out;
|
||||
while (nr > 0) {
|
||||
c = tty->driver->write(tty, b, nr);
|
||||
if (c < 0) {
|
||||
retval = c;
|
||||
goto break_out;
|
||||
}
|
||||
if (!c)
|
||||
break;
|
||||
b += c;
|
||||
nr -= c;
|
||||
}
|
||||
b += c;
|
||||
nr -= c;
|
||||
}
|
||||
if (!nr)
|
||||
break;
|
||||
|
|
|
@ -71,7 +71,6 @@
|
|||
#include <linux/workqueue.h>
|
||||
#include <linux/hdlc.h>
|
||||
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
|
@ -593,11 +592,6 @@ static dev_link_t *mgslpc_attach(void)
|
|||
dev_list = link;
|
||||
|
||||
client_reg.dev_info = &dev_info;
|
||||
client_reg.EventMask =
|
||||
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
|
||||
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
|
||||
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||
client_reg.event_handler = &mgslpc_event;
|
||||
client_reg.Version = 0x0210;
|
||||
client_reg.event_callback_args.client_data = link;
|
||||
|
||||
|
@ -3093,6 +3087,7 @@ static struct pcmcia_driver mgslpc_driver = {
|
|||
.name = "synclink_cs",
|
||||
},
|
||||
.attach = mgslpc_attach,
|
||||
.event = mgslpc_event,
|
||||
.detach = mgslpc_detach,
|
||||
.id_table = mgslpc_ids,
|
||||
};
|
||||
|
|
|
@ -271,7 +271,7 @@ static int random_write_wakeup_thresh = 128;
|
|||
* samples to avoid wasting CPU time and reduce lock contention.
|
||||
*/
|
||||
|
||||
static int trickle_thresh = INPUT_POOL_WORDS * 28;
|
||||
static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28;
|
||||
|
||||
static DEFINE_PER_CPU(int, trickle_count) = 0;
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ static struct sysrq_key_op sysrq_term_op = {
|
|||
|
||||
static void moom_callback(void *ignored)
|
||||
{
|
||||
out_of_memory(GFP_KERNEL);
|
||||
out_of_memory(GFP_KERNEL, 0);
|
||||
}
|
||||
|
||||
static DECLARE_WORK(moom_work, moom_callback, NULL);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue