Compare commits

..

No commits in common. "master" and "Qubes-R1-Beta3-pre3" have entirely different histories.

434 changed files with 505610 additions and 12847 deletions

9
.gitignore vendored
View File

@ -1,8 +1 @@
linux-*.tar.gz
linux-*.tar.xz
linux-*.sign
WireGuard-*.tar.xz
WireGuard-*.tar.asc
kernel-*/
config-base-*
macbook12-spi-driver-*.tar.gz
linux-*.tar.bz2*

View File

@ -1,38 +0,0 @@
From a6b3add4337101ef875423c0888b8ac1cde47c2c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
<marmarek@invisiblethingslab.com>
Date: Thu, 6 Sep 2018 15:09:44 +0200
Subject: [PATCH] xen-netfront-detach-crash
When it get to free_page(queue->grant_tx_page[i]), the use counter on this page
is already 0, which cause a crash. Not sure if this is the proper fix
(according to git log this may introduce some memory leak), but at least it
prevent the crash.
Details in this thread:
http://xen.markmail.org/thread/pw5edbtqienjx4q5
---
drivers/net/xen-netfront.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 482c6c8b0fb7..8f0a790ec5e7 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1138,9 +1138,10 @@ static void xennet_release_tx_bufs(struct netfront_queue *queue)
skb = queue->tx_skbs[i].skb;
get_page(queue->grant_tx_page[i]);
- gnttab_end_foreign_access(queue->grant_tx_ref[i],
- GNTMAP_readonly,
- (unsigned long)page_address(queue->grant_tx_page[i]));
+ gnttab_end_foreign_access_ref(
+ queue->grant_tx_ref[i], GNTMAP_readonly);
+ gnttab_release_grant_reference(
+ &queue->gref_tx_head, queue->grant_tx_ref[i]);
queue->grant_tx_page[i] = NULL;
queue->grant_tx_ref[i] = GRANT_INVALID_REF;
add_id_to_freelist(&queue->tx_skb_freelist, queue->tx_skbs, i);
--
2.21.0

View File

@ -1,70 +0,0 @@
From a58197258286cf8dce45cf03b3b2b436b3cf8a99 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
<marmarek@invisiblethingslab.com>
Date: Tue, 5 Jan 2016 02:44:04 +0100
Subject: [PATCH] mce: hide EBUSY initialization error on Xen
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In case of Xen, the device is already registered by xen mcelog (in
xen_late_init_mcelog), so fail here is expected. Note that
mcheck_init_device call is still expected to initialize mce_device. Comment
from threshold_init_device explaining the situation:
/*
* there are 3 funcs which need to be _initcalled in a logic sequence:
* 1. xen_late_init_mcelog
* 2. mcheck_init_device
* 3. threshold_init_device
*
* xen_late_init_mcelog must register xen_mce_chrdev_device before
* native mce_chrdev_device registration if running under xen platform;
*
* mcheck_init_device should be inited before threshold_init_device to
* initialize mce_device, otherwise a NULL ptr dereference will cause panic.
*
* so we use following _initcalls
* 1. device_initcall(xen_late_init_mcelog);
* 2. device_initcall_sync(mcheck_init_device);
* 3. late_initcall(threshold_init_device);
*
* when running under xen, the initcall order is 1,2,3;
* on baremetal, we skip 1 and we do only 2 and 3.
*/
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
arch/x86/kernel/cpu/mce/core.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
index 743370ee4983..3af7521b2279 100644
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -51,6 +51,10 @@
#include <asm/msr.h>
#include <asm/reboot.h>
+#ifdef CONFIG_XEN_MCE_LOG
+#include <xen/xen.h>
+#endif
+
#include "internal.h"
static DEFINE_MUTEX(mce_log_mutex);
@@ -2464,6 +2468,11 @@ static __init int mcheck_init_device(void)
free_cpumask_var(mce_device_initialized);
err_out:
+#ifdef CONFIG_XEN_MCE_LOG
+ /* in case of Xen, the character device was already registered, so do not
+ * treat this as an error */
+ if (!xen_initial_domain() || err != -EBUSY)
+#endif
pr_err("Unable to init MCE device (rc: %d)\n", err);
return err;
--
2.21.0

View File

@ -1,27 +0,0 @@
From da15c0c3af84be25fdd695dddf61524099f4322e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
<marmarek@invisiblethingslab.com>
Date: Sat, 30 Jan 2016 01:53:26 +0100
Subject: [PATCH] Log error code of EVTCHNOP_bind_pirq failure
Ease debugging of PCI passthrough problems.
---
drivers/xen/events/events_base.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 6c8843968a52..54d2e30683c4 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -522,7 +522,7 @@ static unsigned int __startup_pirq(unsigned int irq)
BIND_PIRQ__WILL_SHARE : 0;
rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq);
if (rc != 0) {
- pr_warn("Failed to obtain physical IRQ %d\n", irq);
+ pr_warn("Failed to obtain physical IRQ %d (error %d)\n", irq, rc);
return 0;
}
evtchn = bind_pirq.port;
--
2.21.0

View File

@ -1,39 +0,0 @@
From 1b9928a04716a54933dcaff9ec7e68323f58090b Mon Sep 17 00:00:00 2001
From: Marek Marczykowski <marmarek@invisiblethingslab.com>
Date: Mon, 11 Jun 2012 22:49:31 +0200
Subject: [PATCH] pvops: respect 'removable' xenstore flag for block devices
Especially this is needed by pmount to allow mount qvm-block attached devices
by normal user.
---
drivers/block/xen-blkfront.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index a74d03913822..e76b999fceca 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -2339,6 +2339,7 @@ static void blkfront_connect(struct blkfront_info *info)
unsigned int binfo;
char *envp[] = { "RESIZE=1", NULL };
int err, i;
+ int removable;
switch (info->connected) {
case BLKIF_STATE_CONNECTED:
@@ -2406,6 +2407,12 @@ static void blkfront_connect(struct blkfront_info *info)
}
}
+ err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+ "removable", "%d", &removable,
+ NULL);
+ if (!err && removable)
+ binfo |= VDISK_REMOVABLE;
+
err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size,
physical_sector_size);
if (err) {
--
2.21.0

View File

@ -1,34 +0,0 @@
From 61d8059c42eaf388b857e0d5c8460ccb76c2f97c Mon Sep 17 00:00:00 2001
From: Marek Marczykowski <marmarek@invisiblethingslab.com>
Date: Sun, 15 Jul 2012 19:57:47 +0200
Subject: [PATCH] pvops/xen-blkfront: handle FDEJECT as detach request (#630)
---
drivers/block/xen-blkfront.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index e76b999fceca..db7d28ac9747 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -47,6 +47,7 @@
#include <linux/bitmap.h>
#include <linux/list.h>
#include <linux/workqueue.h>
+#include <linux/fd.h>
#include <xen/xen.h>
#include <xen/xenbus.h>
@@ -511,6 +512,9 @@ static int blkif_ioctl(struct block_device *bdev, fmode_t mode,
return 0;
return -EINVAL;
}
+ case FDEJECT:
+ xenbus_switch_state(info->xbdev, XenbusStateClosing);
+ return 0;
default:
/*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
--
2.21.0

View File

@ -1,49 +0,0 @@
From 56ce69a0260413418c2845182aa93165c4a1ce42 Mon Sep 17 00:00:00 2001
From: Rusty Bird <rustybird@openmailbox.org>
Date: Mon, 11 Jul 2016 13:05:38 +0000
Subject: [PATCH] block: add no_part_scan module parameter
Define a boolean module parameter named "no_part_scan" defaulting to N,
which, if set to Y, always causes the GENHD_FL_NO_PART_SCAN flag to be
added to subsequently created block devices, thereby disabling the
kernel's various partition table parsers for them.
The parameter's current value can be changed at any time by writing to
the /sys/module/block/parameters/no_part_scan file.
---
block/genhd.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/block/genhd.c b/block/genhd.c
index 26b31fcae217..75993c12e123 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -676,6 +676,15 @@ static void register_disk(struct device *parent, struct gendisk *disk,
}
}
+/* copied (not moved) from far down below, to have fewer patch hunks */
+#undef MODULE_PARAM_PREFIX
+#define MODULE_PARAM_PREFIX "block."
+
+/* partition scanning policy */
+static bool disk_no_part_scan = 0;
+module_param_named(no_part_scan, disk_no_part_scan, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(no_part_scan, "When adding block devices, always mark them as not to be scanned for partitions");
+
/**
* __device_add_disk - add disk information to kernel list
* @parent: parent device for the disk
@@ -704,6 +713,9 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk,
if (register_queue)
elevator_init_mq(disk->queue);
+ if (disk_no_part_scan)
+ disk->flags |= GENHD_FL_NO_PART_SCAN;
+
/* minors == 0 indicates to use ext devt from part0 and should
* be accompanied with EXT_DEVT flag. Make sure all
* parameters make sense.
--
2.21.0

View File

@ -1,58 +0,0 @@
From 76c089d06f5ff8dc7a54c3e5ef7d2f1447ca8ec4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
<marmarek@invisiblethingslab.com>
Date: Tue, 15 Dec 2015 21:35:14 +0100
Subject: [PATCH] xen: Add RING_COPY_RESPONSE()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Using RING_GET_RESPONSE() on a shared ring is easy to use incorrectly
(i.e., by not considering that the other end may alter the data in the
shared ring while it is being inspected). Safe usage of a response
generally requires taking a local copy.
Provide a RING_COPY_RESPONSE() macro to use instead of
RING_GET_RESPONSE() and an open-coded memcpy(). This takes care of
ensuring that the copy is done correctly regardless of any possible
compiler optimizations.
Use a volatile source to prevent the compiler from reordering or
omitting the copy.
This is part of XSA155.
CC: stable@vger.kernel.org
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
include/xen/interface/io/ring.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/include/xen/interface/io/ring.h b/include/xen/interface/io/ring.h
index 3f40501fc60b..03702f6874df 100644
--- a/include/xen/interface/io/ring.h
+++ b/include/xen/interface/io/ring.h
@@ -201,6 +201,20 @@ struct __name##_back_ring { \
#define RING_GET_RESPONSE(_r, _idx) \
(&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
+/*
+ * Get a local copy of a response.
+ *
+ * Use this in preference to RING_GET_RESPONSE() so all processing is
+ * done on a local copy that cannot be modified by the other end.
+ *
+ * Note that https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 may cause this
+ * to be ineffective where _rsp is a struct which consists of only bitfields.
+ */
+#define RING_COPY_RESPONSE(_r, _idx, _rsp) do { \
+ /* Use volatile to force the copy into _rsp. */ \
+ *(_rsp) = *(volatile typeof(_rsp))RING_GET_RESPONSE(_r, _idx); \
+} while (0)
+
/* Loop termination condition: Would the specified index overflow the ring? */
#define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \
(((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
--
2.21.0

View File

@ -1,177 +0,0 @@
From 688769df7c2365ae836eb755ccf5b196b45cbd56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
<marmarek@invisiblethingslab.com>
Date: Wed, 16 Dec 2015 05:09:55 +0100
Subject: [PATCH] xen-netfront: copy response out of shared buffer before
accessing it
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Make local copy of the response, otherwise backend might modify it while
frontend is already processing it - leading to time of check / time of
use issue.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
drivers/net/xen-netfront.c | 51 +++++++++++++++++++-------------------
1 file changed, 25 insertions(+), 26 deletions(-)
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 8f0a790ec5e7..abb9b3cd87b8 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -385,13 +385,13 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue)
rmb(); /* Ensure we see responses up to 'rp'. */
for (cons = queue->tx.rsp_cons; cons != prod; cons++) {
- struct xen_netif_tx_response *txrsp;
+ struct xen_netif_tx_response txrsp;
- txrsp = RING_GET_RESPONSE(&queue->tx, cons);
- if (txrsp->status == XEN_NETIF_RSP_NULL)
+ RING_COPY_RESPONSE(&queue->tx, cons, &txrsp);
+ if (txrsp.status == XEN_NETIF_RSP_NULL)
continue;
- id = txrsp->id;
+ id = txrsp.id;
skb = queue->tx_skbs[id].skb;
if (unlikely(gnttab_query_foreign_access(
queue->grant_tx_ref[id]) != 0)) {
@@ -739,7 +739,7 @@ static int xennet_get_extras(struct netfront_queue *queue,
RING_IDX rp)
{
- struct xen_netif_extra_info *extra;
+ struct xen_netif_extra_info extra;
struct device *dev = &queue->info->netdev->dev;
RING_IDX cons = queue->rx.rsp_cons;
int err = 0;
@@ -755,24 +755,23 @@ static int xennet_get_extras(struct netfront_queue *queue,
break;
}
- extra = (struct xen_netif_extra_info *)
- RING_GET_RESPONSE(&queue->rx, ++cons);
+ RING_COPY_RESPONSE(&queue->rx, ++cons, &extra);
- if (unlikely(!extra->type ||
- extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
+ if (unlikely(!extra.type ||
+ extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
if (net_ratelimit())
dev_warn(dev, "Invalid extra type: %d\n",
- extra->type);
+ extra.type);
err = -EINVAL;
} else {
- memcpy(&extras[extra->type - 1], extra,
- sizeof(*extra));
+ memcpy(&extras[extra.type - 1], &extra,
+ sizeof(extra));
}
skb = xennet_get_rx_skb(queue, cons);
ref = xennet_get_rx_ref(queue, cons);
xennet_move_rx_slot(queue, skb, ref);
- } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
+ } while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE);
queue->rx.rsp_cons = cons;
return err;
@@ -782,28 +781,28 @@ static int xennet_get_responses(struct netfront_queue *queue,
struct netfront_rx_info *rinfo, RING_IDX rp,
struct sk_buff_head *list)
{
- struct xen_netif_rx_response *rx = &rinfo->rx;
+ struct xen_netif_rx_response rx = rinfo->rx;
struct xen_netif_extra_info *extras = rinfo->extras;
struct device *dev = &queue->info->netdev->dev;
RING_IDX cons = queue->rx.rsp_cons;
struct sk_buff *skb = xennet_get_rx_skb(queue, cons);
grant_ref_t ref = xennet_get_rx_ref(queue, cons);
- int max = XEN_NETIF_NR_SLOTS_MIN + (rx->status <= RX_COPY_THRESHOLD);
+ int max = XEN_NETIF_NR_SLOTS_MIN + (rx.status <= RX_COPY_THRESHOLD);
int slots = 1;
int err = 0;
unsigned long ret;
- if (rx->flags & XEN_NETRXF_extra_info) {
+ if (rx.flags & XEN_NETRXF_extra_info) {
err = xennet_get_extras(queue, extras, rp);
cons = queue->rx.rsp_cons;
}
for (;;) {
- if (unlikely(rx->status < 0 ||
- rx->offset + rx->status > XEN_PAGE_SIZE)) {
+ if (unlikely(rx.status < 0 ||
+ rx.offset + rx.status > XEN_PAGE_SIZE)) {
if (net_ratelimit())
dev_warn(dev, "rx->offset: %u, size: %d\n",
- rx->offset, rx->status);
+ rx.offset, rx.status);
xennet_move_rx_slot(queue, skb, ref);
err = -EINVAL;
goto next;
@@ -817,7 +816,7 @@ static int xennet_get_responses(struct netfront_queue *queue,
if (ref == GRANT_INVALID_REF) {
if (net_ratelimit())
dev_warn(dev, "Bad rx response id %d.\n",
- rx->id);
+ rx.id);
err = -EINVAL;
goto next;
}
@@ -830,7 +829,7 @@ static int xennet_get_responses(struct netfront_queue *queue,
__skb_queue_tail(list, skb);
next:
- if (!(rx->flags & XEN_NETRXF_more_data))
+ if (!(rx.flags & XEN_NETRXF_more_data))
break;
if (cons + slots == rp) {
@@ -840,7 +839,7 @@ static int xennet_get_responses(struct netfront_queue *queue,
break;
}
- rx = RING_GET_RESPONSE(&queue->rx, cons + slots);
+ RING_COPY_RESPONSE(&queue->rx, cons + slots, &rx);
skb = xennet_get_rx_skb(queue, cons + slots);
ref = xennet_get_rx_ref(queue, cons + slots);
slots++;
@@ -895,9 +894,9 @@ static int xennet_fill_frags(struct netfront_queue *queue,
struct sk_buff *nskb;
while ((nskb = __skb_dequeue(list))) {
- struct xen_netif_rx_response *rx =
- RING_GET_RESPONSE(&queue->rx, ++cons);
+ struct xen_netif_rx_response rx;
skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0];
+ RING_COPY_RESPONSE(&queue->rx, ++cons, &rx);
if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS) {
unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
@@ -913,7 +912,7 @@ static int xennet_fill_frags(struct netfront_queue *queue,
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
skb_frag_page(nfrag),
- rx->offset, rx->status, PAGE_SIZE);
+ rx.offset, rx.status, PAGE_SIZE);
skb_shinfo(nskb)->nr_frags = 0;
kfree_skb(nskb);
@@ -1011,7 +1010,7 @@ static int xennet_poll(struct napi_struct *napi, int budget)
i = queue->rx.rsp_cons;
work_done = 0;
while ((i != rp) && (work_done < budget)) {
- memcpy(rx, RING_GET_RESPONSE(&queue->rx, i), sizeof(*rx));
+ RING_COPY_RESPONSE(&queue->rx, i, rx);
memset(extras, 0, sizeof(rinfo.extras));
err = xennet_get_responses(queue, &rinfo, rp, &tmpq);
--
2.21.0

View File

@ -1,64 +0,0 @@
From f2452d28602c2de1d69d5ca2e34e6771374414a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
<marmarek@invisiblethingslab.com>
Date: Wed, 16 Dec 2015 05:19:37 +0100
Subject: [PATCH] xen-netfront: do not use data already exposed to backend
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Backend may freely modify anything on shared page, so use data which was
supposed to be written there, instead of reading it back from the shared
page.
This is part of XSA155.
CC: stable@vger.kernel.org
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
drivers/net/xen-netfront.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index abb9b3cd87b8..56c8a4a32672 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -456,7 +456,7 @@ static void xennet_tx_setup_grant(unsigned long gfn, unsigned int offset,
tx->flags = 0;
info->tx = tx;
- info->size += tx->size;
+ info->size += len;
}
static struct xen_netif_tx_request *xennet_make_first_txreq(
@@ -572,7 +572,7 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
int slots;
struct page *page;
unsigned int offset;
- unsigned int len;
+ unsigned int len, this_len;
unsigned long flags;
struct netfront_queue *queue = NULL;
unsigned int num_queues = dev->real_num_tx_queues;
@@ -632,14 +632,15 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
}
/* First request for the linear area. */
+ this_len = min_t(unsigned int, XEN_PAGE_SIZE - offset, len);
first_tx = tx = xennet_make_first_txreq(queue, skb,
page, offset, len);
- offset += tx->size;
+ offset += this_len;
if (offset == PAGE_SIZE) {
page++;
offset = 0;
}
- len -= tx->size;
+ len -= this_len;
if (skb->ip_summed == CHECKSUM_PARTIAL)
/* local packet? */
--
2.21.0

View File

@ -1,35 +0,0 @@
From b5bc80763b7bf0f9e32a9a4d4f930ff50d02385d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
<marmarek@invisiblethingslab.com>
Date: Wed, 16 Dec 2015 05:22:24 +0100
Subject: [PATCH] xen-netfront: add range check for Tx response id
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Tx response ID is fetched from shared page, so make sure it is sane
before using it as an array index.
This is part of XSA155.
CC: stable@vger.kernel.org
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
drivers/net/xen-netfront.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 56c8a4a32672..e11df925c0dc 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -392,6 +392,7 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue)
continue;
id = txrsp.id;
+ BUG_ON(id >= NET_TX_RING_SIZE);
skb = queue->tx_skbs[id].skb;
if (unlikely(gnttab_query_foreign_access(
queue->grant_tx_ref[id]) != 0)) {
--
2.21.0

View File

@ -1,128 +0,0 @@
From def16082c5e64f97d5d138ae638a6cde7a136432 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
<marmarek@invisiblethingslab.com>
Date: Wed, 16 Dec 2015 05:51:10 +0100
Subject: [PATCH] xen-blkfront: make local copy of response before using it
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Data on the shared page can be changed at any time by the backend. Make
a local copy, which is no longer controlled by the backend. And only
then access it.
This is part of XSA155.
CC: stable@vger.kernel.org
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
drivers/block/xen-blkfront.c | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index db7d28ac9747..3f6dbaf0265b 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -1551,7 +1551,7 @@ static bool blkif_completion(unsigned long *id,
static irqreturn_t blkif_interrupt(int irq, void *dev_id)
{
struct request *req;
- struct blkif_response *bret;
+ struct blkif_response bret;
RING_IDX i, rp;
unsigned long flags;
struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)dev_id;
@@ -1568,8 +1568,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
for (i = rinfo->ring.rsp_cons; i != rp; i++) {
unsigned long id;
- bret = RING_GET_RESPONSE(&rinfo->ring, i);
- id = bret->id;
+ RING_COPY_RESPONSE(&rinfo->ring, i, &bret);
+ id = bret.id;
/*
* The backend has messed up and given us an id that we would
* never have given to it (we stamp it up to BLK_RING_SIZE -
@@ -1577,39 +1577,39 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
*/
if (id >= BLK_RING_SIZE(info)) {
WARN(1, "%s: response to %s has incorrect id (%ld)\n",
- info->gd->disk_name, op_name(bret->operation), id);
+ info->gd->disk_name, op_name(bret.operation), id);
/* We can't safely get the 'struct request' as
* the id is busted. */
continue;
}
req = rinfo->shadow[id].request;
- if (bret->operation != BLKIF_OP_DISCARD) {
+ if (bret.operation != BLKIF_OP_DISCARD) {
/*
* We may need to wait for an extra response if the
* I/O request is split in 2
*/
- if (!blkif_completion(&id, rinfo, bret))
+ if (!blkif_completion(&id, rinfo, &bret))
continue;
}
if (add_id_to_freelist(rinfo, id)) {
WARN(1, "%s: response to %s (id %ld) couldn't be recycled!\n",
- info->gd->disk_name, op_name(bret->operation), id);
+ info->gd->disk_name, op_name(bret.operation), id);
continue;
}
- if (bret->status == BLKIF_RSP_OKAY)
+ if (bret.status == BLKIF_RSP_OKAY)
blkif_req(req)->error = BLK_STS_OK;
else
blkif_req(req)->error = BLK_STS_IOERR;
- switch (bret->operation) {
+ switch (bret.operation) {
case BLKIF_OP_DISCARD:
- if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
+ if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) {
struct request_queue *rq = info->rq;
printk(KERN_WARNING "blkfront: %s: %s op failed\n",
- info->gd->disk_name, op_name(bret->operation));
+ info->gd->disk_name, op_name(bret.operation));
blkif_req(req)->error = BLK_STS_NOTSUPP;
info->feature_discard = 0;
info->feature_secdiscard = 0;
@@ -1619,15 +1619,15 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
break;
case BLKIF_OP_FLUSH_DISKCACHE:
case BLKIF_OP_WRITE_BARRIER:
- if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
+ if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) {
printk(KERN_WARNING "blkfront: %s: %s op failed\n",
- info->gd->disk_name, op_name(bret->operation));
+ info->gd->disk_name, op_name(bret.operation));
blkif_req(req)->error = BLK_STS_NOTSUPP;
}
- if (unlikely(bret->status == BLKIF_RSP_ERROR &&
+ if (unlikely(bret.status == BLKIF_RSP_ERROR &&
rinfo->shadow[id].req.u.rw.nr_segments == 0)) {
printk(KERN_WARNING "blkfront: %s: empty %s op failed\n",
- info->gd->disk_name, op_name(bret->operation));
+ info->gd->disk_name, op_name(bret.operation));
blkif_req(req)->error = BLK_STS_NOTSUPP;
}
if (unlikely(blkif_req(req)->error)) {
@@ -1640,9 +1640,9 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
/* fall through */
case BLKIF_OP_READ:
case BLKIF_OP_WRITE:
- if (unlikely(bret->status != BLKIF_RSP_OKAY))
+ if (unlikely(bret.status != BLKIF_RSP_OKAY))
dev_dbg(&info->xbdev->dev, "Bad return from blkdev data "
- "request: %x\n", bret->status);
+ "request: %x\n", bret.status);
break;
default:
--
2.21.0

View File

@ -1,191 +0,0 @@
From 115094605c08f2e2790f6110f7fdc002122e0788 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
<marmarek@invisiblethingslab.com>
Date: Wed, 16 Dec 2015 06:07:14 +0100
Subject: [PATCH] xen-blkfront: prepare request locally, only then put it on
the shared ring
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Do not reuse data which theoretically might be already modified by the
backend. This is mostly about private copy of the request
(info->shadow[id].req) - make sure the request saved there is really the
one just filled.
This is part of XSA155.
CC: stable@vger.kernel.org
Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
drivers/block/xen-blkfront.c | 76 +++++++++++++++++++++---------------
1 file changed, 44 insertions(+), 32 deletions(-)
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 3f6dbaf0265b..37235ab63ca9 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -527,19 +527,16 @@ static int blkif_ioctl(struct block_device *bdev, fmode_t mode,
static unsigned long blkif_ring_get_request(struct blkfront_ring_info *rinfo,
struct request *req,
- struct blkif_request **ring_req)
+ struct blkif_request *ring_req)
{
unsigned long id;
- *ring_req = RING_GET_REQUEST(&rinfo->ring, rinfo->ring.req_prod_pvt);
- rinfo->ring.req_prod_pvt++;
-
id = get_id_from_freelist(rinfo);
rinfo->shadow[id].request = req;
rinfo->shadow[id].status = REQ_WAITING;
rinfo->shadow[id].associated_id = NO_ASSOCIATED_ID;
- (*ring_req)->u.rw.id = id;
+ ring_req->u.rw.id = id;
return id;
}
@@ -547,23 +544,28 @@ static unsigned long blkif_ring_get_request(struct blkfront_ring_info *rinfo,
static int blkif_queue_discard_req(struct request *req, struct blkfront_ring_info *rinfo)
{
struct blkfront_info *info = rinfo->dev_info;
- struct blkif_request *ring_req;
+ struct blkif_request ring_req = { 0 };
unsigned long id;
/* Fill out a communications ring structure. */
id = blkif_ring_get_request(rinfo, req, &ring_req);
- ring_req->operation = BLKIF_OP_DISCARD;
- ring_req->u.discard.nr_sectors = blk_rq_sectors(req);
- ring_req->u.discard.id = id;
- ring_req->u.discard.sector_number = (blkif_sector_t)blk_rq_pos(req);
+ ring_req.operation = BLKIF_OP_DISCARD;
+ ring_req.u.discard.nr_sectors = blk_rq_sectors(req);
+ ring_req.u.discard.id = id;
+ ring_req.u.discard.sector_number = (blkif_sector_t)blk_rq_pos(req);
if (req_op(req) == REQ_OP_SECURE_ERASE && info->feature_secdiscard)
- ring_req->u.discard.flag = BLKIF_DISCARD_SECURE;
+ ring_req.u.discard.flag = BLKIF_DISCARD_SECURE;
else
- ring_req->u.discard.flag = 0;
+ ring_req.u.discard.flag = 0;
+
+ /* make the request available to the backend */
+ *RING_GET_REQUEST(&rinfo->ring, rinfo->ring.req_prod_pvt) = ring_req;
+ wmb();
+ rinfo->ring.req_prod_pvt++;
/* Keep a private copy so we can reissue requests when recovering. */
- rinfo->shadow[id].req = *ring_req;
+ rinfo->shadow[id].req = ring_req;
return 0;
}
@@ -695,7 +697,7 @@ static void blkif_setup_extra_req(struct blkif_request *first,
static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *rinfo)
{
struct blkfront_info *info = rinfo->dev_info;
- struct blkif_request *ring_req, *extra_ring_req = NULL;
+ struct blkif_request ring_req = { 0 }, extra_ring_req = { 0 };
unsigned long id, extra_id = NO_ASSOCIATED_ID;
bool require_extra_req = false;
int i;
@@ -760,16 +762,16 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
* BLKIF_OP_WRITE
*/
BUG_ON(req_op(req) == REQ_OP_FLUSH || req->cmd_flags & REQ_FUA);
- ring_req->operation = BLKIF_OP_INDIRECT;
- ring_req->u.indirect.indirect_op = rq_data_dir(req) ?
+ ring_req.operation = BLKIF_OP_INDIRECT;
+ ring_req.u.indirect.indirect_op = rq_data_dir(req) ?
BLKIF_OP_WRITE : BLKIF_OP_READ;
- ring_req->u.indirect.sector_number = (blkif_sector_t)blk_rq_pos(req);
- ring_req->u.indirect.handle = info->handle;
- ring_req->u.indirect.nr_segments = num_grant;
+ ring_req.u.indirect.sector_number = (blkif_sector_t)blk_rq_pos(req);
+ ring_req.u.indirect.handle = info->handle;
+ ring_req.u.indirect.nr_segments = num_grant;
} else {
- ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req);
- ring_req->u.rw.handle = info->handle;
- ring_req->operation = rq_data_dir(req) ?
+ ring_req.u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req);
+ ring_req.u.rw.handle = info->handle;
+ ring_req.operation = rq_data_dir(req) ?
BLKIF_OP_WRITE : BLKIF_OP_READ;
if (req_op(req) == REQ_OP_FLUSH || req->cmd_flags & REQ_FUA) {
/*
@@ -780,15 +782,15 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
* since it is guaranteed ordered WRT previous writes.)
*/
if (info->feature_flush && info->feature_fua)
- ring_req->operation =
+ ring_req.operation =
BLKIF_OP_WRITE_BARRIER;
else if (info->feature_flush)
- ring_req->operation =
+ ring_req.operation =
BLKIF_OP_FLUSH_DISKCACHE;
else
- ring_req->operation = 0;
+ ring_req.operation = 0;
}
- ring_req->u.rw.nr_segments = num_grant;
+ ring_req.u.rw.nr_segments = num_grant;
if (unlikely(require_extra_req)) {
extra_id = blkif_ring_get_request(rinfo, req,
&extra_ring_req);
@@ -798,7 +800,7 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
*/
rinfo->shadow[extra_id].num_sg = 0;
- blkif_setup_extra_req(ring_req, extra_ring_req);
+ blkif_setup_extra_req(&ring_req, &extra_ring_req);
/* Link the 2 requests together */
rinfo->shadow[extra_id].associated_id = id;
@@ -806,12 +808,12 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
}
}
- setup.ring_req = ring_req;
+ setup.ring_req = &ring_req;
setup.id = id;
setup.require_extra_req = require_extra_req;
if (unlikely(require_extra_req))
- setup.extra_ring_req = extra_ring_req;
+ setup.extra_ring_req = &extra_ring_req;
for_each_sg(rinfo->shadow[id].sg, sg, num_sg, i) {
BUG_ON(sg->offset + sg->length > PAGE_SIZE);
@@ -833,10 +835,20 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
if (setup.segments)
kunmap_atomic(setup.segments);
+ /* make the request available to the backend */
+ *RING_GET_REQUEST(&rinfo->ring, rinfo->ring.req_prod_pvt) = ring_req;
+ wmb();
+ rinfo->ring.req_prod_pvt++;
/* Keep a private copy so we can reissue requests when recovering. */
- rinfo->shadow[id].req = *ring_req;
- if (unlikely(require_extra_req))
- rinfo->shadow[extra_id].req = *extra_ring_req;
+ rinfo->shadow[id].req = ring_req;
+
+ if (unlikely(require_extra_req)) {
+ *RING_GET_REQUEST(&rinfo->ring, rinfo->ring.req_prod_pvt) = extra_ring_req;
+ wmb();
+ rinfo->ring.req_prod_pvt++;
+ /* Keep a private copy so we can reissue requests when recovering. */
+ rinfo->shadow[extra_id].req = extra_ring_req;
+ }
if (new_persistent_gnts)
gnttab_free_grant_references(setup.gref_head);
--
2.21.0

View File

@ -1,75 +0,0 @@
From 6a9f5a2435d3845b41f32b3768bb1c25bba1be2d Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Wed, 1 Apr 2015 17:01:26 -0400
Subject: [PATCH] xen/pcifront/pciback: Update pciif.h with ->err and ->result
values.
The '->err' should contain only the XEN_PCI_ERR_* type values.
The '->result' may contain -EXX values or any other value
that the XEN_PCI_OP_* deems appropiate.
As such update the header and also the implementations.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Details in this thread:
https://patchwork.kernel.org/patch/8258431/
---
drivers/pci/xen-pcifront.c | 2 +-
drivers/xen/xen-pciback/pciback_ops.c | 2 +-
include/xen/interface/io/pciif.h | 6 ++++--
3 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index d1b16cf3403f..4d6f2513b104 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -297,7 +297,7 @@ static int pci_frontend_enable_msix(struct pci_dev *dev,
} else {
pci_err(dev, "enable msix get err %x\n", err);
}
- return err;
+ return err ? -EINVAL : 0;
}
static void pci_frontend_disable_msix(struct pci_dev *dev)
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c
index 787966f44589..0574c9121124 100644
--- a/drivers/xen/xen-pciback/pciback_ops.c
+++ b/drivers/xen/xen-pciback/pciback_ops.c
@@ -266,7 +266,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
if (dev_data)
dev_data->ack_intr = 0;
- return result > 0 ? 0 : result;
+ return result >= 0 ? 0 : XEN_PCI_ERR_op_failed;
}
static
diff --git a/include/xen/interface/io/pciif.h b/include/xen/interface/io/pciif.h
index d9922ae36eb5..c8b674fd2455 100644
--- a/include/xen/interface/io/pciif.h
+++ b/include/xen/interface/io/pciif.h
@@ -70,7 +70,7 @@ struct xen_pci_op {
/* IN: what action to perform: XEN_PCI_OP_* */
uint32_t cmd;
- /* OUT: will contain an error number (if any) from errno.h */
+ /* OUT: will contain an XEN_PCI_ERR_* number. */
int32_t err;
/* IN: which device to touch */
@@ -82,7 +82,9 @@ struct xen_pci_op {
int32_t offset;
int32_t size;
- /* IN/OUT: Contains the result after a READ or the value to WRITE */
+ /* IN/OUT: Contains the result after a READ or the value to WRITE.
+ * If the err does not have XEN_PCI_ERR_success, depending on
+ * XEN_PCI_OP_* might have the errno value. */
uint32_t value;
/* IN: Contains extra infor for this operation */
uint32_t info;
--
2.21.0

View File

@ -1,194 +0,0 @@
From 3a7edaa90f1b3d7066ba9c227577039e4285cb3d Mon Sep 17 00:00:00 2001
From: HW42 <hw42@ipsumj.de>
Date: Tue, 12 Sep 2017 00:49:02 +0200
Subject: [PATCH] xen-pciback: add attribute to allow MSI enable flag writes
QEMU running in a stubdom needs to be able to set the MSI enable flag in
the PCI config space. This adds an attribute 'allow_msi_enable' which
when set for a PCI device allows writes to this flag. The toolstack will
need to set this for stubdoms.
This should not introduce any new security issues since a malicious
guest (or stubdom) can already generate MSIs through other ways, see
[1] page 8.
[1]: https://invisiblethingslab.com/resources/2011/Software%20Attacks%20on%20Intel%20VT-d.pdf
---
.../xen/xen-pciback/conf_space_capability.c | 39 +++++++++++
drivers/xen/xen-pciback/pci_stub.c | 64 +++++++++++++++++++
drivers/xen/xen-pciback/pciback.h | 1 +
3 files changed, 104 insertions(+)
diff --git a/drivers/xen/xen-pciback/conf_space_capability.c b/drivers/xen/xen-pciback/conf_space_capability.c
index e5694133ebe5..4be817f448c3 100644
--- a/drivers/xen/xen-pciback/conf_space_capability.c
+++ b/drivers/xen/xen-pciback/conf_space_capability.c
@@ -189,6 +189,40 @@ static const struct config_field caplist_pm[] = {
{}
};
+#define MSI_OK_BITS (PCI_MSI_FLAGS_ENABLE)
+
+static int msi_flags_write(struct pci_dev *dev, int offset, u16 new_value,
+ void *data)
+{
+ int err;
+ u16 old_value;
+ struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
+
+ if (xen_pcibk_permissive || dev_data->permissive)
+ goto write;
+
+ err = pci_read_config_word(dev, offset, &old_value);
+ if (err)
+ return err;
+
+ if (!dev_data->allow_msi_enable
+ || (new_value ^ old_value) & ~MSI_OK_BITS)
+ return PCIBIOS_SET_FAILED;
+
+write:
+ return pci_write_config_word(dev, offset, new_value);
+}
+
+static const struct config_field caplist_msi[] = {
+ {
+ .offset = PCI_MSI_FLAGS,
+ .size = 2,
+ .u.w.read = xen_pcibk_read_config_word,
+ .u.w.write = msi_flags_write,
+ },
+ {}
+};
+
static struct xen_pcibk_config_capability xen_pcibk_config_capability_pm = {
.capability = PCI_CAP_ID_PM,
.fields = caplist_pm,
@@ -197,11 +231,16 @@ static struct xen_pcibk_config_capability xen_pcibk_config_capability_vpd = {
.capability = PCI_CAP_ID_VPD,
.fields = caplist_vpd,
};
+static struct xen_pcibk_config_capability xen_pcibk_config_capability_msi = {
+ .capability = PCI_CAP_ID_MSI,
+ .fields = caplist_msi,
+};
int xen_pcibk_config_capability_init(void)
{
register_capability(&xen_pcibk_config_capability_vpd);
register_capability(&xen_pcibk_config_capability_pm);
+ register_capability(&xen_pcibk_config_capability_msi);
return 0;
}
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 097410a7cdb7..fb6a4a43c11d 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -304,6 +304,8 @@ void pcistub_put_pci_dev(struct pci_dev *dev)
xen_pcibk_config_reset_dev(dev);
xen_pcibk_config_free_dyn_fields(dev);
+ dev_data->allow_msi_enable = 0;
+
xen_unregister_device_domain_owner(dev);
spin_lock_irqsave(&found_psdev->lock, flags);
@@ -1431,6 +1433,63 @@ static ssize_t permissive_show(struct device_driver *drv, char *buf)
}
static DRIVER_ATTR_RW(permissive);
+static ssize_t allow_msi_enable_store(struct device_driver *drv, const char *buf,
+ size_t count)
+{
+ int domain, bus, slot, func;
+ int err;
+ struct pcistub_device *psdev;
+ struct xen_pcibk_dev_data *dev_data;
+
+ err = str_to_slot(buf, &domain, &bus, &slot, &func);
+ if (err)
+ goto out;
+
+ psdev = pcistub_device_find(domain, bus, slot, func);
+ if (!psdev) {
+ err = -ENODEV;
+ goto out;
+ }
+
+ dev_data = pci_get_drvdata(psdev->dev);
+ /* the driver data for a device should never be null at this point */
+ if (!dev_data) {
+ err = -ENXIO;
+ goto release;
+ }
+ dev_data->allow_msi_enable = 1;
+release:
+ pcistub_device_put(psdev);
+out:
+ if (!err)
+ err = count;
+ return err;
+}
+
+static ssize_t allow_msi_enable_show(struct device_driver *drv, char *buf)
+{
+ struct pcistub_device *psdev;
+ struct xen_pcibk_dev_data *dev_data;
+ size_t count = 0;
+ unsigned long flags;
+ spin_lock_irqsave(&pcistub_devices_lock, flags);
+ list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+ if (count >= PAGE_SIZE)
+ break;
+ if (!psdev->dev)
+ continue;
+ dev_data = pci_get_drvdata(psdev->dev);
+ if (!dev_data || !dev_data->allow_msi_enable)
+ continue;
+ count +=
+ scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
+ pci_name(psdev->dev));
+ }
+ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+ return count;
+}
+static DRIVER_ATTR_RW(allow_msi_enable);
+
static void pcistub_exit(void)
{
driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_new_slot);
@@ -1440,6 +1499,8 @@ static void pcistub_exit(void)
driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_quirks);
driver_remove_file(&xen_pcibk_pci_driver.driver,
&driver_attr_permissive);
+ driver_remove_file(&xen_pcibk_pci_driver.driver,
+ &driver_attr_allow_msi_enable);
driver_remove_file(&xen_pcibk_pci_driver.driver,
&driver_attr_irq_handlers);
driver_remove_file(&xen_pcibk_pci_driver.driver,
@@ -1530,6 +1591,9 @@ static int __init pcistub_init(void)
if (!err)
err = driver_create_file(&xen_pcibk_pci_driver.driver,
&driver_attr_permissive);
+ if (!err)
+ err = driver_create_file(&xen_pcibk_pci_driver.driver,
+ &driver_attr_allow_msi_enable);
if (!err)
err = driver_create_file(&xen_pcibk_pci_driver.driver,
diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h
index 263c059bff90..796f949c92be 100644
--- a/drivers/xen/xen-pciback/pciback.h
+++ b/drivers/xen/xen-pciback/pciback.h
@@ -45,6 +45,7 @@ struct xen_pcibk_dev_data {
struct list_head config_fields;
struct pci_saved_state *pci_saved_state;
unsigned int permissive:1;
+ unsigned int allow_msi_enable:1;
unsigned int warned_on_write:1;
unsigned int enable_intx:1;
unsigned int isr_on:1; /* Whether the IRQ handler is installed. */
--
2.21.0

138
Makefile
View File

@ -11,110 +11,55 @@ SOURCEDIR := $(WORKDIR)
NO_OF_CPUS := $(shell grep -c ^processor /proc/cpuinfo)
ifndef BUILD_FLAVOR
$(error "Add BUILD_FLAVOR=pvops or BUILD_FLAVOR=xenlinux to make cmdline")
endif
RPM_DEFINES := --define "_sourcedir $(SOURCEDIR)" \
--define "_specdir $(SPECDIR)" \
--define "_builddir $(BUILDDIR)" \
--define "_srcrpmdir $(SRCRPMDIR)" \
--define "_rpmdir $(RPMDIR)"
--define "_rpmdir $(RPMDIR)" \
--define "build_flavor $(BUILD_FLAVOR)" \
--define "jobs $(NO_OF_CPUS)"
VER_REL := $(shell rpm $(RPM_DEFINES) -q --qf "%{VERSION} %{RELEASE}\n" --specfile $(SPECFILE)| head -1)
ifndef NAME
$(error "You can not run this Makefile without having NAME defined")
endif
ifndef VERSION
VERSION := $(shell cat version)
VERSION := $(word 1, $(VER_REL))
endif
ifndef RELEASE
RELEASE := $(shell cat rel)
endif
ifneq ($(VERSION),$(subst -rc,,$(VERSION)))
DOWNLOAD_FROM_GIT=1
VERIFICATION := hash
else
VERIFICATION := signature
RELEASE := $(word 2, $(VER_REL))
endif
all: help
MIRROR := cdn.kernel.org
ifeq (,$(DISTFILES_MIRROR))
SRC_BASEURL := https://${MIRROR}/pub/linux/kernel/v$(shell echo $(VERSION) | sed 's/^\(2\.[0-9]*\).*/\1/;s/^3\..*/3.x/;s/^4\..*/4.x/;s/^5\..*/5.x/')
else
SRC_BASEURL := $(DISTFILES_MIRROR)
endif
ifeq ($(VERIFICATION),signature)
SRC_FILE := linux-${VERSION}.tar.xz
SIGN_FILE := linux-${VERSION}.tar.sign
else
SRC_FILE := linux-${VERSION}.tar.gz
HASH_FILE := $(SRC_FILE).sha512
endif
WG_BASE_URL := https://git.zx2c4.com/wireguard-linux-compat/snapshot
WG_SRC_FILE := wireguard-linux-compat-0.0.20200121.tar.xz
WG_SRC_URL := $(WG_BASE_URL)/$(WG_SRC_FILE)
WG_SIG_FILE := $(WG_SRC_FILE:%.xz=%.asc)
WG_SIG_URL := $(WG_BASE_URL)/$(WG_SIG_FILE)
SPI_BASE_URL := https://github.com/roadrunner2/macbook12-spi-driver/archive
SPI_REVISION := ddfbc7733542b8474a0e8f593aba91e06542be4f
SPI_SRC_URL := $(SPI_BASE_URL)/$(SPI_REVISION).tar.gz
SPI_SRC_FILE := macbook12-spi-driver-$(SPI_REVISION).tar.gz
SPI_HASH_SHA256 := 8039f103fbb351ecbbaddd540feeb7b0b1abfa216f0689a611e43d997426470e
MIRROR := kernel.inode.at
SRC_BASEURL := http://${MIRROR}/pub/linux/kernel/v$(shell echo $(VERSION) | sed 's/^\([0-9]*\.[0-9]*\).*/\1/')
SRC_FILE := linux-${VERSION}.tar.bz2
SIGN_FILE := linux-${VERSION}.tar.bz2.sign
URL := $(SRC_BASEURL)/$(SRC_FILE)
URL_SIGN := $(SRC_BASEURL)/$(SIGN_FILE)
ifeq ($(DOWNLOAD_FROM_GIT),1)
URL := https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-$(VERSION).tar.gz
endif
get-sources: $(SRC_FILE) $(SIGN_FILE) $(WG_SRC_FILE) $(WG_SIG_FILE) $(SPI_SRC_FILE)
get-sources: $(SRC_FILE)
$(SRC_FILE):
@wget -q -N $(URL)
@echo -n "Downloading $(URL)... "
@wget -q $(URL)
@wget -q $(URL_SIGN)
@echo "OK."
$(SIGN_FILE):
@wget -q -N $(URL_SIGN)
$(WG_SRC_FILE):
@wget -q -N $(WG_SRC_URL)
$(WG_SIG_FILE):
@wget -q -N $(WG_SIG_URL)
$(SPI_SRC_FILE):
@wget -q -N -O $(SPI_SRC_FILE) $(SPI_SRC_URL)
import-keys:
@if [ -n "$$GNUPGHOME" ]; then rm -f "$$GNUPGHOME/linux-kernel-trustedkeys.gpg"; fi
@gpg --no-auto-check-trustdb --no-default-keyring --keyring linux-kernel-trustedkeys.gpg -q --import kernel*-key.asc
@if [ -n "$$GNUPGHOME" ]; then rm -f "$$GNUPGHOME/wireguard-trustedkeys.gpg"; fi
@gpg --no-auto-check-trustdb --no-default-keyring --keyring wireguard-trustedkeys.gpg -q --import wireguard*-key.asc
verify-sources: import-keys
@xzcat $(WG_SRC_FILE) | gpgv --keyring wireguard-trustedkeys.gpg $(WG_SIG_FILE) - 2>/dev/null
ifeq ($(VERIFICATION),signature)
@xzcat $(SRC_FILE) | gpgv --keyring linux-kernel-trustedkeys.gpg $(SIGN_FILE) - 2>/dev/null
else
# there are no signatures for rc tarballs
# verify locally based on a signed git tag and commit hash file
sha512sum --quiet -c $(HASH_FILE)
endif
@gunzip -c $(SPI_SRC_FILE) | sha256sum | head -c64 | grep -q "^$(SPI_HASH_SHA256)$$"
verify-sources:
@gpg --verify $(SIGN_FILE) $(SRC_FILE)
.PHONY: clean-sources
clean-sources:
ifneq ($(SRC_FILE), None)
-rm $(SRC_FILE) $(SIGN_FILE)
endif
ifneq ($(WG_SRC_FILE), None)
-rm $(WG_SRC_FILE) $(WG_SIG_FILE)
endif
ifneq ($(SPI_SRC_FILE), None)
-rm $(SPI_SRC_FILE)
-rm $(SRC_FILE)
endif
@ -123,11 +68,7 @@ RPM := rpmbuild
RPM_WITH_DIRS = $(RPM) $(RPM_DEFINES)
rpms: rpms-dom0
rpms-vm:
rpms-dom0: get-sources $(SPECFILE)
rpms: get-sources $(SPECFILE)
$(RPM_WITH_DIRS) -bb $(SPECFILE)
rpm --addsign $(RPMDIR)/x86_64/*$(VERSION)-$(RELEASE)*.rpm
@ -149,6 +90,37 @@ srpm: get-sources $(SPECFILE)
verrel:
@echo $(NAME)-$(VERSION)-$(RELEASE)
update-repo-current:
ln -f rpm/x86_64/kernel-$(VERSION)-$(RELEASE)*.rpm ../yum/current-release/current/dom0/rpm/
ln -f rpm/x86_64/kernel-debuginfo-$(VERSION)-$(RELEASE)*.rpm ../yum/current-release/current/dom0/rpm/
ln -f rpm/x86_64/kernel-devel-$(VERSION)-$(RELEASE)*.rpm ../yum/current-release/current/dom0/rpm/
for vmrepo in ../yum/current-release/current/vm/* ; do \
ln -f rpm/x86_64/kernel-devel-$(VERSION)-$(RELEASE)*.rpm $$vmrepo/rpm/ ;\
done
update-repo-current-testing:
ln -f rpm/x86_64/kernel-$(VERSION)-$(RELEASE)*.rpm ../yum/current-release/current-testing/dom0/rpm/
ln -f rpm/x86_64/kernel-debuginfo-$(VERSION)-$(RELEASE)*.rpm ../yum/current-release/current-testing/dom0/rpm/
ln -f rpm/x86_64/kernel-devel-$(VERSION)-$(RELEASE)*.rpm ../yum/current-release/current-testing/dom0/rpm/
for vmrepo in ../yum/current-release/current-testing/vm/* ; do \
ln -f rpm/x86_64/kernel-devel-$(VERSION)-$(RELEASE)*.rpm $$vmrepo/rpm/ ;\
done
update-repo-unstable:
ln -f rpm/x86_64/kernel-$(VERSION)-$(RELEASE)*.rpm ../yum/current-release/unstable/dom0/rpm/
ln -f rpm/x86_64/kernel-debuginfo-$(VERSION)-$(RELEASE)*.rpm ../yum/current-release/unstable/dom0/rpm/
ln -f rpm/x86_64/kernel-devel-$(VERSION)-$(RELEASE)*.rpm ../yum/current-release/unstable/dom0/rpm/
for vmrepo in ../yum/current-release/unstable/vm/* ; do \
ln -f rpm/x86_64/kernel-devel-$(VERSION)-$(RELEASE)*.rpm $$vmrepo/rpm/ ;\
done
update-repo-installer-kernel-dom0:
ln -f rpm/x86_64/kernel-$(VERSION)-$(RELEASE)*.rpm ../installer/yum/qubes-dom0/rpm/
update-repo-installer-kernel-vm:
ln -f rpm/x86_64/kernel-qubes-vm-$(VERSION)-$(RELEASE)*.rpm ../installer/yum/qubes-dom0/rpm/
# mop up, printing out exactly what was mopped.
.PHONY : clean

View File

@ -1,4 +0,0 @@
ifeq ($(PACKAGE_SET),dom0)
RPM_SPEC_FILES := kernel.spec
NO_ARCHIVE := 1
endif

File diff suppressed because it is too large Load Diff

5599
config-pvops Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,138 +0,0 @@
## Qubes specific config settings.
##
## Lines starting with ## are comments.
################################################################################
## Enable expert options
CONFIG_EXPERT=y
################################################################################
## Use xz to save space on /boot
# CONFIG_KERNEL_GZIP is not set
CONFIG_KERNEL_XZ=y
################################################################################
## Enable /proc/config.gz to help debugging etc.
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
################################################################################
## Enable some more hardening options
CONFIG_GCC_PLUGINS=y
CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y
CONFIG_GCC_PLUGIN_STRUCTLEAK=y
CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL=y
## XXX: What's about RANDSTRUCT?
## Those depend on CONFIG_EXPERT
CONFIG_ARCH_MMAP_RND_BITS=32
CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
CONFIG_REFCOUNT_FULL=y
# CONFIG_KEXEC is not set
# CONFIG_LEGACY_VSYSCALL_EMULATE is not set
CONFIG_LEGACY_VSYSCALL_NONE=y
# CONFIG_ACPI_CUSTOM_METHOD is not set
CONFIG_SECURITY_DMESG_RESTRICT=y
CONFIG_INTEL_IOMMU_DEFAULT_ON=y
# CONFIG_PROC_KCORE is not set
CONFIG_PAGE_POISONING=y
# CONFIG_PAGE_POISONING_NO_SANITY is not set
CONFIG_PAGE_POISONING_ZERO=y
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_ON_OOPS_VALUE=1
CONFIG_PANIC_TIMEOUT=-1
CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_DEBUG_TIMEKEEPING=y
CONFIG_IO_STRICT_DEVMEM=y
CONFIG_SECURITY_YAMA=y
# CONFIG_HIBERNATION is not set
################################################################################
## Disable PCI hotplug to prevent DMA attacks via ExpressCard or Thunderbolt
## ports. QubesOS/qubes-issues#1673
# CONFIG_HOTPLUG_PCI is not set
################################################################################
## Deactivate selinux by default
# CONFIG_DEFAULT_SECURITY_SELINUX is not set
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_LSM="yama,loadpin,safesetid,integrity"
################################################################################
## Enable paravirt spinlocks. This should be more performant.
CONFIG_PARAVIRT_SPINLOCKS=y
################################################################################
## Disable DEBUG_WX. Xen PV guests currently have some WX pages, so suppress
## the useless Warning.
# CONFIG_DEBUG_WX is not set
################################################################################
## Set USB drivers to module to allow attaching PCI devices to pciback before
## those get loaded.
CONFIG_USB_UHCI_HCD=m
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_XHCI_HCD=m
################################################################################
## USB gadget driver support for testing qvm-usb
CONFIG_USB_GADGET=m
CONFIG_USB_CONFIGFS=m
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_DUMMY_HCD=m
################################################################################
## Enable AppArmor
## It's optionally used by Whonix (https://www.whonix.org/wiki/AppArmor).
CONFIG_SECURITY_APPARMOR=y
################################################################################
## TODO: from diff to old config
## CONFIG_X86_AMD_PLATFORM_DEVICE=y
##
## # CONFIG_X86_MCELOG_LEGACY is not set
## # CONFIG_X86_MCE_INJECT is not set
##
## CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
##
## sensors from 0f976d972a1671a303fad30a5e690304b0b82ee0
##
## Intel ME driver e0f8e9ca81b80d897b190f48a4af80eff3198cb1

View File

@ -1,95 +0,0 @@
## Minimal config for a Qubes VM. Intended for easier testing (git bisect, etc.)
##
## Lines starting with ## are comments.
##
## Run
##
## .../linux-kernel/gen-config arch/x86/configs/x86_64_defconfig .../linux-kernel/config-qubes-minimal
##
## in a linux tree to generate a complete config file.
################################################################################
## linux/kernel/configs/xen.config
## global stuff - these enable us to allow some
## of the not so generic stuff below for xen
CONFIG_PARAVIRT=y
CONFIG_NET=y
CONFIG_NET_CORE=y
CONFIG_NETDEVICES=y
CONFIG_BLOCK=y
CONFIG_WATCHDOG=y
CONFIG_TARGET_CORE=y
CONFIG_SCSI=y
CONFIG_FB=y
CONFIG_INPUT_MISC=y
CONFIG_MEMORY_HOTPLUG=y
CONFIG_TTY=y
## Technically not required but otherwise produces
## pretty useless systems starting from allnoconfig
## You want TCP/IP and ELF binaries right?
CONFIG_INET=y
CONFIG_BINFMT_ELF=y
## generic config
CONFIG_XEN=y
CONFIG_XEN_DOM0=y
## backend drivers
CONFIG_XEN_BACKEND=y
CONFIG_XEN_BLKDEV_BACKEND=m
CONFIG_XEN_NETDEV_BACKEND=m
CONFIG_HVC_XEN=y
CONFIG_XEN_WDT=m
CONFIG_XEN_SCSI_BACKEND=m
## frontend drivers
CONFIG_XEN_FBDEV_FRONTEND=m
CONFIG_HVC_XEN_FRONTEND=y
CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m
## others
CONFIG_XEN_BALLOON=y
CONFIG_XEN_SCRUB_PAGES=y
CONFIG_XEN_DEV_EVTCHN=m
CONFIG_XEN_BLKDEV_FRONTEND=m
CONFIG_XEN_NETDEV_FRONTEND=m
CONFIG_XENFS=m
CONFIG_XEN_COMPAT_XENFS=y
CONFIG_XEN_SYS_HYPERVISOR=y
CONFIG_XEN_XENBUS_FRONTEND=y
CONFIG_XEN_GNTDEV=m
CONFIG_XEN_GRANT_DEV_ALLOC=m
CONFIG_SWIOTLB_XEN=y
CONFIG_XEN_PRIVCMD=m
################################################################################
## linux/arch/x86/configs/xen.config
## global x86 required specific stuff
CONFIG_64BIT=y
## These enable us to allow some of the
## not so generic stuff below
CONFIG_HYPERVISOR_GUEST=y
CONFIG_PCI=y
CONFIG_PCI_MSI=y
CONFIG_X86_MCE=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_CPU_FREQ=y
## x86 xen specific config options
CONFIG_XEN_PVH=y
CONFIG_XEN_SAVE_RESTORE=y
## CONFIG_XEN_DEBUG_FS is not set
CONFIG_XEN_MCE_LOG=y
CONFIG_XEN_ACPI_PROCESSOR=m
## x86 specific backend drivers
CONFIG_XEN_PCIDEV_BACKEND=m
## x86 specific frontend drivers
CONFIG_XEN_PCIDEV_FRONTEND=m
## depends on MEMORY_HOTPLUG, arm64 doesn't enable this yet,
## move to generic config if it ever does.
CONFIG_XEN_BALLOON_MEMORY_HOTPLUG=y
################################################################################
## Some basic stuff required in an Qubes VM
CONFIG_DM_SNAPSHOT=m

5371
config-xenlinux Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +0,0 @@
#!/bin/bash
# The Qubes OS Project, https://www.qubes-os.org
#
# Copyright (C) 2017 Simon Gaiser <simon@invisiblethingslab.com>
# Copyright (c) 2009-2010 Wind River Systems, Inc.
# Copyright 2011 Linaro
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
set -eu -o pipefail
linux_merge_config="./scripts/kconfig/merge_config.sh"
make_opts=""
if [ -n "${LINUX_UPSTREAM_VERSION:-}" ]; then
linux_merge_config="../linux-$LINUX_UPSTREAM_VERSION/scripts/kconfig/merge_config.sh"
make_opts="-C ../linux-$LINUX_UPSTREAM_VERSION O=$PWD"
fi
if [ -z "$linux_merge_config" ]; then
printf 'Error: Could not find merge_config.sh from the linux source tree!\n'
exit 1
fi
sed_config_exp='s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p'
if [ $# -ne 2 ]; then
printf 'Usage: gen-config base.config local.config\n'
exit 1
fi
base_config="$1"
local_config="$2"
grep -v '^##' "$local_config" > "$local_config.gen" || [ $? -le 1 ]
$linux_merge_config -m "$base_config" "$local_config.gen"
make $make_opts KCONFIG_ALLCONFIG=.config alldefconfig
rc=0
for cfg in $(sed -n "$sed_config_exp" "$local_config.gen"); do
requested="$(grep -w "$cfg" "$local_config.gen" || true)"
actual="$(grep -w "$cfg" .config || true)"
if [ "$requested" != "$actual" ]; then
printf 'Local config setting for %s didn'\''t make it into the final config\n' "$cfg"
rc=1
fi
done
rm "$local_config.gen"
exit $rc

View File

@ -1,96 +0,0 @@
#!/bin/bash
# vim: set ts=4 sw=4 sts=4 et :
set -e
if [ "${VERBOSE:-0}" -ge 2 ] || [ "${DEBUG:-0}" -eq 1 ]; then
debug=1
set -x
fi
localdir="$(dirname "$(readlink -f "$0")")"
releasever="$1"
# Set to 1 to include rc srpm
rc="$2"
kernelver="$(cat "$localdir/version")"
kernelsrc="linux-$kernelver"
exit_clean() {
local exit_code=$?
rm -rf "$tmpdir"
exit "${exit_code}"
}
errecho() {
>&2 echo "$@"
}
# example of releasever: '29' or 'rawhide'
if [ "x$releasever" != "x" ]; then
if [[ ! "$releasever" =~ ^[1-9][0-9]$ ]] && [ "$releasever" != "rawhide" ]; then
errecho "Invalid release format"
exit 1
fi
elif [ "x$releasever" == "x" ]; then
listver="$(curl -s -L https://dl.fedoraproject.org/pub/fedora/linux/releases 2> /dev/null)"
releasever="$(echo "$listver" | sed -e 's/<[^>]*>//g' | awk '{print $1}' | grep -o "[1-9][0-9]" | tail -1)"
if ! [[ "$releasever" =~ ^[1-9][0-9]$ ]]; then
errecho "An error occurred while trying to determine latest Fedora version"
exit 1
fi
fi
# get the latest kernel rpm
latestver=$(dnf -q repoquery kernel-core --disablerepo=* --enablerepo=fedora --enablerepo=updates --releasever="$releasever")
if [ "$rc" != "1" ]; then
latestver=$(echo "$latestver" | grep -v "rc[0-9]*")
fi
latestver=$(echo "$latestver" | sort -V | tail -1 | cut -d ':' -f2)
latestrpm="kernel-core-$latestver.rpm"
if [ "$releasever" == 'rawhide' ]; then
releasever="$(echo "$latestver" | grep -o "fc[1-9][0-9]" | sed 's/fc//')"
fi
if [ "x$latestrpm" != "x" ] && [ "x$releasever" != "x" ]; then
key="$localdir/../builder-rpm/keys/RPM-GPG-KEY-fedora-$releasever-primary"
trap 'exit_clean' 0 1 2 3 6 15
tmpdir="$(mktemp -d -p "$localdir")"
# download latest kernel rpm
dnf -q download kernel-core --disablerepo=* --enablerepo=fedora --enablerepo=updates --releasever="$releasever"
mv "$latestrpm" "$tmpdir/$latestrpm.untrusted"
# check signature
mkdir -p "$tmpdir/rpmdb"
rpmkeys --dbpath="$tmpdir/rpmdb" --import "$key"
{ rpmkeys --dbpath="$tmpdir/rpmdb" --checksig "$tmpdir/$latestrpm.untrusted" | grep -q 'signatures OK' ; } || { errecho "Failed to check signature"; exit 1; }
mv "$tmpdir/$latestrpm.untrusted" "$tmpdir/$latestrpm"
# extract kernel sources in qubes-linux-kernel
tar xf "$localdir/$kernelsrc.tar.xz" -C "$tmpdir"
# get latest config and put it in extracted sources
rpm2cpio "$tmpdir/$latestrpm" | cpio --quiet -i --to-stdout "./lib/modules/$latestver/config" > "$tmpdir/$kernelsrc/.config"
# generate new config with: yes '' | make oldconfig
cd "$tmpdir/$kernelsrc/"
## drop config settings which depend on Fedora patches and adjust for the small version difference
if [ "$debug" == "1" ]; then
yes '' | make oldconfig
else
yes '' | make oldconfig > /dev/null 2>&1
fi
## remove comments in header
sed -i '1,4d' "$tmpdir/$kernelsrc/.config"
# create final config
cat - "$tmpdir/$kernelsrc/.config" > "$localdir/config-base-$(echo "$latestver" | cut -d '-' -f1)" << EOF
# Base config based on Fedora's config ($latestrpm)
# Only modification is \`yes '' | make oldconfig\` to drop config settings which
# depend on Fedora patches and adjust for the small version difference.
EOF
rm -rf "$tmpdir"
else
errecho "Unable to find the latest kernel rpm for Fedora $releasever"; exit 1
fi

View File

@ -1,45 +0,0 @@
%if 0%{?qubes_builder}
%define _sourcedir %(pwd)
%endif
#%define _unpackaged_files_terminate_build 0
%define variant pvops.qubes
%define plainrel %(cat rel)
%define rel %{plainrel}.%{variant}
%define version %(cat version)
Name: kernel-devel
Version: %{version}
Release: %{rel}
Epoch: 1000
Summary: Development files necessary for building kernel modules
Group: Development/Sources
License: GPL v2 only
Url: http://www.kernel.org/
%description
This package contains files necessary for building kernel modules (and
kernel module packages) against the pvops flavor of the kernel.
%prep
echo "Dummy spec, do not try to build, use kernel.spec instead"
exit 1
%build
echo "Dummy spec, do not try to build, use kernel.spec instead"
exit 1
%install
echo "Dummy spec, do not try to build, use kernel.spec instead"
exit 1
%files
%doc
%changelog

View File

@ -1,37 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=d8eq
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -1,863 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.12 (GNU/Linux)
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
kBETLNKF3RynOcOebKM4gpZU
=wjnZ
-----END PGP PUBLIC KEY BLOCK-----

817
kernel.org-key.asc Normal file
View File

@ -0,0 +1,817 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.14 (GNU/Linux)
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
=wkDV
-----END PGP PUBLIC KEY BLOCK-----

436
kernel.spec Normal file
View File

@ -0,0 +1,436 @@
# A spec file for building xenlinux Dom0 kernel for Qubes
# Based on the Open SUSE kernel-spec & Fedora kernel-spec.
#
#%define _unpackaged_files_terminate_build 0
%define variant %{build_flavor}.qubes
%define rel %(cat rel-%{build_flavor}).%{variant}
%define version %(cat version-%{build_flavor})
%define _buildshell /bin/bash
%define build_xen 1
%global cpu_arch x86_64
%define cpu_arch_flavor %cpu_arch/%build_flavor
%define kernelrelease %version-%rel.%cpu_arch
%define my_builddir %_builddir/%{name}-%{version}
%define build_src_dir %my_builddir/linux-%version
%define src_install_dir /usr/src/kernels/%kernelrelease
%define kernel_build_dir %my_builddir/linux-obj
%define vm_install_dir /var/lib/qubes/vm-kernels/%version
%(chmod +x %_sourcedir/{guards,apply-patches,check-for-config-changes})
%define install_vdso 1
Name: kernel
Summary: The Xen Kernel
Version: %{version}
Epoch: 1000
Release: %{rel}
License: GPL v2 only
Group: System/Kernel
Url: http://www.kernel.org/
AutoReqProv: on
BuildRequires: coreutils module-init-tools sparse
Provides: multiversion(kernel)
Provides: %name = %version-%kernelrelease
Provides: kernel-xen-dom0
Provides: kernel-qubes-dom0
Provides: kernel-drm-nouveau = 16
Requires: xen >= 3.4.3
Requires(post): /sbin/new-kernel-pkg
Requires(preun):/sbin/new-kernel-pkg
Requires(pre): coreutils gawk
Requires(post): dracut
Conflicts: sysfsutils < 2.0
# root-lvm only works with newer udevs
Conflicts: udev < 118
Conflicts: lvm2 < 2.02.33
Provides: kernel = %kernelrelease
Provides: kernel-uname-r = %kernelrelease
Source0: linux-%version.tar.bz2
Source14: series-%{build_flavor}.conf
Source16: guards
Source17: apply-patches
Source33: check-for-config-changes
Source100: config-%{build_flavor}
# FIXME: Including dirs this way does NOT produce proper src.rpms
Source200: patches.arch
Source201: patches.drivers
Source202: patches.fixes
Source203: patches.rpmify
Source204: patches.suse
Source205: patches.xen
Source207: patches.kernel.org
Source300: patches.qubes
Source301: u2mfn
Source302: vm-initramfs-pre-udev
BuildRoot: %{_tmppath}/%{name}-%{version}-build
ExclusiveArch: x86_64
%description
Qubes Dom0 kernel.
%prep
if ! [ -e %_sourcedir/linux-%version.tar.bz2 ]; then
echo "The %name-%version.nosrc.rpm package does not contain the" \
"complete sources. Please install kernel-source-%version.src.rpm."
exit 1
fi
SYMBOLS="xen-dom0 %{build_flavor}"
# Unpack all sources and patches
%setup -q -c -T -a 0
mkdir -p %kernel_build_dir
cd linux-%version
%_sourcedir/apply-patches %_sourcedir/series-%{build_flavor}.conf %_sourcedir $SYMBOLS
cd %kernel_build_dir
cp %_sourcedir/config-%{build_flavor} .config
%build_src_dir/scripts/config \
--set-str CONFIG_LOCALVERSION -%release.%cpu_arch \
--disable CONFIG_DEBUG_INFO
# --enable CONFIG_DEBUG_INFO
# Enabling CONFIG_DEBUG_INFO produces *huge* packages!
MAKE_ARGS="$MAKE_ARGS -C %build_src_dir O=$PWD"
if test -e %_sourcedir/TOLERATE-UNKNOWN-NEW-CONFIG-OPTIONS; then
yes '' | make oldconfig $MAKE_ARGS
else
cp .config .config.orig
make silentoldconfig $MAKE_ARGS < /dev/null
%_sourcedir/check-for-config-changes .config.orig .config
rm .config.orig
fi
make prepare $MAKE_ARGS
make scripts $MAKE_ARGS
krel=$(make -s kernelrelease $MAKE_ARGS)
if [ "$krel" != "%kernelrelease" ]; then
echo "Kernel release mismatch: $krel != %kernelrelease" >&2
exit 1
fi
make clean $MAKE_ARGS
rm -f source
find . ! -type d -printf '%%P\n' > %my_builddir/obj-files
%build
cd %kernel_build_dir
# If the %jobs macro is defined to a number, make will spawn that many jobs.
# There are several ways how to define it:
# With plain rpmbuild:
# rpmbuild -ba --define 'jobs N' kernel-$flavor.spec
# To spawn as many jobs as there are cpu cores:
# rpmbuild -ba --define "jobs 0$(grep -c ^processor /proc/cpuinfo)" \
# kernel-$flavor.spec
make %{?jobs:-j%jobs} all $MAKE_ARGS CONFIG_DEBUG_SECTION_MISMATCH=y
# Build u2mfn module
make -C %kernel_build_dir SUBDIRS=%_builddir/u2mfn modules
%install
# get rid of /usr/lib/rpm/brp-strip-debug
# strip removes too much from the vmlinux ELF binary
export NO_BRP_STRIP_DEBUG=true
export STRIP_KEEP_SYMTAB='*/vmlinux-*'
cd %kernel_build_dir
mkdir -p %buildroot/boot
cp -p System.map %buildroot/boot/System.map-%kernelrelease
if [ "%{build_flavor}" == "xenlinux" ]; then
cp -p arch/x86/boot/vmlinuz %buildroot/boot/vmlinuz-%kernelrelease
else
cp -p arch/x86/boot/bzImage %buildroot/boot/vmlinuz-%kernelrelease
fi
cp .config %buildroot/boot/config-%kernelrelease
%if %install_vdso
# Install the unstripped vdso's that are linked in the kernel image
make vdso_install $MAKE_ARGS INSTALL_MOD_PATH=%buildroot
%endif
# Create a dummy initramfs with roughly the size the real one will have.
# That way, rpm will know that this package requires some additional
# space in /boot.
dd if=/dev/zero of=%buildroot/boot/initramfs-%kernelrelease.img \
bs=1M count=20
gzip -c9 < Module.symvers > %buildroot/boot/symvers-%kernelrelease.gz
make modules_install $MAKE_ARGS INSTALL_MOD_PATH=%buildroot
make -C %kernel_build_dir SUBDIRS=%_builddir/u2mfn modules_install $MAKE_ARGS INSTALL_MOD_PATH=%buildroot
mkdir -p %buildroot/%src_install_dir
rm -f %buildroot/lib/modules/%kernelrelease/build
rm -f %buildroot/lib/modules/%kernelrelease/source
mkdir -p %buildroot/lib/modules/%kernelrelease/build
(cd %buildroot/lib/modules/%kernelrelease ; ln -s build source)
# dirs for additional modules per module-init-tools, kbuild/modules.txt
mkdir -p %buildroot/lib/modules/%kernelrelease/extra
mkdir -p %buildroot/lib/modules/%kernelrelease/updates
mkdir -p %buildroot/lib/modules/%kernelrelease/weak-updates
pushd %build_src_dir
cp --parents `find -type f -name "Makefile*" -o -name "Kconfig*"` %buildroot/lib/modules/%kernelrelease/build
cp -a scripts %buildroot/lib/modules/%kernelrelease/build
cp -a --parents arch/x86/include/asm %buildroot/lib/modules/%kernelrelease/build/
if [ "%{build_flavor}" == "xenlinux" ]; then
cp -a --parents arch/x86/include/mach-xen %buildroot/lib/modules/%kernelrelease/build/
fi
cp -a include %buildroot/lib/modules/%kernelrelease/build/include
popd
cp Module.symvers %buildroot/lib/modules/%kernelrelease/build
cp System.map %buildroot/lib/modules/%kernelrelease/build
if [ -s Module.markers ]; then
cp Module.markers %buildroot/lib/modules/%kernelrelease/build
fi
rm -rf %buildroot/lib/modules/%kernelrelease/build/Documentation
cp .config %buildroot/lib/modules/%kernelrelease/build
rm -f %buildroot/lib/modules/%kernelrelease/build/scripts/*.o
rm -f %buildroot/lib/modules/%kernelrelease/build/scripts/*/*.o
cp -a scripts/* %buildroot/lib/modules/%kernelrelease/build/scripts/
cp -a include/* %buildroot/lib/modules/%kernelrelease/build/include
# Make sure the Makefile and version.h have a matching timestamp so that
# external modules can be built
touch -r %buildroot/lib/modules/%kernelrelease/build/Makefile %buildroot/lib/modules/%kernelrelease/build/include/linux/version.h
touch -r %buildroot/lib/modules/%kernelrelease/build/.config %buildroot/lib/modules/%kernelrelease/build/include/linux/autoconf.h
# Copy .config to include/config/auto.conf so "make prepare" is unnecessary.
cp %buildroot/lib/modules/%kernelrelease/build/.config %buildroot/lib/modules/%kernelrelease/build/include/config/auto.conf
if test -s vmlinux.id; then
cp vmlinux.id %buildroot/lib/modules/%kernelrelease/build/vmlinux.id
else
echo >&2 "*** WARNING *** no vmlinux build ID! ***"
fi
#
# save the vmlinux file for kernel debugging into the kernel-debuginfo rpm
#
mkdir -p %buildroot%{debuginfodir}/lib/modules/%kernelrelease
cp vmlinux %buildroot%{debuginfodir}/lib/modules/%kernelrelease
find %buildroot/lib/modules/%kernelrelease -name "*.ko" -type f >modnames
# mark modules executable so that strip-to-file can strip them
xargs --no-run-if-empty chmod u+x < modnames
# Generate a list of modules for block and networking.
fgrep /drivers/ modnames | xargs --no-run-if-empty nm -upA |
sed -n 's,^.*/\([^/]*\.ko\): *U \(.*\)$,\1 \2,p' > drivers.undef
collect_modules_list()
{
sed -r -n -e "s/^([^ ]+) \\.?($2)\$/\\1/p" drivers.undef |
LC_ALL=C sort -u > %buildroot/lib/modules/%kernelrelease/modules.$1
}
collect_modules_list networking \
'register_netdev|ieee80211_register_hw|usbnet_probe'
collect_modules_list block \
'ata_scsi_ioctl|scsi_add_host|scsi_add_host_with_dma|blk_init_queue|register_mtd_blktrans|scsi_esp_register|scsi_register_device_handler'
collect_modules_list drm \
'drm_open|drm_init'
collect_modules_list modesetting \
'drm_crtc_init'
# detect missing or incorrect license tags
rm -f modinfo
while read i
do
echo -n "${i#%buildroot/lib/modules/%kernelrelease/} " >> modinfo
/sbin/modinfo -l $i >> modinfo
done < modnames
egrep -v \
'GPL( v2)?$|Dual BSD/GPL$|Dual MPL/GPL$|GPL and additional rights$' \
modinfo && exit 1
rm -f modinfo modnames
# Move the devel headers out of the root file system
mkdir -p %buildroot/usr/src/kernels
mv %buildroot/lib/modules/%kernelrelease/build/* %buildroot/%src_install_dir/
mv %buildroot/lib/modules/%kernelrelease/build/.config %buildroot/%src_install_dir
rmdir %buildroot/lib/modules/%kernelrelease/build
ln -sf %src_install_dir %buildroot/lib/modules/%kernelrelease/build
# Abort if there are any undefined symbols
msg="$(/sbin/depmod -F %buildroot/boot/System.map-%kernelrelease \
-b %buildroot -ae %kernelrelease 2>&1)"
if [ $? -ne 0 ] || echo "$msg" | grep 'needs unknown symbol'; then
exit 1
fi
if [ "%{build_flavor}" == "pvops" ]; then
mv %buildroot/lib/firmware %buildroot/lib/firmware-all
mkdir -p %buildroot/lib/firmware
mv %buildroot/lib/firmware-all %buildroot/lib/firmware/%kernelrelease
fi
# Prepare initramfs for Qubes VM
mkdir -p %buildroot/%vm_install_dir
/sbin/dracut --nomdadmconf --nolvmconf \
--kmoddir %buildroot/lib/modules/%kernelrelease \
--include %_sourcedir/vm-initramfs / \
-d "xenblk xen-blkfront cdrom ext4 jbd2 crc16 dm_snapshot" \
%buildroot/%vm_install_dir/initramfs %kernelrelease
if [ "%{build_flavor}" == "xenlinux" ]; then
cp -p arch/x86/boot/vmlinuz %buildroot/%vm_install_dir/vmlinuz
else
cp -p arch/x86/boot/bzImage %buildroot/%vm_install_dir/vmlinuz
fi
# Modules for Qubes VM
mkdir -p %buildroot%vm_install_dir/modules
cp -a %buildroot/lib/modules/%kernelrelease %buildroot%vm_install_dir/modules/
mkdir -p %buildroot%vm_install_dir/modules/firmware
cp -a %buildroot/lib/firmware/%kernelrelease %buildroot%vm_install_dir/modules/firmware/
# remove files that will be auto generated by depmod at rpm -i time
for i in alias alias.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap
do
rm -f %buildroot/lib/modules/%kernelrelease/modules.$i
done
%post
INITRD_OPT="--mkinitrd --dracut"
/sbin/new-kernel-pkg --package %{name}-%{kernelrelease}\
$INITRD_OPT \
--depmod --kernel-args="max_loop=255"\
--multiboot=/boot/xen.gz --banner="Qubes"\
--make-default --install %{kernelrelease}
if [ -e /boot/grub/grub.conf ]; then
# Make it possible to enter GRUB menu if something goes wrong...
sed -i "s/^timeout *=.*/timeout=3/" /boot/grub/grub.conf
fi
%posttrans
/sbin/new-kernel-pkg --package %{name}-%{kernelrelease} --rpmposttrans %{kernelrelease}
%preun
/sbin/new-kernel-pkg --rminitrd --rmmoddep --remove %{kernelrelease}
%files
%defattr(-, root, root)
%ghost /boot/initramfs-%{kernelrelease}.img
/boot/System.map-%{kernelrelease}
/boot/config-%{kernelrelease}
/boot/symvers-%kernelrelease.gz
%attr(0644, root, root) /boot/vmlinuz-%{kernelrelease}
/lib/firmware/%{kernelrelease}
/lib/modules/%{kernelrelease}
%package devel
Summary: Development files necessary for building kernel modules
License: GPL v2 only
Group: Development/Sources
Provides: multiversion(kernel)
Provides: %name-devel = %kernelrelease
Provides: kernel-devel-uname-r = %kernelrelease
AutoReqProv: on
%description devel
This package contains files necessary for building kernel modules (and
kernel module packages) against the %build_flavor flavor of the kernel.
%post devel
if [ -f /etc/sysconfig/kernel ]
then
. /etc/sysconfig/kernel || exit $?
fi
if [ "$HARDLINK" != "no" -a -x /usr/sbin/hardlink ]
then
(cd /usr/src/kernels/%{kernelrelease} &&
/usr/bin/find . -type f | while read f; do
hardlink -c /usr/src/kernels/*.fc*.*/$f $f
done)
fi
%files devel
%defattr(-,root,root)
/usr/src/kernels/%{kernelrelease}
%package qubes-vm
Summary: The Xen Kernel
Version: %{version}
Release: %{rel}
License: GPL v2 only
Group: System/Kernel
Url: http://www.kernel.org/
AutoReqProv: on
BuildRequires: coreutils module-init-tools sparse
Provides: multiversion(kernel-qubes-vm)
Provides: kernel-xen-domU
Provides: kernel-qubes-domU
Requires(pre): coreutils gawk
Requires(post): dracut
Conflicts: sysfsutils < 2.0
# root-lvm only works with newer udevs
Conflicts: udev < 118
Conflicts: lvm2 < 2.02.33
Provides: kernel-qubes-vm = %version-%kernelrelease
%description qubes-vm
Qubes domU kernel.
%post qubes-vm
mkdir /tmp/qubes-modules-%kernelrelease
truncate -s 200M /tmp/qubes-modules-%kernelrelease.img
mkfs -t ext3 -F /tmp/qubes-modules-%kernelrelease.img > /dev/null
mount /tmp/qubes-modules-%kernelrelease.img /tmp/qubes-modules-%kernelrelease -o loop
cp -a -t /tmp/qubes-modules-%kernelrelease %vm_install_dir/modules/%kernelrelease
mkdir /tmp/qubes-modules-%kernelrelease/firmware
cp -a -t /tmp/qubes-modules-%kernelrelease/firmware %vm_install_dir/modules/firmware/%kernelrelease
umount /tmp/qubes-modules-%kernelrelease
rmdir /tmp/qubes-modules-%kernelrelease
mv /tmp/qubes-modules-%kernelrelease.img %vm_install_dir/modules.img
qvm-set-default-kernel %version
%files qubes-vm
%defattr(-, root, root)
%ghost %attr(0644, root, root) %vm_install_dir/modules.img
%attr(0644, root, root) %vm_install_dir/initramfs
%attr(0644, root, root) %vm_install_dir/vmlinuz
%vm_install_dir/modules
%changelog

View File

@ -1,679 +0,0 @@
# A spec file for building xenlinux Dom0 kernel for Qubes
# Based on the Open SUSE kernel-spec & Fedora kernel-spec.
#
%define variant qubes
%define plainrel @REL@
%define rel %{plainrel}.%{variant}
%define version %(echo '@VERSION@' | sed 's/~rc.*/.0/')
%define upstream_version %(echo '@VERSION@' | sed 's/~rc/-rc/')
%if "%{version}" != "%{upstream_version}"
%define prerelease 1
%define rel 0.%(echo '@VERSION@' | sed 's/.*~rc/rc/').%{plainrel}.%{variant}
%else
%define prerelease 0
%define rel %{plainrel}.%{variant}
%endif
%define name_suffix -latest
%define _buildshell /bin/bash
%define build_xen 1
%global cpu_arch x86_64
%define cpu_arch_flavor %cpu_arch
%define kernelrelease %(echo %{upstream_version} | sed 's/^[0-9]\\.[0-9]\\+$/\\0.0/;s/-rc.*/.0/')-%rel.%cpu_arch
%define my_builddir %_builddir/%{name}-%{version}
%define build_src_dir %my_builddir/linux-%upstream_version
%define src_install_dir /usr/src/kernels/%kernelrelease
%define kernel_build_dir %my_builddir/linux-obj
%define vm_install_dir /var/lib/qubes/vm-kernels/%upstream_version-%{plainrel}
%define install_vdso 1
%define debuginfodir /usr/lib/debug
# debuginfo build is disabled by default to save disk space (it needs 2-3GB build time)
%define with_debuginfo 0
# Sign all modules
%global signmodules 1
%if !%{with_debuginfo}
%global debug_package %{nil}
%define setup_config --disable CONFIG_DEBUG_INFO
%else
%define setup_config --enable CONFIG_DEBUG_INFO --disable CONFIG_DEBUG_INFO_REDUCED
%endif
Name: kernel%{?name_suffix}
Summary: The Xen Kernel
Version: %{version}
Epoch: 1000
Release: %{rel}
License: GPL v2 only
Group: System/Kernel
Url: http://www.kernel.org/
AutoReqProv: on
BuildRequires: coreutils module-init-tools sparse
BuildRequires: qubes-kernel-vm-support
BuildRequires: dracut
BuildRequires: busybox
BuildRequires: bc
BuildRequires: openssl
BuildRequires: openssl-devel
BuildRequires: python3-devel
BuildRequires: gcc-plugin-devel
BuildRequires: elfutils-libelf-devel
BuildRequires: bison
BuildRequires: flex
BuildRequires: e2fsprogs
# gcc with support for BTI mitigation
%if 0%{?fedora} == 23
BuildRequires: gcc >= 5.3.1-6.qubes1
%else
%if 0%{?fedora} == 25
BuildRequires: gcc >= 6.4.1-1.qubes1
%else
BuildRequires: gcc
%endif
%endif
# Needed for building GCC hardened plugins
BuildRequires: gcc-c++
Provides: multiversion(kernel)
Provides: %name = %kernelrelease
Provides: kernel-xen-dom0
Provides: kernel-qubes-dom0
Provides: kernel-qubes-dom0-pvops
Provides: kernel-drm = 4.3.0
Provides: kernel-drm-nouveau = 16
Provides: kernel-modules-extra = %kernelrelease
Provides: kernel-modeset = 1
Requires(pre): coreutils gawk
Requires(post): dracut binutils
Requires: qubes-core-dom0-linux-kernel-install
Conflicts: sysfsutils < 2.0
# root-lvm only works with newer udevs
Conflicts: udev < 118
Conflicts: lvm2 < 2.02.33
Provides: kernel = %kernelrelease
Provides: kernel-uname-r = %kernelrelease
ExclusiveArch: x86_64
%if !%{prerelease}
Source0: linux-%{upstream_version}.tar.xz
%else
Source0: linux-%{upstream_version}.tar.gz
%endif
Source5: wireguard-linux-compat-0.0.20200121.tar.xz
Source6: macbook12-spi-driver-ddfbc7733542b8474a0e8f593aba91e06542be4f.tar.gz
Source16: guards
Source17: apply-patches
Source18: mod-sign.sh
Source33: check-for-config-changes
Source34: gen-config
Source100: config-base
Source101: config-qubes
%define modsign_cmd %{SOURCE18}
Patch0: 0001-xen-netfront-detach-crash.patch
Patch1: 0002-mce-hide-EBUSY-initialization-error-on-Xen.patch
Patch2: 0003-Log-error-code-of-EVTCHNOP_bind_pirq-failure.patch
Patch3: 0004-pvops-respect-removable-xenstore-flag-for-block-devi.patch
Patch4: 0005-pvops-xen-blkfront-handle-FDEJECT-as-detach-request-.patch
Patch5: 0006-block-add-no_part_scan-module-parameter.patch
Patch6: 0007-xen-Add-RING_COPY_RESPONSE.patch
Patch7: 0008-xen-netfront-copy-response-out-of-shared-buffer-befo.patch
Patch8: 0009-xen-netfront-do-not-use-data-already-exposed-to-back.patch
Patch9: 0010-xen-netfront-add-range-check-for-Tx-response-id.patch
Patch10: 0011-xen-blkfront-make-local-copy-of-response-before-usin.patch
Patch11: 0012-xen-blkfront-prepare-request-locally-only-then-put-i.patch
Patch12: 0013-xen-pcifront-pciback-Update-pciif.h-with-err-and-res.patch
Patch13: 0014-xen-pciback-add-attribute-to-allow-MSI-enable-flag-w.patch
%description
Qubes Dom0 kernel.
%prep
SYMBOLS="xen-dom0 pvops"
# Unpack all sources and patches
%autosetup -N -c -T -a 0
export LINUX_UPSTREAM_VERSION=%{upstream_version}
mkdir -p %kernel_build_dir
cd linux-%upstream_version
%autopatch -p1
# drop EXTRAVERSION - possible -rc suffix already included in %release
sed -i -e 's/^EXTRAVERSION = -rc.*/EXTRAVERSION =/' Makefile
%if 0%{?fedora} >= 31
# Mangle /usr/bin/python shebangs to /usr/bin/python3
# Mangle all Python shebangs to be Python 3 explicitly
# -p preserves timestamps
# -n prevents creating ~backup files
# -i specifies the interpreter for the shebang
# This fixes errors such as
# *** ERROR: ambiguous python shebang in /usr/bin/kvm_stat: #!/usr/bin/python. Change it to python3 (or python2) explicitly.
# We patch all sources below for which we got a report/error.
pathfix.py -i "%{__python3} %{py3_shbang_opts}" -p -n \
tools/kvm/kvm_stat/kvm_stat \
scripts/show_delta \
scripts/diffconfig \
scripts/bloat-o-meter \
tools/perf/tests/attr.py \
tools/perf/scripts/python/stat-cpi.py \
tools/perf/scripts/python/sched-migration.py \
Documentation \
scripts/gen_compile_commands.py
%endif
cd %kernel_build_dir
# Create QubesOS config kernel
%{SOURCE34} %{SOURCE100} %{SOURCE101}
%build_src_dir/scripts/config \
--set-str CONFIG_LOCALVERSION -%release.%cpu_arch %{setup_config}
MAKE_ARGS="$MAKE_ARGS -C %build_src_dir O=$PWD KERNELRELEASE=%{kernelrelease}"
make prepare $MAKE_ARGS
make scripts $MAKE_ARGS
make scripts_basic $MAKE_ARGS
krel=$(make -s kernelrelease $MAKE_ARGS)
if [ "$krel" != "%kernelrelease" ]; then
echo "Kernel release mismatch: $krel != %kernelrelease" >&2
exit 1
fi
make clean $MAKE_ARGS
rm -f source
find . ! -type d -printf '%%P\n' > %my_builddir/obj-files
rm -rf %_builddir/u2mfn
u2mfn_ver=`dkms status u2mfn|tail -n 1|cut -f 2 -d ' '|tr -d ':,:'`
if [ -n "$u2mfn_ver" ]; then
cp -r /usr/src/u2mfn-$u2mfn_ver %_builddir/u2mfn
fi
rm -rf %_builddir/wireguard
tar x -C %_builddir -Jpf %{SOURCE5}
mv %_builddir/$(basename %{SOURCE5} .tar.xz) %_builddir/wireguard
rm -rf %_builddir/macbook12-spi-driver
tar -x -C %_builddir -zf %{SOURCE6}
mv %_builddir/$(basename %{SOURCE6} .tar.gz) %_builddir/macbook12-spi-driver
%build
cd %kernel_build_dir
make %{?_smp_mflags} all $MAKE_ARGS CONFIG_DEBUG_SECTION_MISMATCH=y
# Build u2mfn module
if [ -d "%_builddir/u2mfn" ]; then
make -C %kernel_build_dir M=%_builddir/u2mfn modules
fi
if [ -d "%_builddir/wireguard" ]; then
make -C %kernel_build_dir M=%_builddir/wireguard/src modules
fi
# Build applespi, apple-ibridge, apple-ib-tb, apple-ib-als modules
if [ -d "%_builddir/macbook12-spi-driver" ]; then
make -C %kernel_build_dir M=%_builddir/macbook12-spi-driver modules
fi
%define __modsign_install_post \
if [ "%{signmodules}" -eq "1" ]; then \
%{modsign_cmd} certs/signing_key.pem certs/signing_key.x509 $RPM_BUILD_ROOT/lib/modules/%kernelrelease/ \
fi \
%{nil}
#
# Disgusting hack alert! We need to ensure we sign modules *after* all
# invocations of strip occur, which is in __debug_install_post if
# find-debuginfo.sh runs, and __os_install_post if not.
#
%define __spec_install_post \
%{?__debug_package:%{__debug_install_post}}\
%{__arch_install_post}\
%{__os_install_post}\
%{?__remove_unwanted_dbginfo_install_post}\
%{__modsign_install_post}
%install
# get rid of /usr/lib/rpm/brp-strip-debug
# strip removes too much from the vmlinux ELF binary
export NO_BRP_STRIP_DEBUG=true
export STRIP_KEEP_SYMTAB='*/vmlinux-*'
# /lib/modules/%kernelrelease-%build_flavor/build will be a stale symlink until the
# kernel-devel package is installed. Don't check for stale symlinks
# in the brp-symlink check:
export NO_BRP_STALE_LINK_ERROR=yes
cd %kernel_build_dir
mkdir -p %buildroot/boot
cp -p System.map %buildroot/boot/System.map-%kernelrelease
cp -p arch/x86/boot/bzImage %buildroot/boot/vmlinuz-%kernelrelease
cp .config %buildroot/boot/config-%kernelrelease
%if %install_vdso
# Install the unstripped vdso's that are linked in the kernel image
make vdso_install $MAKE_ARGS INSTALL_MOD_PATH=%buildroot
%endif
# Create a dummy initramfs with roughly the size the real one will have.
# That way, rpm will know that this package requires some additional
# space in /boot.
dd if=/dev/zero of=%buildroot/boot/initramfs-%kernelrelease.img \
bs=1M count=20
gzip -c9 < Module.symvers > %buildroot/boot/symvers-%kernelrelease.gz
make modules_install $MAKE_ARGS INSTALL_MOD_PATH=%buildroot
if [ -d "%_builddir/u2mfn" ]; then
make modules_install $MAKE_ARGS INSTALL_MOD_PATH=%buildroot M=%_builddir/u2mfn
fi
if [ -d "%_builddir/wireguard" ]; then
make modules_install $MAKE_ARGS INSTALL_MOD_PATH=%buildroot M=%_builddir/wireguard/src
fi
if [ -d "%_builddir/macbook12-spi-driver" ]; then
make modules_install $MAKE_ARGS INSTALL_MOD_PATH=%buildroot M=%_builddir/macbook12-spi-driver
fi
mkdir -p %buildroot/%src_install_dir
rm -f %buildroot/lib/modules/%kernelrelease/build
rm -f %buildroot/lib/modules/%kernelrelease/source
mkdir -p %buildroot/lib/modules/%kernelrelease/build
(cd %buildroot/lib/modules/%kernelrelease ; ln -s build source)
# dirs for additional modules per module-init-tools, kbuild/modules.txt
mkdir -p %buildroot/lib/modules/%kernelrelease/extra
mkdir -p %buildroot/lib/modules/%kernelrelease/updates
mkdir -p %buildroot/lib/modules/%kernelrelease/weak-updates
pushd %build_src_dir
cp --parents `find -type f -name "Makefile*" -o -name "Kconfig*"` %buildroot/lib/modules/%kernelrelease/build
cp -a scripts %buildroot/lib/modules/%kernelrelease/build
cp -a --parents arch/x86/include %buildroot/lib/modules/%kernelrelease/build/
cp -a include %buildroot/lib/modules/%kernelrelease/build/include
popd
cp Module.symvers %buildroot/lib/modules/%kernelrelease/build
cp System.map %buildroot/lib/modules/%kernelrelease/build
if [ -s Module.markers ]; then
cp Module.markers %buildroot/lib/modules/%kernelrelease/build
fi
rm -rf %buildroot/lib/modules/%kernelrelease/build/Documentation
# Remove useless scripts that creates ERROR with ambiguous shebang
# that are removed too in Fedora
rm -rf %buildroot/lib/modules/%kernelrelease/build/scripts/tracing
rm -f %buildroot/lib/modules/%kernelrelease/build/scripts/spdxcheck.py
rm -f %buildroot/lib/modules/%kernelrelease/build/scripts/*.o
rm -f %buildroot/lib/modules/%kernelrelease/build/scripts/*/*.o
cp -a scripts/* %buildroot/lib/modules/%kernelrelease/build/scripts/
cp -a include/* %buildroot/lib/modules/%kernelrelease/build/include/
cp -a --parents arch/x86/include/* %buildroot/lib/modules/%kernelrelease/build/
if [ -f tools/objtool/objtool ]; then
cp -a --parents tools/objtool %buildroot/lib/modules/%kernelrelease/build/
pushd %build_src_dir
cp -a --parents tools/objtool %buildroot/lib/modules/%kernelrelease/build/
cp -a --parents tools/build/Build.include %buildroot/lib/modules/%kernelrelease/build/
cp -a --parents tools/build/Build %buildroot/lib/modules/%kernelrelease/build/
cp -a --parents tools/build/fixdep.c %buildroot/lib/modules/%kernelrelease/build/
cp -a --parents tools/scripts/utilities.mak %buildroot/lib/modules/%kernelrelease/build/
cp -a --parents tools/lib/str_error_r.c %buildroot/lib/modules/%kernelrelease/build/
cp -a --parents tools/lib/string.c %buildroot/lib/modules/%kernelrelease/build/
cp -a --parents tools/lib/subcmd/* %buildroot/lib/modules/%kernelrelease/build/
popd
fi
# disable GCC plugins for external modules build, to not fail if different gcc
# version is used
sed -e 's/^\(CONFIG_GCC_PLUGIN.*\)=y/# \1 is not set/' .config > \
%buildroot/lib/modules/%kernelrelease/build/.config
sed -e '/^#define CONFIG_GCC_PLUGIN/d' include/generated/autoconf.h > \
%buildroot/lib/modules/%kernelrelease/build/include/generated/autoconf.h
# Copy .config to include/config/auto.conf so "make prepare" is unnecessary.
cp %buildroot/lib/modules/%kernelrelease/build/.config %buildroot/lib/modules/%kernelrelease/build/include/config/auto.conf
# Make sure the Makefile and version.h have a matching timestamp so that
# external modules can be built
touch -r %buildroot/lib/modules/%kernelrelease/build/Makefile %buildroot/lib/modules/%kernelrelease/build/include/generated/uapi/linux/version.h
touch -r %buildroot/lib/modules/%kernelrelease/build/.config %buildroot/lib/modules/%kernelrelease/build/include/config/auto.conf
touch -r %buildroot/lib/modules/%kernelrelease/build/.config %buildroot/lib/modules/%kernelrelease/build/include/generated/autoconf.h
if test -s vmlinux.id; then
cp vmlinux.id %buildroot/lib/modules/%kernelrelease/build/vmlinux.id
else
echo >&2 "*** WARNING *** no vmlinux build ID! ***"
fi
#
# save the vmlinux file for kernel debugging into the kernel-debuginfo rpm
#
%if %{with_debuginfo}
mkdir -p %buildroot%{debuginfodir}/lib/modules/%kernelrelease
cp vmlinux %buildroot%{debuginfodir}/lib/modules/%kernelrelease
%endif
find %buildroot/lib/modules/%kernelrelease -name "*.ko" -type f >modnames
# mark modules executable so that strip-to-file can strip them
xargs --no-run-if-empty chmod u+x < modnames
# Generate a list of modules for block and networking.
fgrep /drivers/ modnames | xargs --no-run-if-empty nm -upA |
sed -n 's,^.*/\([^/]*\.ko\): *U \(.*\)$,\1 \2,p' > drivers.undef
collect_modules_list()
{
sed -r -n -e "s/^([^ ]+) \\.?($2)\$/\\1/p" drivers.undef |
LC_ALL=C sort -u > %buildroot/lib/modules/%kernelrelease/modules.$1
}
collect_modules_list networking \
'register_netdev|ieee80211_register_hw|usbnet_probe'
collect_modules_list block \
'ata_scsi_ioctl|scsi_add_host|scsi_add_host_with_dma|blk_init_queue|register_mtd_blktrans|scsi_esp_register|scsi_register_device_handler'
collect_modules_list drm \
'drm_open|drm_init'
collect_modules_list modesetting \
'drm_crtc_init'
# detect missing or incorrect license tags
rm -f modinfo
while read i
do
echo -n "${i#%buildroot/lib/modules/%kernelrelease/} " >> modinfo
/sbin/modinfo -l $i >> modinfo
done < modnames
egrep -v \
'GPL( v2)?$|Dual BSD/GPL$|Dual MPL/GPL$|GPL and additional rights$' \
modinfo && exit 1
rm -f modinfo modnames
# Move the devel headers out of the root file system
mkdir -p %buildroot/usr/src/kernels
mv %buildroot/lib/modules/%kernelrelease/build/* %buildroot/%src_install_dir/
mv %buildroot/lib/modules/%kernelrelease/build/.config %buildroot/%src_install_dir
rmdir %buildroot/lib/modules/%kernelrelease/build
ln -sf %src_install_dir %buildroot/lib/modules/%kernelrelease/build
# Abort if there are any undefined symbols
msg="$(/sbin/depmod -F %buildroot/boot/System.map-%kernelrelease \
-b %buildroot -ae %kernelrelease 2>&1)"
if [ $? -ne 0 ] || echo "$msg" | grep 'needs unknown symbol'; then
exit 1
fi
# in case of no firmware built - place empty dir
mkdir -p %buildroot/lib/firmware
mv %buildroot/lib/firmware %buildroot/lib/firmware-all
mkdir -p %buildroot/lib/firmware
mv %buildroot/lib/firmware-all %buildroot/lib/firmware/%kernelrelease
# Prepare initramfs for Qubes VM
mkdir -p %buildroot/%vm_install_dir
PATH="/sbin:$PATH" dracut --nomdadmconf --nolvmconf \
--kmoddir %buildroot/lib/modules/%kernelrelease \
--modules "kernel-modules qubes-vm-simple" \
--conf /dev/null --confdir /var/empty \
-d "xenblk xen-blkfront cdrom ext4 jbd2 crc16 dm_snapshot" \
%buildroot/%vm_install_dir/initramfs %kernelrelease || exit 1
# workaround for buggy dracut-044 in Fedora 25
# https://bugzilla.redhat.com/show_bug.cgi?id=1431317
# https://github.com/dracutdevs/dracut/issues/194
modules_dep=$(lsinitrd "%buildroot/%vm_install_dir/initramfs" \
"usr/lib/modules/%kernelrelease/modules.dep")
if [ -z "$modules_dep" ]; then
tmpdir=$(mktemp -d)
zcat "%buildroot/%vm_install_dir/initramfs" | cpio -imd -D "$tmpdir" || exit 1
mv "$tmpdir"/%buildroot/lib/modules/%kernelrelease/kernel \
"$tmpdir"/lib/modules/%kernelrelease/ || exit 1
depmod -F %buildroot/boot/System.map-%kernelrelease \
-b "$tmpdir" -a %kernelrelease || exit 1
pushd "$tmpdir"
if [ -n "$SOURCE_DATE_EPOCH" ]; then
find . -exec touch --no-dereference --date="@${SOURCE_DATE_EPOCH}" {} +
fi
find . -print0 | sort -z \
| cpio --null -R 0:0 -H newc -o --reproducible --quiet \
| gzip -n > %buildroot/%vm_install_dir/initramfs || exit 1
popd
fi
cp -p arch/x86/boot/bzImage %buildroot/%vm_install_dir/vmlinuz
# default kernel options for this kernel
def_kernelopts="root=/dev/mapper/dmroot ro nomodeset console=hvc0"
def_kernelopts="$def_kernelopts rd_NO_PLYMOUTH rd.plymouth.enable=0 plymouth.enable=0"
if [ -e /usr/lib/dracut/modules.d/90qubes-vm-simple/xen-scrub-pages-supported ]; then
# set xen_scrub_pages=0 _only_ when included initramfs does support
# re-enabling it
def_kernelopts="$def_kernelopts xen_scrub_pages=0"
fi
echo "$def_kernelopts " > %buildroot/%vm_install_dir/default-kernelopts-common.txt
# Modules for Qubes VM
mkdir -p %buildroot%vm_install_dir/modules
cp -a %buildroot/lib/modules/%kernelrelease %buildroot%vm_install_dir/modules/
mkdir -p %buildroot%vm_install_dir/modules/firmware
cp -a %buildroot/lib/firmware/%kernelrelease %buildroot%vm_install_dir/modules/firmware/
# Include kernel headers for Qubes VM in "/lib/modules" - so kernel-devel
# package will be unnecessary there, regardless of distribution
rm -f %buildroot%vm_install_dir/modules/%kernelrelease/build
cp -a %buildroot/%src_install_dir %buildroot%vm_install_dir/modules/%kernelrelease/build
%if 0%{?fedora} >= 25
# include kernel+initramfs also inside modules.img, for direct kernel boot with
# stubdomain
cp %buildroot%vm_install_dir/vmlinuz %buildroot%vm_install_dir/modules/
cp %buildroot%vm_install_dir/initramfs %buildroot%vm_install_dir/modules/
if [ -n "$SOURCE_DATE_EPOCH" ]; then
find %buildroot%vm_install_dir/modules \
-exec touch --no-dereference --date="@${SOURCE_DATE_EPOCH}" {} +
fi
PATH="/sbin:$PATH" mkfs.ext3 -d %buildroot%vm_install_dir/modules \
-U dcee2318-92bd-47a5-a15d-e79d1412cdce \
%buildroot%vm_install_dir/modules.img 1024M
rm -rf %buildroot%vm_install_dir/modules
%endif
# remove files that will be auto generated by depmod at rpm -i time
for i in alias alias.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap
do
rm -f %buildroot/lib/modules/%kernelrelease/modules.$i
done
%post
/sbin/depmod -a %{kernelrelease}
%posttrans
# with kernel-4.14+ plymouth detects hvc0 serial console and forces text boot
# we simply make plymouth ignore it to recover the splash screen
if [ -f /etc/default/grub ]; then
if ! grep -q plymouth.ignore-serial-consoles /etc/default/grub; then
echo 'GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX plymouth.ignore-serial-consoles"' >> /etc/default/grub
fi
fi
if [ -f /boot/efi/EFI/qubes/xen.cfg ]; then
if ! grep -q plymouth.ignore-serial-consoles /boot/efi/EFI/qubes/xen.cfg; then
sed -i 's/kernel=.*/& plymouth.ignore-serial-consoles/g' /boot/efi/EFI/qubes/xen.cfg
fi
fi
/bin/kernel-install add %{kernelrelease} /boot/vmlinuz-%{kernelrelease} || exit $?
# grubby (used by new-kernel-pkg) do not understand xen entries in grub2 config
if [ -x /sbin/new-kernel-pkg -a -e /boot/grub2/grub.cfg ]; then
grub2-mkconfig > /boot/grub2/grub.cfg
fi
%preun
/bin/kernel-install remove %{kernelrelease} /boot/vmlinuz-%{kernelrelease} || exit $?
%files
%defattr(-, root, root)
%ghost /boot/initramfs-%{kernelrelease}.img
/boot/System.map-%{kernelrelease}
/boot/config-%{kernelrelease}
/boot/symvers-%kernelrelease.gz
%attr(0644, root, root) /boot/vmlinuz-%{kernelrelease}
/lib/firmware/%{kernelrelease}
/lib/modules/%{kernelrelease}
%package devel
Summary: Development files necessary for building kernel modules
License: GPL v2 only
Group: Development/Sources
Provides: multiversion(kernel)
Provides: %name-devel = %kernelrelease
%if "%{?name_suffix}" != ""
Provides: kernel-devel = %kernelrelease
%endif
Provides: kernel-devel-uname-r = %kernelrelease
Requires: elfutils-libelf-devel
AutoReqProv: on
%description devel
This package contains files necessary for building kernel modules (and
kernel module packages) against the kernel.
%post devel
if [ -f /etc/sysconfig/kernel ]
then
. /etc/sysconfig/kernel || exit $?
fi
if [ "$HARDLINK" != "no" -a -x /usr/sbin/hardlink ]
then
(cd /usr/src/kernels/%{kernelrelease} &&
/usr/bin/find . -type f | while read f; do
hardlink -c /usr/src/kernels/*.fc*.*/$f $f
done)
fi
%files devel
%defattr(-,root,root)
/usr/src/kernels/%{kernelrelease}
%package qubes-vm
Summary: The Xen Kernel
Version: %{version}
Release: %{rel}
License: GPL v2 only
Group: System/Kernel
Url: http://www.kernel.org/
AutoReqProv: on
BuildRequires: coreutils module-init-tools sparse
Provides: multiversion(kernel-qubes-vm)
Provides: kernel-xen-domU
Provides: kernel-qubes-domU
Requires(pre): coreutils gawk
Requires(post): dracut
Requires(post): qubes-core-dom0
Conflicts: sysfsutils < 2.0
# root-lvm only works with newer udevs
Conflicts: udev < 118
Conflicts: lvm2 < 2.02.33
Provides: kernel-qubes-vm = %kernelrelease
%description qubes-vm
Qubes domU kernel.
%post qubes-vm
%if 0%{?fedora} < 25
mkdir /tmp/qubes-modules-%kernelrelease
truncate -s 500M /tmp/qubes-modules-%kernelrelease.img
mkfs -t ext3 -F /tmp/qubes-modules-%kernelrelease.img > /dev/null
mount /tmp/qubes-modules-%kernelrelease.img /tmp/qubes-modules-%kernelrelease -o loop
cp -a -t /tmp/qubes-modules-%kernelrelease %vm_install_dir/modules/%kernelrelease
mkdir /tmp/qubes-modules-%kernelrelease/firmware
cp -a -t /tmp/qubes-modules-%kernelrelease/firmware %vm_install_dir/modules/firmware/%kernelrelease
cp %vm_install_dir/vmlinuz /tmp/qubes-modules-%kernelrelease/
cp %vm_install_dir/initramfs /tmp/qubes-modules-%kernelrelease/
umount /tmp/qubes-modules-%kernelrelease
rmdir /tmp/qubes-modules-%kernelrelease
mv /tmp/qubes-modules-%kernelrelease.img %vm_install_dir/modules.img
%endif
current_default="$(qubes-prefs default-kernel)"
current_default_path="/var/lib/qubes/vm-kernels/$current_default"
current_default_package="$(rpm --qf '%{NAME}' -qf "$current_default_path")"
if [ "$current_default_package" = "%{name}-qubes-vm" ]; then
# Set kernel as default VM kernel if we are the default package.
# If qubes-prefs isn't installed yet, the default kernel will be set by %post
# of qubes-core-dom0
type qubes-prefs &>/dev/null && qubes-prefs --set default-kernel %upstream_version-%plainrel
fi
exit 0
%preun qubes-vm
if [ "`qubes-prefs -g default-kernel`" == "%upstream_version-%plainrel" ]; then
echo "This kernel version is set as default VM kernel, cannot remove"
exit 1
fi
if qvm-ls --kernel | grep -qw "%upstream_version-%plainrel"; then
echo "This kernel version is used by at least one VM, cannot remove"
exit 1
fi
exit 0
%files qubes-vm
%defattr(-, root, root)
%dir %vm_install_dir
%if 0%{?fedora} < 25
%ghost %attr(0644, root, root) %vm_install_dir/modules.img
%else
%attr(0644, root, root) %vm_install_dir/modules.img
%endif
%attr(0644, root, root) %vm_install_dir/initramfs
%attr(0644, root, root) %vm_install_dir/vmlinuz
%if 0%{?fedora} < 25
%vm_install_dir/modules
%endif
%attr(0644, root, root) %vm_install_dir/default-kernelopts-common.txt
%changelog
@CHANGELOG@

View File

@ -1,37 +0,0 @@
#! /bin/bash
# The modules_sign target checks for corresponding .o files for every .ko that
# is signed. This doesn't work for package builds which re-use the same build
# directory for every flavour, and the .config may change between flavours.
# So instead of using this script to just sign lib/modules/$KernelVer/extra,
# sign all .ko in the buildroot.
# This essentially duplicates the 'modules_sign' Kbuild target and runs the
# same commands for those modules.
MODSECKEY=$1
MODPUBKEY=$2
moddir=$3
modules=`find $moddir -type f -name '*.ko'`
NPROC=`nproc`
[ -z "$NPROC" ] && NPROC=1
# NB: this loop runs 2000+ iterations. Try to be fast.
echo "$modules" | xargs -r -n16 -P $NPROC sh -c "
for mod; do
./scripts/sign-file sha256 $MODSECKEY $MODPUBKEY \$mod
rm -f \$mod.sig \$mod.dig
done
" DUMMYARG0 # xargs appends ARG1 ARG2..., which go into $mod in for loop.
RANDOMMOD=$(echo "$modules" | sort -R | head -n 1)
if [ "~Module signature appended~" != "$(tail -c 28 $RANDOMMOD)" ]; then
echo "*****************************"
echo "*** Modules are unsigned! ***"
echo "*****************************"
exit 1
fi
exit 0

View File

@ -0,0 +1,64 @@
From: John Johansen <john.johansen@canonical.com>
Date: Tue, 20 Jul 2010 06:57:08 -0700
Subject: AppArmor: Allow dfa backward compatibility with broken userspace
Patch-mainline: 2.6.37?
The apparmor_parser when compiling policy could generate invalid dfas
that did not have sufficient padding to avoid invalid references, when
used by the kernel. The kernels check to verify the next/check table
size was broken meaning invalid dfas were being created by userspace
and not caught.
To remain compatible with old tools that are not fixed, pad the loaded
dfas next/check table. The dfa's themselves are valid except for the
high padding for potentially invalid transitions (high bounds error),
which have a maximimum is 256 entries. So just allocate an extra null filled
256 entries for the next/check tables. This will guarentee all bounds
are good and invalid transitions go to the null (0) state.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Jeff Mahoney <jeffm@suse.com>
---
security/apparmor/match.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -57,8 +57,17 @@ static struct table_header *unpack_table
if (bsize < tsize)
goto out;
+ /* Pad table allocation for next/check by 256 entries to remain
+ * backwards compatible with old (buggy) tools and remain safe without
+ * run time checks
+ */
+ if (th.td_id == YYTD_ID_NXT || th.td_id == YYTD_ID_CHK)
+ tsize += 256 * th.td_flags;
+
table = kvmalloc(tsize);
if (table) {
+ /* ensure the pad is clear, else there will be errors */
+ memset(table, 0, tsize);
*table = th;
if (th.td_flags == YYTD_DATA8)
UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
@@ -134,11 +143,19 @@ static int verify_dfa(struct aa_dfa *dfa
goto out;
if (flags & DFA_FLAG_VERIFY_STATES) {
+ int warning = 0;
for (i = 0; i < state_count; i++) {
if (DEFAULT_TABLE(dfa)[i] >= state_count)
goto out;
/* TODO: do check that DEF state recursion terminates */
if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
+ if (warning)
+ continue;
+ printk(KERN_WARNING "AppArmor DFA next/check "
+ "upper bounds error fixed, upgrade "
+ "user space tools \n");
+ warning = 1;
+ } else if (BASE_TABLE(dfa)[i] >= trans_count) {
printk(KERN_ERR "AppArmor DFA next/check upper "
"bounds error\n");
goto out;

View File

@ -0,0 +1,379 @@
From: John Johansen <john.johansen@canonical.com>
Date: Thu, 22 Jul 2010 02:32:02 -0700
Subject: AppArmor: compatibility patch for v5 interface
Patch-mainline: 2.6.37?
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Jeff Mahoney <jeffm@suse.com>
---
security/apparmor/Kconfig | 9 +
security/apparmor/Makefile | 2
security/apparmor/apparmorfs-24.c | 287 +++++++++++++++++++++++++++++++++
security/apparmor/apparmorfs.c | 18 +-
security/apparmor/include/apparmorfs.h | 6
5 files changed, 320 insertions(+), 2 deletions(-)
create mode 100644 security/apparmor/apparmorfs-24.c
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
boot.
If you are unsure how to answer this question, answer 1.
+
+config SECURITY_APPARMOR_COMPAT_24
+ bool "Enable AppArmor 2.4 compatability"
+ depends on SECURITY_APPARMOR
+ default y
+ help
+ This option enables compatability with AppArmor 2.4. It is
+ recommended if compatability with older versions of AppArmor
+ is desired.
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -6,6 +6,8 @@ apparmor-y := apparmorfs.o audit.o capab
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
resource.o sid.o file.o net.o
+apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
+
clean-files: capability_names.h af_names.h
quiet_cmd_make-caps = GEN $@
--- /dev/null
+++ b/security/apparmor/apparmorfs-24.c
@@ -0,0 +1,287 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ *
+ * This file contain functions providing an interface for <= AppArmor 2.4
+ * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
+ * being set (see Makefile).
+ */
+
+#include <linux/security.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/namei.h>
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/policy.h"
+
+
+/* apparmor/matching */
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
+ "user::other";
+
+ return simple_read_from_buffer(buf, size, ppos, matching,
+ sizeof(matching) - 1);
+}
+
+const struct file_operations aa_fs_matching_fops = {
+ .read = aa_matching_read,
+};
+
+/* apparmor/features */
+static ssize_t aa_features_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char features[] = "file=3.1 capability=2.0 network=1.0 "
+ "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
+
+ return simple_read_from_buffer(buf, size, ppos, features,
+ sizeof(features) - 1);
+}
+
+const struct file_operations aa_fs_features_fops = {
+ .read = aa_features_read,
+};
+
+/**
+ * __next_namespace - find the next namespace to list
+ * @root: root namespace to stop search at (NOT NULL)
+ * @ns: current ns position (NOT NULL)
+ *
+ * Find the next namespace from @ns under @root and handle all locking needed
+ * while switching current namespace.
+ *
+ * Returns: next namespace or NULL if at last namespace under @root
+ * NOTE: will not unlock root->lock
+ */
+static struct aa_namespace *__next_namespace(struct aa_namespace *root,
+ struct aa_namespace *ns)
+{
+ struct aa_namespace *parent;
+
+ /* is next namespace a child */
+ if (!list_empty(&ns->sub_ns)) {
+ struct aa_namespace *next;
+ next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
+ read_lock(&next->lock);
+ return next;
+ }
+
+ /* check if the next ns is a sibling, parent, gp, .. */
+ parent = ns->parent;
+ while (parent) {
+ read_unlock(&ns->lock);
+ list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
+ read_lock(&ns->lock);
+ return ns;
+ }
+ if (parent == root)
+ return NULL;
+ ns = parent;
+ parent = parent->parent;
+ }
+
+ return NULL;
+}
+
+/**
+ * __first_profile - find the first profile in a namespace
+ * @root: namespace that is root of profiles being displayed (NOT NULL)
+ * @ns: namespace to start in (NOT NULL)
+ *
+ * Returns: unrefcounted profile or NULL if no profile
+ */
+static struct aa_profile *__first_profile(struct aa_namespace *root,
+ struct aa_namespace *ns)
+{
+ for ( ; ns; ns = __next_namespace(root, ns)) {
+ if (!list_empty(&ns->base.profiles))
+ return list_first_entry(&ns->base.profiles,
+ struct aa_profile, base.list);
+ }
+ return NULL;
+}
+
+/**
+ * __next_profile - step to the next profile in a profile tree
+ * @profile: current profile in tree (NOT NULL)
+ *
+ * Perform a depth first taversal on the profile tree in a namespace
+ *
+ * Returns: next profile or NULL if done
+ * Requires: profile->ns.lock to be held
+ */
+static struct aa_profile *__next_profile(struct aa_profile *p)
+{
+ struct aa_profile *parent;
+ struct aa_namespace *ns = p->ns;
+
+ /* is next profile a child */
+ if (!list_empty(&p->base.profiles))
+ return list_first_entry(&p->base.profiles, typeof(*p),
+ base.list);
+
+ /* is next profile a sibling, parent sibling, gp, subling, .. */
+ parent = p->parent;
+ while (parent) {
+ list_for_each_entry_continue(p, &parent->base.profiles,
+ base.list)
+ return p;
+ p = parent;
+ parent = parent->parent;
+ }
+
+ /* is next another profile in the namespace */
+ list_for_each_entry_continue(p, &ns->base.profiles, base.list)
+ return p;
+
+ return NULL;
+}
+
+/**
+ * next_profile - step to the next profile in where ever it may be
+ * @root: root namespace (NOT NULL)
+ * @profile: current profile (NOT NULL)
+ *
+ * Returns: next profile or NULL if there isn't one
+ */
+static struct aa_profile *next_profile(struct aa_namespace *root,
+ struct aa_profile *profile)
+{
+ struct aa_profile *next = __next_profile(profile);
+ if (next)
+ return next;
+
+ /* finished all profiles in namespace move to next namespace */
+ return __first_profile(root, __next_namespace(root, profile->ns));
+}
+
+/**
+ * p_start - start a depth first traversal of profile tree
+ * @f: seq_file to fill
+ * @pos: current position
+ *
+ * Returns: first profile under current namespace or NULL if none found
+ *
+ * acquires first ns->lock
+ */
+static void *p_start(struct seq_file *f, loff_t *pos)
+ __acquires(root->lock)
+{
+ struct aa_profile *profile = NULL;
+ struct aa_namespace *root = aa_current_profile()->ns;
+ loff_t l = *pos;
+ f->private = aa_get_namespace(root);
+
+
+ /* find the first profile */
+ read_lock(&root->lock);
+ profile = __first_profile(root, root);
+
+ /* skip to position */
+ for (; profile && l > 0; l--)
+ profile = next_profile(root, profile);
+
+ return profile;
+}
+
+/**
+ * p_next - read the next profile entry
+ * @f: seq_file to fill
+ * @p: profile previously returned
+ * @pos: current position
+ *
+ * Returns: next profile after @p or NULL if none
+ *
+ * may acquire/release locks in namespace tree as necessary
+ */
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
+{
+ struct aa_profile *profile = p;
+ struct aa_namespace *root = f->private;
+ (*pos)++;
+
+ return next_profile(root, profile);
+}
+
+/**
+ * p_stop - stop depth first traversal
+ * @f: seq_file we are filling
+ * @p: the last profile writen
+ *
+ * Release all locking done by p_start/p_next on namespace tree
+ */
+static void p_stop(struct seq_file *f, void *p)
+ __releases(root->lock)
+{
+ struct aa_profile *profile = p;
+ struct aa_namespace *root = f->private, *ns;
+
+ if (profile) {
+ for (ns = profile->ns; ns && ns != root; ns = ns->parent)
+ read_unlock(&ns->lock);
+ }
+ read_unlock(&root->lock);
+ aa_put_namespace(root);
+}
+
+/**
+ * seq_show_profile - show a profile entry
+ * @f: seq_file to file
+ * @p: current position (profile) (NOT NULL)
+ *
+ * Returns: error on failure
+ */
+static int seq_show_profile(struct seq_file *f, void *p)
+{
+ struct aa_profile *profile = (struct aa_profile *)p;
+ struct aa_namespace *root = f->private;
+
+ if (profile->ns != root)
+ seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
+ seq_printf(f, "%s (%s)\n", profile->base.hname,
+ COMPLAIN_MODE(profile) ? "complain" : "enforce");
+
+ return 0;
+}
+
+static const struct seq_operations aa_fs_profiles_op = {
+ .start = p_start,
+ .next = p_next,
+ .stop = p_stop,
+ .show = seq_show_profile,
+};
+
+static int profiles_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &aa_fs_profiles_op);
+}
+
+static int profiles_release(struct inode *inode, struct file *file)
+{
+ return seq_release(inode, file);
+}
+
+const struct file_operations aa_fs_profiles_fops = {
+ .open = profiles_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = profiles_release,
+};
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -182,7 +182,11 @@ void __init aa_destroy_aafs(void)
aafs_remove(".remove");
aafs_remove(".replace");
aafs_remove(".load");
-
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ aafs_remove("profiles");
+ aafs_remove("matching");
+ aafs_remove("features");
+#endif
securityfs_remove(aa_fs_dentry);
aa_fs_dentry = NULL;
}
@@ -213,7 +217,17 @@ int __init aa_create_aafs(void)
aa_fs_dentry = NULL;
goto error;
}
-
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+ error = aafs_create("matching", 0444, &aa_fs_matching_fops);
+ if (error)
+ goto error;
+ error = aafs_create("features", 0444, &aa_fs_features_fops);
+ if (error)
+ goto error;
+#endif
+ error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
+ if (error)
+ goto error;
error = aafs_create(".load", 0640, &aa_fs_profile_load);
if (error)
goto error;
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -17,4 +17,10 @@
extern void __init aa_destroy_aafs(void);
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+extern const struct file_operations aa_fs_matching_fops;
+extern const struct file_operations aa_fs_features_fops;
+extern const struct file_operations aa_fs_profiles_fops;
+#endif
+
#endif /* __AA_APPARMORFS_H */

View File

@ -0,0 +1,518 @@
From: John Johansen <john.johansen@canonical.com>
Date: Mon, 4 Oct 2010 15:03:36 -0700
Subject: AppArmor: compatibility patch for v5 network control
Patch-mainline: 2.6.37?
Add compatibility for v5 network rules.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Jeff Mahoney <jeffm@suse.com>
---
include/linux/lsm_audit.h | 4
security/apparmor/Makefile | 6 +
security/apparmor/include/net.h | 40 ++++++++
security/apparmor/include/policy.h | 3
security/apparmor/lsm.c | 112 ++++++++++++++++++++++
security/apparmor/net.c | 170 ++++++++++++++++++++++++++++++++++
security/apparmor/policy.c | 1
security/apparmor/policy_unpack.c | 48 +++++++++
8 files changed, 381 insertions(+), 2 deletions(-)
create mode 100644 security/apparmor/include/net.h
create mode 100644 security/apparmor/net.c
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -123,6 +123,10 @@ struct common_audit_data {
u32 denied;
uid_t ouid;
} fs;
+ struct {
+ int type, protocol;
+ struct sock *sk;
+ } net;
};
} apparmor_audit_data;
#endif
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -4,17 +4,21 @@ obj-$(CONFIG_SECURITY_APPARMOR) += appar
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
- resource.o sid.o file.o
+ resource.o sid.o file.o net.o
clean-files: capability_names.h af_names.h
quiet_cmd_make-caps = GEN $@
cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
+quiet_cmd_make-af = GEN $@
+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
+
quiet_cmd_make-rlim = GEN $@
cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@
$(obj)/capability.o : $(obj)/capability_names.h
+$(obj)/net.o : $(obj)/af_names.h
$(obj)/resource.o : $(obj)/rlim_names.h
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
$(call cmd,make-caps)
--- /dev/null
+++ b/security/apparmor/include/net.h
@@ -0,0 +1,40 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * 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, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_NET_H
+#define __AA_NET_H
+
+#include <net/sock.h>
+
+/* struct aa_net - network confinement data
+ * @allowed: basic network families permissions
+ * @audit_network: which network permissions to force audit
+ * @quiet_network: which network permissions to quiet rejects
+ */
+struct aa_net {
+ u16 allow[AF_MAX];
+ u16 audit[AF_MAX];
+ u16 quiet[AF_MAX];
+};
+
+extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
+ int type, int protocol, struct sock *sk);
+extern int aa_revalidate_sk(int op, struct sock *sk);
+
+static inline void aa_free_net_rules(struct aa_net *new)
+{
+ /* NOP */
+}
+
+#endif /* __AA_NET_H */
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -27,6 +27,7 @@
#include "capability.h"
#include "domain.h"
#include "file.h"
+#include "net.h"
#include "resource.h"
extern const char *profile_mode_names[];
@@ -145,6 +146,7 @@ struct aa_namespace {
* @size: the memory consumed by this profiles rules
* @file: The set of rules governing basic file access and domain transitions
* @caps: capabilities for the profile
+ * @net: network controls for the profile
* @rlimits: rlimits for the profile
*
* The AppArmor profile contains the basic confinement data. Each profile
@@ -181,6 +183,7 @@ struct aa_profile {
struct aa_file_rules file;
struct aa_caps caps;
+ struct aa_net net;
struct aa_rlimit rlimits;
};
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -31,6 +31,7 @@
#include "include/context.h"
#include "include/file.h"
#include "include/ipc.h"
+#include "include/net.h"
#include "include/path.h"
#include "include/policy.h"
#include "include/procattr.h"
@@ -619,6 +620,104 @@ static int apparmor_task_setrlimit(struc
return error;
}
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ if (kern)
+ return 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
+ NULL);
+ return error;
+}
+
+static int apparmor_socket_bind(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_BIND, sk);
+}
+
+static int apparmor_socket_connect(struct socket *sock,
+ struct sockaddr *address, int addrlen)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_CONNECT, sk);
+}
+
+static int apparmor_socket_listen(struct socket *sock, int backlog)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_LISTEN, sk);
+}
+
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_ACCEPT, sk);
+}
+
+static int apparmor_socket_sendmsg(struct socket *sock,
+ struct msghdr *msg, int size)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SENDMSG, sk);
+}
+
+static int apparmor_socket_recvmsg(struct socket *sock,
+ struct msghdr *msg, int size, int flags)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_RECVMSG, sk);
+}
+
+static int apparmor_socket_getsockname(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETSOCKNAME, sk);
+}
+
+static int apparmor_socket_getpeername(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETPEERNAME, sk);
+}
+
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_GETSOCKOPT, sk);
+}
+
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
+ int optname)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SETSOCKOPT, sk);
+}
+
+static int apparmor_socket_shutdown(struct socket *sock, int how)
+{
+ struct sock *sk = sock->sk;
+
+ return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
+}
+
static struct security_operations apparmor_ops = {
.name = "apparmor",
@@ -650,6 +749,19 @@ static struct security_operations apparm
.getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr,
+ .socket_create = apparmor_socket_create,
+ .socket_bind = apparmor_socket_bind,
+ .socket_connect = apparmor_socket_connect,
+ .socket_listen = apparmor_socket_listen,
+ .socket_accept = apparmor_socket_accept,
+ .socket_sendmsg = apparmor_socket_sendmsg,
+ .socket_recvmsg = apparmor_socket_recvmsg,
+ .socket_getsockname = apparmor_socket_getsockname,
+ .socket_getpeername = apparmor_socket_getpeername,
+ .socket_getsockopt = apparmor_socket_getsockopt,
+ .socket_setsockopt = apparmor_socket_setsockopt,
+ .socket_shutdown = apparmor_socket_shutdown,
+
.cred_alloc_blank = apparmor_cred_alloc_blank,
.cred_free = apparmor_cred_free,
.cred_prepare = apparmor_cred_prepare,
--- /dev/null
+++ b/security/apparmor/net.c
@@ -0,0 +1,170 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * 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, version 2 of the
+ * License.
+ */
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/net.h"
+#include "include/policy.h"
+
+#include "af_names.h"
+
+static const char *sock_type_names[] = {
+ "unknown(0)",
+ "stream",
+ "dgram",
+ "raw",
+ "rdm",
+ "seqpacket",
+ "dccp",
+ "unknown(7)",
+ "unknown(8)",
+ "unknown(9)",
+ "packet",
+};
+
+/* audit callback for net specific fields */
+static void audit_cb(struct audit_buffer *ab, void *va)
+{
+ struct common_audit_data *sa = va;
+
+ audit_log_format(ab, " family=");
+ if (address_family_names[sa->u.net.family]) {
+ audit_log_string(ab, address_family_names[sa->u.net.family]);
+ } else {
+ audit_log_format(ab, " \"unknown(%d)\"", sa->u.net.family);
+ }
+
+ audit_log_format(ab, " sock_type=");
+ if (sock_type_names[sa->aad.net.type]) {
+ audit_log_string(ab, sock_type_names[sa->aad.net.type]);
+ } else {
+ audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type);
+ }
+
+ audit_log_format(ab, " protocol=%d", sa->aad.net.protocol);
+}
+
+/**
+ * audit_net - audit network access
+ * @profile: profile being enforced (NOT NULL)
+ * @op: operation being checked
+ * @family: network family
+ * @type: network type
+ * @protocol: network protocol
+ * @sk: socket auditing is being applied to
+ * @error: error code for failure else 0
+ *
+ * Returns: %0 or sa->error else other errorcode on failure
+ */
+static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
+ int protocol, struct sock *sk, int error)
+{
+ int audit_type = AUDIT_APPARMOR_AUTO;
+ struct common_audit_data sa;
+ if (sk) {
+ COMMON_AUDIT_DATA_INIT(&sa, NET);
+ } else {
+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ }
+ /* todo fill in socket addr info */
+
+ sa.aad.op = op,
+ sa.u.net.family = family;
+ sa.u.net.sk = sk;
+ sa.aad.net.type = type;
+ sa.aad.net.protocol = protocol;
+ sa.aad.error = error;
+
+ if (likely(!sa.aad.error)) {
+ u16 audit_mask = profile->net.audit[sa.u.net.family];
+ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
+ !(1 << sa.aad.net.type & audit_mask)))
+ return 0;
+ audit_type = AUDIT_APPARMOR_AUDIT;
+ } else {
+ u16 quiet_mask = profile->net.quiet[sa.u.net.family];
+ u16 kill_mask = 0;
+ u16 denied = (1 << sa.aad.net.type) & ~quiet_mask;
+
+ if (denied & kill_mask)
+ audit_type = AUDIT_APPARMOR_KILL;
+
+ if ((denied & quiet_mask) &&
+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
+ AUDIT_MODE(profile) != AUDIT_ALL)
+ return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
+ }
+
+ return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
+}
+
+/**
+ * aa_net_perm - very course network access check
+ * @op: operation being checked
+ * @profile: profile being enforced (NOT NULL)
+ * @family: network family
+ * @type: network type
+ * @protocol: network protocol
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
+ int protocol, struct sock *sk)
+{
+ u16 family_mask;
+ int error;
+
+ if ((family < 0) || (family >= AF_MAX))
+ return -EINVAL;
+
+ if ((type < 0) || (type >= SOCK_MAX))
+ return -EINVAL;
+
+ /* unix domain and netlink sockets are handled by ipc */
+ if (family == AF_UNIX || family == AF_NETLINK)
+ return 0;
+
+ family_mask = profile->net.allow[family];
+
+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
+
+ return audit_net(profile, op, family, type, protocol, sk, error);
+}
+
+/**
+ * aa_revalidate_sk - Revalidate access to a sock
+ * @op: operation being checked
+ * @sk: sock being revalidated (NOT NULL)
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_revalidate_sk(int op, struct sock *sk)
+{
+ struct aa_profile *profile;
+ int error = 0;
+
+ /* aa_revalidate_sk should not be called from interrupt context
+ * don't mediate these calls as they are not task related
+ */
+ if (in_interrupt())
+ return 0;
+
+ profile = __aa_current_profile();
+ if (!unconfined(profile))
+ error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
+ sk->sk_protocol, sk);
+
+ return error;
+}
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -745,6 +745,7 @@ static void free_profile(struct aa_profi
aa_free_file_rules(&profile->file);
aa_free_cap_rules(&profile->caps);
+ aa_free_net_rules(&profile->net);
aa_free_rlimit_rules(&profile->rlimits);
aa_free_sid(profile->sid);
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -190,6 +190,19 @@ fail:
return 0;
}
+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
+{
+ if (unpack_nameX(e, AA_U16, name)) {
+ if (!inbounds(e, sizeof(u16)))
+ return 0;
+ if (data)
+ *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
+ e->pos += sizeof(u16);
+ return 1;
+ }
+ return 0;
+}
+
static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
{
if (unpack_nameX(e, AA_U32, name)) {
@@ -468,7 +481,8 @@ static struct aa_profile *unpack_profile
{
struct aa_profile *profile = NULL;
const char *name = NULL;
- int error = -EPROTO;
+ size_t size = 0;
+ int i, error = -EPROTO;
kernel_cap_t tmpcap;
u32 tmp;
@@ -559,6 +573,38 @@ static struct aa_profile *unpack_profile
if (!unpack_rlimits(e, profile))
goto fail;
+ size = unpack_array(e, "net_allowed_af");
+ if (size) {
+
+ for (i = 0; i < size; i++) {
+ /* discard extraneous rules that this kernel will
+ * never request
+ */
+ if (i > AF_MAX) {
+ u16 tmp;
+ if (!unpack_u16(e, &tmp, NULL) ||
+ !unpack_u16(e, &tmp, NULL) ||
+ !unpack_u16(e, &tmp, NULL))
+ goto fail;
+ continue;
+ }
+ if (!unpack_u16(e, &profile->net.allow[i], NULL))
+ goto fail;
+ if (!unpack_u16(e, &profile->net.audit[i], NULL))
+ goto fail;
+ if (!unpack_u16(e, &profile->net.quiet[i], NULL))
+ goto fail;
+ }
+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ /*
+ * allow unix domain and netlink sockets they are handled
+ * by IPC
+ */
+ }
+ profile->net.allow[AF_UNIX] = 0xffff;
+ profile->net.allow[AF_NETLINK] = 0xffff;
+
/* get file rules */
profile->file.dfa = unpack_dfa(e);
if (IS_ERR(profile->file.dfa)) {

View File

@ -0,0 +1,24 @@
From: Jeff Mahoney <jeffm@suse.com>
Subject: acpi: export acpi_os_hotplug_execute
Patch-mainline: not yet
The ACPI dock driver changes require acpi_os_hotplug_execute,
which wasn't exported.
This patch exports it.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
drivers/acpi/osl.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -941,6 +941,7 @@ acpi_status acpi_os_hotplug_execute(acpi
{
return __acpi_os_execute(0, function, context, 1);
}
+EXPORT_SYMBOL(acpi_os_hotplug_execute);
void acpi_os_wait_events_complete(void *context)
{

View File

@ -0,0 +1,67 @@
From: Alexey Starikovskiy <astarikovskiy@suse.de>
Subject: ACPI: EC: Don't degrade to poll mode at storm automatically.
References: bnc#446142
Patch-Mainline: no
Signed-off-by: Thomas Renninger <trenn@suse.de>
Not all users of semi-broken EC devices want to degrade to poll mode, so
give them right to choose.
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
---
Documentation/kernel-parameters.txt | 5 +++++
drivers/acpi/ec.c | 15 +++++++++++++++
2 files changed, 20 insertions(+)
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -691,6 +691,11 @@ and is between 256 and 4096 characters.
eata= [HW,SCSI]
+ ec_intr= [HW,ACPI] ACPI Embedded Controller interrupt mode
+ Format: <int>
+ 0: polling mode
+ non-0: interrupt mode (default)
+
edd= [EDD]
Format: {"off" | "on" | "skip[mbr]"}
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -118,6 +118,8 @@ static struct acpi_ec {
spinlock_t curr_lock;
} *boot_ec, *first_ec;
+int acpi_ec_intr = 1; /* Default is interrupt mode */
+
static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
/* --------------------------------------------------------------------------
@@ -754,6 +756,8 @@ static int ec_install_handlers(struct ac
&acpi_ec_gpe_handler, ec);
if (ACPI_FAILURE(status))
return -ENODEV;
+ if (!acpi_ec_intr)
+ set_bit(EC_FLAGS_NO_GPE, &ec->flags);
acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
acpi_enable_gpe(NULL, ec->gpe);
status = acpi_install_address_space_handler(ec->handle,
@@ -1034,3 +1038,14 @@ static void __exit acpi_ec_exit(void)
return;
}
#endif /* 0 */
+
+static int __init acpi_ec_set_intr_mode(char *str)
+{
+ if (!get_option(&str, &acpi_ec_intr)) {
+ acpi_ec_intr = 0;
+ return 0;
+ }
+ return 1;
+}
+
+__setup("ec_intr=", acpi_ec_set_intr_mode);

View File

@ -0,0 +1,30 @@
From: Thomas Renninger <trenn@suse.de>
Subject: Only use 32 bit addresses if they have a valid length
References: bug#581644
Patch-Mainline: not yet
Also not sure whether it will help, but it's a fix.
Please remove this patch again after a while also if it's not
mainline.
---
drivers/acpi/acpica/tbfadt.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -550,11 +550,12 @@ static void acpi_tb_validate_fadt(void)
(!address64->address && length)) {
ACPI_WARNING((AE_INFO,
"Optional field %s has zero address or length: "
- "0x%8.8X%8.8X/0x%X",
+ "0x%8.8X%8.8X/0x%X - not using it",
name,
ACPI_FORMAT_UINT64(address64->
address),
length));
+ address64->address = 0;
}
}
}

View File

@ -0,0 +1,59 @@
From: Kurt Garloff <garloff@suse.de>
Subject: Use SRAT table rev to use 8bit or 16/32bit PXM fields (ia64)
References: bnc#503038
Patch-mainline: not yet
In SRAT v1, we had 8bit proximity domain (PXM) fields; SRAT v2 provides
32bits for these. The new fields were reserved before.
According to the ACPI spec, the OS must disregrard reserved fields.
ia64 did handle the PXM fields almost consistently, but depending on
sgi's sn2 platform. This patch leaves the sn2 logic in, but does also
use 16/32 bits for PXM if the SRAT has rev 2 or higher.
The patch also adds __init to the two pxm accessor functions, as they
access __initdata now and are called from an __init function only anyway.
Note that the code only uses 16 bits for the PXM field in the processor
proximity field; the patch does not address this as 16 bits are more than
enough.
This is patch 3/3.
Signed-off-by: Kurt Garloff <garloff@suse.de>
---
arch/ia64/kernel/acpi.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -429,22 +429,24 @@ static u32 __devinitdata pxm_flag[PXM_FL
static struct acpi_table_slit __initdata *slit_table;
cpumask_t early_cpu_possible_map = CPU_MASK_NONE;
-static int get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
+static int __init
+get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
{
int pxm;
pxm = pa->proximity_domain_lo;
- if (ia64_platform_is("sn2"))
+ if (ia64_platform_is("sn2") || acpi_srat_revision >= 2)
pxm += pa->proximity_domain_hi[0] << 8;
return pxm;
}
-static int get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma)
+static int __init
+get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma)
{
int pxm;
pxm = ma->proximity_domain;
- if (!ia64_platform_is("sn2"))
+ if (!ia64_platform_is("sn2") && acpi_srat_revision <= 1)
pxm &= 0xff;
return pxm;

View File

@ -0,0 +1,52 @@
From: Kurt Garloff <garloff@suse.de>
Subject: Store SRAT table revision
References: bnc#503038
Patch-mainline: not yet
In SRAT v1, we had 8bit proximity domain (PXM) fields; SRAT v2 provides
32bits for these. The new fields were reserved before.
According to the ACPI spec, the OS must disregrard reserved fields.
In order to know whether or not, we must know what version the SRAT
table has.
This patch stores the SRAT table revision for later consumption
by arch specific __init functions.
This is patch 1/3.
Signed-off-by: Kurt Garloff <garloff@suse.de>
---
drivers/acpi/numa.c | 3 +++
include/acpi/acpi_numa.h | 1 +
2 files changed, 4 insertions(+)
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -45,6 +45,8 @@ static int pxm_to_node_map[MAX_PXM_DOMAI
static int node_to_pxm_map[MAX_NUMNODES]
= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
+unsigned char acpi_srat_revision __initdata;
+
int pxm_to_node(int pxm)
{
if (pxm < 0)
@@ -259,6 +261,7 @@ static int __init acpi_parse_srat(struct
return -EINVAL;
/* Real work done in acpi_table_parse_srat below. */
+ acpi_srat_revision = table->revision;
return 0;
}
--- a/include/acpi/acpi_numa.h
+++ b/include/acpi/acpi_numa.h
@@ -15,6 +15,7 @@ extern int pxm_to_node(int);
extern int node_to_pxm(int);
extern void __acpi_map_pxm_to_node(int, int);
extern int acpi_map_pxm_to_node(int);
+extern unsigned char acpi_srat_revision;
#endif /* CONFIG_ACPI_NUMA */
#endif /* __ACP_NUMA_H */

View File

@ -0,0 +1,42 @@
From: Kurt Garloff <garloff@suse.de>
Subject: Use SRAT table rev to use 8bit or 32bit PXM fields (x86-64)
References: bnc#503038
Patch-mainline: not yet
In SRAT v1, we had 8bit proximity domain (PXM) fields; SRAT v2 provides
32bits for these. The new fields were reserved before.
According to the ACPI spec, the OS must disregrard reserved fields.
x86-64 was rather inconsistent prior to this patch; it used 8 bits
for the pxm field in cpu_affinity, but 32 bits in mem_affinity.
This patch makes it consistent: Either use 8 bits consistently (SRAT
rev 1 or lower) or 32 bits (SRAT rev 2 or higher).
This is patch 2/3.
Signed-off-by: Kurt Garloff <garloff@suse.de>
---
arch/x86/mm/srat_64.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -156,6 +156,8 @@ acpi_numa_processor_affinity_init(struct
if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0)
return;
pxm = pa->proximity_domain_lo;
+ if (acpi_srat_revision >= 2)
+ pxm |= *((unsigned int*)pa->proximity_domain_hi) << 8;
node = setup_node(pxm);
if (node < 0) {
printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
@@ -259,6 +261,8 @@ acpi_numa_memory_affinity_init(struct ac
start = ma->base_address;
end = start + ma->length;
pxm = ma->proximity_domain;
+ if (acpi_srat_revision <= 1)
+ pxm &= 0xff;
node = setup_node(pxm);
if (node < 0) {
printk(KERN_ERR "SRAT: Too many proximity domains.\n");

View File

@ -0,0 +1,125 @@
From: Thomas Renninger <trenn@suse.de>
Subject: Avoid critical temp shutdowns on specific ThinkPad T4x(p) and R40
References: https://bugzilla.novell.com/show_bug.cgi?id=333043
Patch-mainline: not yet
---
drivers/acpi/thermal.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -41,6 +41,7 @@
#include <linux/kmod.h>
#include <linux/reboot.h>
#include <linux/device.h>
+#include <linux/dmi.h>
#include <asm/uaccess.h>
#include <linux/thermal.h>
#include <acpi/acpi_bus.h>
@@ -984,6 +985,86 @@ static void acpi_thermal_guess_offset(st
tz->kelvin_offset = 2732;
}
+static struct dmi_system_id thermal_psv_dmi_table[] = {
+ {
+ .ident = "IBM ThinkPad T41",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T41"),
+ },
+ },
+ {
+ .ident = "IBM ThinkPad T42",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T42"),
+ },
+ },
+ {
+ .ident = "IBM ThinkPad T43",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T43"),
+ },
+ },
+ {
+ .ident = "IBM ThinkPad T41p",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T41p"),
+ },
+ },
+ {
+ .ident = "IBM ThinkPad T42p",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T42p"),
+ },
+ },
+ {
+ .ident = "IBM ThinkPad T43p",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T43p"),
+ },
+ },
+ {
+ .ident = "IBM ThinkPad R40",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad R40"),
+ },
+ },
+ {
+ .ident = "IBM ThinkPad R50p",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad R50p"),
+ },
+ },
+ {},
+};
+
+static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
+{
+ if (!tz)
+ return -EINVAL;
+
+ /* Convert value to deci-seconds */
+ tz->polling_frequency = seconds * 10;
+
+ tz->thermal_zone->polling_delay = seconds * 1000;
+
+ if (tz->tz_enabled)
+ thermal_zone_device_update(tz->thermal_zone);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Polling frequency set to %lu seconds\n",
+ tz->polling_frequency/10));
+
+ return 0;
+}
+
static int acpi_thermal_add(struct acpi_device *device)
{
int result = 0;
@@ -1015,6 +1096,18 @@ static int acpi_thermal_add(struct acpi_
if (result)
goto free_memory;
+ if (dmi_check_system(thermal_psv_dmi_table)) {
+ if (tz->trips.passive.flags.valid &&
+ tz->trips.passive.temperature > CELSIUS_TO_KELVIN(85)) {
+ printk (KERN_INFO "Adjust passive trip point from %lu"
+ " to %lu\n",
+ KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
+ KELVIN_TO_CELSIUS(tz->trips.passive.temperature - 150));
+ tz->trips.passive.temperature -= 150;
+ acpi_thermal_set_polling(tz, 5);
+ }
+ }
+
printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
acpi_device_name(device), acpi_device_bid(device),
KELVIN_TO_CELSIUS(tz->temperature));

View File

@ -0,0 +1,118 @@
From: Thomas Renninger <trenn@suse.de>
Subject: Introduce acpi_root_table=rsdt boot param and dmi list to force rsdt
Patch-mainline: not yet
References: http://bugzilla.kernel.org/show_bug.cgi?id=8246
This one is part of a patch series:
acpi_thinkpad_introduce_acpi_root_table_boot_param.patch
acpi_thinkpad_introduce_acpica_rsdt_global_variable.patch
acpi_thinkpad_remove_R40e_c-state_blacklist.patch
Blacklist R40e, R51e and T40, T40p, T41, T41p, T42, T42p, R50 and R50p
ThinkPads to use the RSDT instead of the XSDT.
Update: Jan 12 2009 jeffm
* 2.6.29-rc1 introduced acpi_rsdt_forced. I've updated the patch to issue
a warning that acpi=rsdt is the prefered method of forcing.
* Moved the dmi table stuff to the main dmi table in x86/kernel/acpi/boot.
Update: Apr 10 2009 jeffm
* Removed documentation, since it's deprecated.
Signed-off-by: Thomas Renninger <trenn@suse.de>
Tested-by: Mark Doughty <me@markdoughty.co.uk>
CC: Yakui Zhao <yakui.zhao@intel.com>
---
arch/x86/kernel/acpi/boot.c | 53 ++++++++++++++++++++++++++++++++++++++++++++
drivers/acpi/tables.c | 3 ++
2 files changed, 56 insertions(+)
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1350,6 +1350,21 @@ static int __init dmi_ignore_irq0_timer_
return 0;
}
+static int __init force_acpi_rsdt(const struct dmi_system_id *d)
+{
+ if (!acpi_force) {
+ printk(KERN_NOTICE "%s detected: force use of acpi=rsdt\n",
+ d->ident);
+ acpi_rsdt_forced = 1;
+ } else {
+ printk(KERN_NOTICE
+ "Warning: acpi=force overrules DMI blacklist: "
+ "acpi=rsdt\n");
+ }
+ return 0;
+
+}
+
/*
* If your system is blacklisted here, but you find that acpi=force
* works for you, please contact linux-acpi@vger.kernel.org
@@ -1425,6 +1440,32 @@ static struct dmi_system_id __initdata a
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
},
},
+
+ /*
+ * Boxes that need RSDT as ACPI root table
+ */
+ {
+ .callback = force_acpi_rsdt,
+ .ident = "ThinkPad ", /* R40e, broken C-states */
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION, "1SET")},
+ },
+ {
+ .callback = force_acpi_rsdt,
+ .ident = "ThinkPad ", /* R50e, slow booting */
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION, "1WET")},
+ },
+ {
+ .callback = force_acpi_rsdt,
+ .ident = "ThinkPad ", /* T40, T40p, T41, T41p, T42, T42p
+ R50, R50p */
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION, "1RET")},
+ },
{}
};
@@ -1612,6 +1653,18 @@ static int __init parse_acpi(char *arg)
}
early_param("acpi", parse_acpi);
+/* Alias for acpi=rsdt for compatibility with openSUSE 11.1 and SLE11 */
+static int __init parse_acpi_root_table(char *opt)
+{
+ if (!strcmp(opt, "rsdt")) {
+ acpi_rsdt_forced = 1;
+ printk(KERN_WARNING "acpi_root_table=rsdt is deprecated. "
+ "Please use acpi=rsdt instead.\n");
+ }
+ return 0;
+}
+early_param("acpi_root_table", parse_acpi_root_table);
+
/* FIXME: Using pci= for an ACPI parameter is a travesty. */
static int __init parse_pci(char *arg)
{
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -339,6 +339,9 @@ int __init acpi_table_init(void)
{
acpi_status status;
+ if (acpi_rsdt_forced)
+ printk(KERN_INFO "Using RSDT as ACPI root table\n");
+
status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
if (ACPI_FAILURE(status))
return 1;

View File

@ -0,0 +1,15 @@
From: jbeulich@novell.com
Subject: fix unwind annotations
Patch-mainline: queued for 2.6.39
--- head-2011-02-17.orig/arch/x86/lib/semaphore_32.S 2011-03-01 15:03:45.000000000 +0100
+++ head-2011-02-17/arch/x86/lib/semaphore_32.S 2011-03-01 15:04:50.000000000 +0100
@@ -36,7 +36,7 @@
*/
#ifdef CONFIG_SMP
ENTRY(__write_lock_failed)
- CFI_STARTPROC simple
+ CFI_STARTPROC
FRAME
2: LOCK_PREFIX
addl $ RW_LOCK_BIAS,(%eax)

View File

@ -0,0 +1,603 @@
From: Russ Anderson <rja@sgi.com>
Subject: ia64: Call migration code on correctable errors v8
References: 415829
Acked-by: schwab@suse.de
Patch-mainline: not yet
Migrate data off pages with correctable memory errors. This patch is the
ia64 specific piece. It connects the CPE handler to the page migration
code. It is implemented as a kernel loadable module, similar to the mca
recovery code (mca_recovery.ko). This allows the feature to be turned off
by uninstalling the module.
Update Jan 19 2009 jeffm:
- isolate_lru_page doesn't put the page on a list anymore
Signed-off-by: Russ Anderson <rja@sgi.com>
---
arch/ia64/Kconfig | 9
arch/ia64/include/asm/mca.h | 6
arch/ia64/include/asm/page.h | 1
arch/ia64/kernel/Makefile | 1
arch/ia64/kernel/cpe_migrate.c | 434 +++++++++++++++++++++++++++++++++++++++++
arch/ia64/kernel/mca.c | 37 +++
6 files changed, 487 insertions(+), 1 deletion(-)
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -511,6 +511,15 @@ config ARCH_PROC_KCORE_TEXT
config IA64_MCA_RECOVERY
tristate "MCA recovery from errors other than TLB."
+config IA64_CPE_MIGRATE
+ tristate "Migrate data off pages with correctable errors"
+ default m
+ help
+ Migrate data off pages with correctable memory errors. Selecting
+ Y will build this functionality into the kernel. Selecting M will
+ build this functionality as a kernel loadable module. Installing
+ the module will turn on the functionality.
+
config PERFMON
bool "Performance monitor support"
help
--- a/arch/ia64/include/asm/mca.h
+++ b/arch/ia64/include/asm/mca.h
@@ -142,6 +142,7 @@ extern unsigned long __per_cpu_mca[NR_CP
extern int cpe_vector;
extern int ia64_cpe_irq;
+extern int cpe_poll_enabled;
extern void ia64_mca_init(void);
extern void ia64_mca_cpu_init(void *);
extern void ia64_os_mca_dispatch(void);
@@ -156,11 +157,16 @@ extern void ia64_slave_init_handler(void
extern void ia64_mca_cmc_vector_setup(void);
extern int ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *));
extern void ia64_unreg_MCA_extension(void);
+extern int ia64_reg_CE_extension(int (*fn)(void *));
+extern void ia64_unreg_CE_extension(void);
extern unsigned long ia64_get_rnat(unsigned long *);
extern void ia64_set_psr_mc(void);
extern void ia64_mca_printk(const char * fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+extern struct list_head badpagelist;
+extern unsigned int total_badpages;
+
struct ia64_mca_notify_die {
struct ia64_sal_os_state *sos;
int *monarch_cpu;
--- a/arch/ia64/include/asm/page.h
+++ b/arch/ia64/include/asm/page.h
@@ -121,6 +121,7 @@ extern unsigned long max_low_pfn;
#endif
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
+#define phys_to_page(kaddr) (pfn_to_page(kaddr >> PAGE_SHIFT))
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_PERFMON) += perfmon_defaul
obj-$(CONFIG_IA64_CYCLONE) += cyclone.o
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
+obj-$(CONFIG_IA64_CPE_MIGRATE) += cpe_migrate.o
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
--- /dev/null
+++ b/arch/ia64/kernel/cpe_migrate.c
@@ -0,0 +1,434 @@
+/*
+ * File: cpe_migrate.c
+ * Purpose: Migrate data from physical pages with excessive correctable
+ * errors to new physical pages. Keep the old pages on a discard
+ * list.
+ *
+ * Copyright (C) 2008 SGI - Silicon Graphics Inc.
+ * Copyright (C) 2008 Russ Anderson <rja@sgi.com>
+ */
+
+#include <linux/sysdev.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/workqueue.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/vmalloc.h>
+#include <linux/migrate.h>
+#include <linux/page-isolation.h>
+#include <linux/memcontrol.h>
+#include <linux/kobject.h>
+
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/mca.h>
+
+#define BADRAM_BASENAME "badram"
+#define CE_HISTORY_LENGTH 30
+
+struct cpe_info {
+ u64 paddr;
+ u16 node;
+};
+static struct cpe_info cpe[CE_HISTORY_LENGTH];
+
+static int cpe_polling_enabled = 1;
+static int cpe_head;
+static int cpe_tail;
+static int work_scheduled;
+static int mstat_cannot_isolate;
+static int mstat_failed_to_discard;
+static int mstat_already_marked;
+static int mstat_already_on_list;
+
+DEFINE_SPINLOCK(cpe_migrate_lock);
+
+static void
+get_physical_address(void *buffer, u64 *paddr, u16 *node)
+{
+ sal_log_record_header_t *rh;
+ sal_log_mem_dev_err_info_t *mdei;
+ ia64_err_rec_t *err_rec;
+ sal_log_platform_err_info_t *plat_err;
+ efi_guid_t guid;
+
+ err_rec = buffer;
+ rh = &err_rec->sal_elog_header;
+ *paddr = 0;
+ *node = 0;
+
+ /*
+ * Make sure it is a corrected error.
+ */
+ if (rh->severity != sal_log_severity_corrected)
+ return;
+
+ plat_err = (sal_log_platform_err_info_t *)&err_rec->proc_err;
+
+ guid = plat_err->mem_dev_err.header.guid;
+ if (efi_guidcmp(guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) {
+ /*
+ * Memory cpe
+ */
+ mdei = &plat_err->mem_dev_err;
+ if (mdei->valid.oem_data) {
+ if (mdei->valid.physical_addr)
+ *paddr = mdei->physical_addr;
+
+ if (mdei->valid.node) {
+ if (ia64_platform_is("sn2"))
+ *node = nasid_to_cnodeid(mdei->node);
+ else
+ *node = mdei->node;
+ }
+ }
+ }
+}
+
+static struct page *
+alloc_migrate_page(struct page *ignored, unsigned long node, int **x)
+{
+
+ return alloc_pages_node(node, GFP_HIGHUSER_MOVABLE, 0);
+}
+
+static int
+validate_paddr_page(u64 paddr)
+{
+ struct page *page;
+
+ if (!paddr)
+ return -EINVAL;
+
+ if (!ia64_phys_addr_valid(paddr))
+ return -EINVAL;
+
+ if (!pfn_valid(paddr >> PAGE_SHIFT))
+ return -EINVAL;
+
+ page = phys_to_page(paddr);
+ if (PageMemError(page))
+ mstat_already_marked++;
+ return 0;
+}
+
+extern int isolate_lru_page(struct page *);
+static int
+ia64_mca_cpe_move_page(u64 paddr, u32 node)
+{
+ LIST_HEAD(pagelist);
+ struct page *page;
+ int ret;
+
+ ret = validate_paddr_page(paddr);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * convert physical address to page number
+ */
+ page = phys_to_page(paddr);
+
+ migrate_prep();
+ ret = isolate_lru_page(page);
+ if (ret) {
+ mstat_cannot_isolate++;
+ return ret;
+ }
+
+ list_add(&page->lru, &pagelist);
+ ret = migrate_pages(&pagelist, alloc_migrate_page, node, 0, true);
+ if (ret == 0) {
+ total_badpages++;
+ list_add_tail(&page->lru, &badpagelist);
+ } else {
+ mstat_failed_to_discard++;
+ /*
+ * The page failed to migrate and is not on the bad page list.
+ * Clearing the error bit will allow another attempt to migrate
+ * if it gets another correctable error.
+ */
+ ClearPageMemError(page);
+ }
+
+ return 0;
+}
+
+/*
+ * ia64_mca_cpe_migrate
+ * The worker that does the actual migration. It pulls a
+ * physical address off the list and calls the migration code.
+ */
+static void
+ia64_mca_cpe_migrate(struct work_struct *unused)
+{
+ int ret;
+ u64 paddr;
+ u16 node;
+
+ do {
+ paddr = cpe[cpe_tail].paddr;
+ if (paddr) {
+ /*
+ * There is a valid entry that needs processing.
+ */
+ node = cpe[cpe_tail].node;
+
+ ret = ia64_mca_cpe_move_page(paddr, node);
+ if (ret <= 0)
+ /*
+ * Even though the return status is negative,
+ * clear the entry. If the same address has
+ * another CPE it will be re-added to the list.
+ */
+ cpe[cpe_tail].paddr = 0;
+
+ }
+ if (++cpe_tail >= CE_HISTORY_LENGTH)
+ cpe_tail = 0;
+
+ } while (cpe_tail != cpe_head);
+ work_scheduled = 0;
+}
+
+static DECLARE_WORK(cpe_enable_work, ia64_mca_cpe_migrate);
+DEFINE_SPINLOCK(cpe_list_lock);
+
+/*
+ * cpe_setup_migrate
+ * Get the physical address out of the CPE record, add it
+ * to the list of addresses to migrate (if not already on),
+ * and schedule the back end worker task. This is called
+ * in interrupt context so cannot directly call the migration
+ * code.
+ *
+ * Inputs
+ * rec The CPE record
+ * Outputs
+ * 1 on Success, -1 on failure
+ */
+static int
+cpe_setup_migrate(void *rec)
+{
+ u64 paddr;
+ u16 node;
+ /* int head, tail; */
+ int i, ret;
+
+ if (!rec)
+ return -EINVAL;
+
+ get_physical_address(rec, &paddr, &node);
+ ret = validate_paddr_page(paddr);
+ if (ret < 0)
+ return -EINVAL;
+
+ if ((cpe_head != cpe_tail) || (cpe[cpe_head].paddr != 0))
+ /*
+ * List not empty
+ */
+ for (i = 0; i < CE_HISTORY_LENGTH; i++) {
+ if (PAGE_ALIGN(cpe[i].paddr) == PAGE_ALIGN(paddr)) {
+ mstat_already_on_list++;
+ return 1; /* already on the list */
+ }
+ }
+
+ if (!spin_trylock(&cpe_list_lock)) {
+ /*
+ * Someone else has the lock. To avoid spinning in interrupt
+ * handler context, bail.
+ */
+ return 1;
+ }
+
+ if (cpe[cpe_head].paddr == 0) {
+ cpe[cpe_head].node = node;
+ cpe[cpe_head].paddr = paddr;
+
+ if (++cpe_head >= CE_HISTORY_LENGTH)
+ cpe_head = 0;
+ }
+ spin_unlock(&cpe_list_lock);
+
+ if (!work_scheduled) {
+ work_scheduled = 1;
+ schedule_work(&cpe_enable_work);
+ }
+
+ return 1;
+}
+
+/*
+ * =============================================================================
+ */
+
+/*
+ * free_one_bad_page
+ * Free one page from the list of bad pages.
+ */
+static int
+free_one_bad_page(unsigned long paddr)
+{
+ LIST_HEAD(pagelist);
+ struct page *page, *page2, *target;
+
+ /*
+ * Verify page address
+ */
+ target = phys_to_page(paddr);
+ list_for_each_entry_safe(page, page2, &badpagelist, lru) {
+ if (page != target)
+ continue;
+
+ ClearPageMemError(page); /* Mark the page as good */
+ total_badpages--;
+ list_move_tail(&page->lru, &pagelist);
+ putback_lru_pages(&pagelist);
+ break;
+ }
+ return 0;
+}
+
+/*
+ * free_all_bad_pages
+ * Free all of the pages on the bad pages list.
+ */
+static int
+free_all_bad_pages(void)
+{
+ struct page *page, *page2;
+
+ list_for_each_entry_safe(page, page2, &badpagelist, lru) {
+ ClearPageMemError(page); /* Mark the page as good */
+ total_badpages--;
+ }
+ putback_lru_pages(&badpagelist);
+ return 0;
+}
+
+#define OPT_LEN 16
+
+static ssize_t
+badpage_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ char optstr[OPT_LEN];
+ unsigned long opt;
+ int len = OPT_LEN;
+ int err;
+
+ if (count < len)
+ len = count;
+
+ strlcpy(optstr, buf, len);
+
+ err = strict_strtoul(optstr, 16, &opt);
+ if (err)
+ return err;
+
+ if (opt == 0)
+ free_all_bad_pages();
+ else
+ free_one_bad_page(opt);
+
+ return count;
+}
+
+/*
+ * badpage_show
+ * Display the number, size, and addresses of all the pages on the
+ * bad page list.
+ *
+ * Note that sysfs provides buf of PAGE_SIZE length. bufend tracks
+ * the remaining space in buf to avoid overflowing.
+ */
+static ssize_t
+badpage_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+
+{
+ struct page *page, *page2;
+ int i = 0, cnt = 0;
+ char *bufend = buf + PAGE_SIZE;
+
+ cnt = snprintf(buf, bufend - (buf + cnt),
+ "Memory marked bad: %d kB\n"
+ "Pages marked bad: %d\n"
+ "Unable to isolate on LRU: %d\n"
+ "Unable to migrate: %d\n"
+ "Already marked bad: %d\n"
+ "Already on list: %d\n"
+ "List of bad physical pages\n",
+ total_badpages << (PAGE_SHIFT - 10), total_badpages,
+ mstat_cannot_isolate, mstat_failed_to_discard,
+ mstat_already_marked, mstat_already_on_list
+ );
+
+ list_for_each_entry_safe(page, page2, &badpagelist, lru) {
+ if (bufend - (buf + cnt) < 20)
+ break; /* Avoid overflowing the buffer */
+ cnt += snprintf(buf + cnt, bufend - (buf + cnt),
+ " 0x%011lx", page_to_phys(page));
+ if (!(++i % 5))
+ cnt += snprintf(buf + cnt, bufend - (buf + cnt), "\n");
+ }
+ cnt += snprintf(buf + cnt, bufend - (buf + cnt), "\n");
+
+ return cnt;
+}
+
+static struct kobj_attribute badram_attr = {
+ .attr = {
+ .name = "badram",
+ .mode = S_IWUSR | S_IRUGO,
+ },
+ .show = badpage_show,
+ .store = badpage_store,
+};
+
+static int __init
+cpe_migrate_external_handler_init(void)
+{
+ int error;
+
+ error = sysfs_create_file(kernel_kobj, &badram_attr.attr);
+ if (error)
+ return -EINVAL;
+
+ /*
+ * register external ce handler
+ */
+ if (ia64_reg_CE_extension(cpe_setup_migrate)) {
+ printk(KERN_ERR "ia64_reg_CE_extension failed.\n");
+ return -EFAULT;
+ }
+ cpe_poll_enabled = cpe_polling_enabled;
+
+ printk(KERN_INFO "Registered badram Driver\n");
+ return 0;
+}
+
+static void __exit
+cpe_migrate_external_handler_exit(void)
+{
+ /* unregister external mca handlers */
+ ia64_unreg_CE_extension();
+
+ sysfs_remove_file(kernel_kobj, &badram_attr.attr);
+}
+
+module_init(cpe_migrate_external_handler_init);
+module_exit(cpe_migrate_external_handler_exit);
+
+module_param(cpe_polling_enabled, int, 0644);
+MODULE_PARM_DESC(cpe_polling_enabled,
+ "Enable polling with migration");
+
+MODULE_AUTHOR("Russ Anderson <rja@sgi.com>");
+MODULE_DESCRIPTION("ia64 Corrected Error page migration driver");
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -68,6 +68,9 @@
*
* 2007-04-27 Russ Anderson <rja@sgi.com>
* Support multiple cpus going through OS_MCA in the same event.
+ *
+ * 2008-04-22 Russ Anderson <rja@sgi.com>
+ * Migrate data off pages with correctable memory errors.
*/
#include <linux/jiffies.h>
#include <linux/types.h>
@@ -164,7 +167,14 @@ static int cmc_polling_enabled = 1;
* but encounters problems retrieving CPE logs. This should only be
* necessary for debugging.
*/
-static int cpe_poll_enabled = 1;
+int cpe_poll_enabled = 1;
+EXPORT_SYMBOL(cpe_poll_enabled);
+
+unsigned int total_badpages;
+EXPORT_SYMBOL(total_badpages);
+
+LIST_HEAD(badpagelist);
+EXPORT_SYMBOL(badpagelist);
extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe);
@@ -524,6 +534,28 @@ int mca_recover_range(unsigned long addr
}
EXPORT_SYMBOL_GPL(mca_recover_range);
+/* Function pointer to Corrected Error memory migration driver */
+int (*ia64_mca_ce_extension)(void *);
+
+int
+ia64_reg_CE_extension(int (*fn)(void *))
+{
+ if (ia64_mca_ce_extension)
+ return 1;
+
+ ia64_mca_ce_extension = fn;
+ return 0;
+}
+EXPORT_SYMBOL(ia64_reg_CE_extension);
+
+void
+ia64_unreg_CE_extension(void)
+{
+ if (ia64_mca_ce_extension)
+ ia64_mca_ce_extension = NULL;
+}
+EXPORT_SYMBOL(ia64_unreg_CE_extension);
+
#ifdef CONFIG_ACPI
int cpe_vector = -1;
@@ -535,6 +567,7 @@ ia64_mca_cpe_int_handler (int cpe_irq, v
static unsigned long cpe_history[CPE_HISTORY_LENGTH];
static int index;
static DEFINE_SPINLOCK(cpe_history_lock);
+ int recover;
IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n",
__func__, cpe_irq, smp_processor_id());
@@ -581,6 +614,8 @@ ia64_mca_cpe_int_handler (int cpe_irq, v
out:
/* Get the CPE error record and log it */
ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
+ recover = (ia64_mca_ce_extension && ia64_mca_ce_extension(
+ IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_CPE)));
return IRQ_HANDLED;
}

View File

@ -0,0 +1,159 @@
From: Russ Anderson <rja@sgi.com>
Subject: ia64: cpe_migrate.ko causes deadlock.
References: bnc#464676
Patch-mainline: not yet, depends on patches.arch/ia64-page-migration
schedule_on_each_cpu() deadlocks when called from an event thread.
Change cpe_migrate to use a kthread to avoid the problem.
Signed-off-by: Russ Anderson <rja@sgi.com>
Acked-by: Raymund Will <rw@suse.de>
---
arch/ia64/kernel/cpe_migrate.c | 72 +++++++++++++++++++++++++++++++----------
1 file changed, 56 insertions(+), 16 deletions(-)
--- a/arch/ia64/kernel/cpe_migrate.c
+++ b/arch/ia64/kernel/cpe_migrate.c
@@ -22,6 +22,7 @@
#include <linux/page-isolation.h>
#include <linux/memcontrol.h>
#include <linux/kobject.h>
+#include <linux/kthread.h>
#include <asm/page.h>
#include <asm/system.h>
@@ -40,12 +41,15 @@ static struct cpe_info cpe[CE_HISTORY_LE
static int cpe_polling_enabled = 1;
static int cpe_head;
static int cpe_tail;
-static int work_scheduled;
static int mstat_cannot_isolate;
static int mstat_failed_to_discard;
static int mstat_already_marked;
static int mstat_already_on_list;
+/* IRQ handler notifies this wait queue on receipt of an IRQ */
+DECLARE_WAIT_QUEUE_HEAD(cpe_activate_IRQ_wq);
+static DECLARE_COMPLETION(kthread_cpe_migrated_exited);
+int cpe_active;
DEFINE_SPINLOCK(cpe_migrate_lock);
static void
@@ -160,12 +164,12 @@ ia64_mca_cpe_move_page(u64 paddr, u32 no
}
/*
- * ia64_mca_cpe_migrate
- * The worker that does the actual migration. It pulls a
- * physical address off the list and calls the migration code.
+ * cpe_process_queue
+ * Pulls the physical address off the list and calls the migration code.
+ * Will process all the addresses on the list.
*/
-static void
-ia64_mca_cpe_migrate(struct work_struct *unused)
+void
+cpe_process_queue(void)
{
int ret;
u64 paddr;
@@ -193,10 +197,36 @@ ia64_mca_cpe_migrate(struct work_struct
cpe_tail = 0;
} while (cpe_tail != cpe_head);
- work_scheduled = 0;
+ return;
+}
+
+inline int
+cpe_list_empty(void)
+{
+ return (cpe_head == cpe_tail) && (!cpe[cpe_head].paddr);
+}
+
+/*
+ * kthread_cpe_migrate
+ * kthread_cpe_migrate is created at module load time and lives
+ * until the module is removed. When not active, it will sleep.
+ */
+static int
+kthread_cpe_migrate(void *ignore)
+{
+ while (cpe_active) {
+ /*
+ * wait for work
+ */
+ (void)wait_event_interruptible(cpe_activate_IRQ_wq,
+ (!cpe_list_empty() ||
+ !cpe_active));
+ cpe_process_queue(); /* process work */
+ }
+ complete(&kthread_cpe_migrated_exited);
+ return 0;
}
-static DECLARE_WORK(cpe_enable_work, ia64_mca_cpe_migrate);
DEFINE_SPINLOCK(cpe_list_lock);
/*
@@ -228,10 +258,7 @@ cpe_setup_migrate(void *rec)
if (ret < 0)
return -EINVAL;
- if ((cpe_head != cpe_tail) || (cpe[cpe_head].paddr != 0))
- /*
- * List not empty
- */
+ if (!cpe_list_empty())
for (i = 0; i < CE_HISTORY_LENGTH; i++) {
if (PAGE_ALIGN(cpe[i].paddr) == PAGE_ALIGN(paddr)) {
mstat_already_on_list++;
@@ -256,10 +283,7 @@ cpe_setup_migrate(void *rec)
}
spin_unlock(&cpe_list_lock);
- if (!work_scheduled) {
- work_scheduled = 1;
- schedule_work(&cpe_enable_work);
- }
+ wake_up_interruptible(&cpe_activate_IRQ_wq);
return 1;
}
@@ -396,12 +420,23 @@ static int __init
cpe_migrate_external_handler_init(void)
{
int error;
+ struct task_struct *kthread;
error = sysfs_create_file(kernel_kobj, &badram_attr.attr);
if (error)
return -EINVAL;
/*
+ * set up the kthread
+ */
+ cpe_active = 1;
+ kthread = kthread_run(kthread_cpe_migrate, NULL, "cpe_migrate");
+ if (IS_ERR(kthread)) {
+ complete(&kthread_cpe_migrated_exited);
+ return -EFAULT;
+ }
+
+ /*
* register external ce handler
*/
if (ia64_reg_CE_extension(cpe_setup_migrate)) {
@@ -420,6 +455,11 @@ cpe_migrate_external_handler_exit(void)
/* unregister external mca handlers */
ia64_unreg_CE_extension();
+ /* Stop kthread */
+ cpe_active = 0; /* tell kthread_cpe_migrate to exit */
+ wake_up_interruptible(&cpe_activate_IRQ_wq);
+ wait_for_completion(&kthread_cpe_migrated_exited);
+
sysfs_remove_file(kernel_kobj, &badram_attr.attr);
}

View File

@ -0,0 +1,54 @@
From: Jeff Mahoney <jeffm@suse.com>
Subject: kmsg: Fix parameter limitations
Patch-mainline: Whenever kmsg is upstream
The kmsg infrastructure, currently only employed on s/390, has limitations
with the parameters it can handle due to the way it assembles the
magic string for parsing with scripts/kmsg-doc.
cpp expects the result to be a valid expression and exits with an error
if it is not.
The netfilter ipvs code causes this error, though there are more examples:
error: pasting "_ARGS_" and "&" does not give a valid preprocessing token
This stems from an otherwise valid expression:
pr_info("Registered protocols (%s)\n", &protocols[2]);
It tries to concatenate _ARGS_ and &protocols[2] and fails.
This patch fixes the issue by stringifying the entire parameter list
and allowing kmsg-doc to unquote the resultant expression.
The dev_* expressions that evaluate to __KMSG_DEV are unaffected because
the insertion of the "dev, " between _ARGS_ and the parameter list ends
up creating a valid expression.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
include/linux/printk.h | 2 +-
scripts/kmsg-doc | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -416,7 +416,7 @@ extern int hex_to_bin(char ch);
/* generate magic string for scripts/kmsg-doc to parse */
#define pr_printk_hash(level, format, ...) \
- __KMSG_PRINT(level _FMT_ format _ARGS_ ##__VA_ARGS__ _END_)
+ __KMSG_PRINT(level _FMT_ format _ARGS_ #__VA_ARGS__ _END_)
#elif defined(CONFIG_KMSG_IDS) && defined(KMSG_COMPONENT)
--- a/scripts/kmsg-doc
+++ b/scripts/kmsg-doc
@@ -307,7 +307,7 @@ sub process_cpp_file($$$$)
while (<FD>) {
chomp;
- if (/.*__KMSG_PRINT\(\s*(\S*)\s*_FMT_(.*)_ARGS_\s*(.*)?_END_\s*\)/o) {
+ if (/.*__KMSG_PRINT\(\s*(\S*)\s*_FMT_(.*)_ARGS_\s*"(.*)"\s*_END_\s*\)/o) {
if ($component ne "") {
add_kmsg_print($component, $1, $2, $3);
} else {

View File

@ -0,0 +1,139 @@
From: Alexander Graf <agraf@suse.de>
Date: Wed, 18 Nov 2009 00:39:12 +0100
Subject: Only export selected pv-ops feature structs
References: bnc#556135, FATE#306453
Patch-Mainline: Submitted to virtualization list
To really check for sure that we're not using any pv-ops code by accident,
we should make sure that we don't even export the structures used to access
pv-ops exported functions.
So let's surround the pv-ops structs by #ifdefs.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/x86/kernel/paravirt.c | 35 +++++++++++++++++++++++++++++------
1 file changed, 29 insertions(+), 6 deletions(-)
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -124,11 +124,21 @@ static void *get_call_destination(u8 typ
{
struct paravirt_patch_template tmpl = {
.pv_init_ops = pv_init_ops,
+#ifdef CONFIG_PARAVIRT_TIME
.pv_time_ops = pv_time_ops,
+#endif
+#ifdef CONFIG_PARAVIRT_CPU
.pv_cpu_ops = pv_cpu_ops,
+#endif
+#ifdef CONFIG_PARAVIRT_IRQ
.pv_irq_ops = pv_irq_ops,
+#endif
+#ifdef CONFIG_PARAVIRT_APIC
.pv_apic_ops = pv_apic_ops,
+#endif
+#ifdef CONFIG_PARAVIRT_MMU
.pv_mmu_ops = pv_mmu_ops,
+#endif
#ifdef CONFIG_PARAVIRT_SPINLOCKS
.pv_lock_ops = pv_lock_ops,
#endif
@@ -185,6 +195,7 @@ unsigned paravirt_patch_insns(void *insn
return insn_len;
}
+#ifdef CONFIG_PARAVIRT_MMU
static void native_flush_tlb(void)
{
__native_flush_tlb();
@@ -203,6 +214,7 @@ static void native_flush_tlb_single(unsi
{
__native_flush_tlb_single(addr);
}
+#endif /* CONFIG_PARAVIRT_MMU */
/* These are in entry.S */
extern void native_iret(void);
@@ -284,6 +296,7 @@ enum paravirt_lazy_mode paravirt_get_laz
return percpu_read(paravirt_lazy_mode);
}
+#ifdef CONFIG_PARAVIRT_MMU
void arch_flush_lazy_mmu_mode(void)
{
preempt_disable();
@@ -295,6 +308,7 @@ void arch_flush_lazy_mmu_mode(void)
preempt_enable();
}
+#endif /* CONFIG_PARAVIRT_MMU */
struct pv_info pv_info = {
.name = "bare hardware",
@@ -306,11 +320,16 @@ struct pv_info pv_info = {
struct pv_init_ops pv_init_ops = {
.patch = native_patch,
};
+EXPORT_SYMBOL_GPL(pv_info);
+#ifdef CONFIG_PARAVIRT_TIME
struct pv_time_ops pv_time_ops = {
.sched_clock = native_sched_clock,
};
+EXPORT_SYMBOL_GPL(pv_time_ops);
+#endif
+#ifdef CONFIG_PARAVIRT_IRQ
struct pv_irq_ops pv_irq_ops = {
.save_fl = __PV_IS_CALLEE_SAVE(native_save_fl),
.restore_fl = __PV_IS_CALLEE_SAVE(native_restore_fl),
@@ -322,7 +341,10 @@ struct pv_irq_ops pv_irq_ops = {
.adjust_exception_frame = paravirt_nop,
#endif
};
+EXPORT_SYMBOL (pv_irq_ops);
+#endif
+#ifdef CONFIG_PARAVIRT_CPU
struct pv_cpu_ops pv_cpu_ops = {
.cpuid = native_cpuid,
.get_debugreg = native_get_debugreg,
@@ -383,12 +405,17 @@ struct pv_cpu_ops pv_cpu_ops = {
.start_context_switch = paravirt_nop,
.end_context_switch = paravirt_nop,
};
+EXPORT_SYMBOL (pv_cpu_ops);
+#endif
+#ifdef CONFIG_PARAVIRT_APIC
struct pv_apic_ops pv_apic_ops = {
#ifdef CONFIG_X86_LOCAL_APIC
.startup_ipi_hook = paravirt_nop,
#endif
};
+EXPORT_SYMBOL_GPL(pv_apic_ops);
+#endif
#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
/* 32-bit pagetable entries */
@@ -398,6 +425,7 @@ struct pv_apic_ops pv_apic_ops = {
#define PTE_IDENT __PV_IS_CALLEE_SAVE(_paravirt_ident_64)
#endif
+#ifdef CONFIG_PARAVIRT_MMU
struct pv_mmu_ops pv_mmu_ops = {
.read_cr2 = native_read_cr2,
@@ -466,10 +494,5 @@ struct pv_mmu_ops pv_mmu_ops = {
.set_fixmap = native_set_fixmap,
};
-
-EXPORT_SYMBOL_GPL(pv_time_ops);
-EXPORT_SYMBOL (pv_cpu_ops);
EXPORT_SYMBOL (pv_mmu_ops);
-EXPORT_SYMBOL_GPL(pv_apic_ops);
-EXPORT_SYMBOL_GPL(pv_info);
-EXPORT_SYMBOL (pv_irq_ops);
+#endif

View File

@ -0,0 +1,80 @@
From: Alexander Graf <agraf@suse.de>
Date: Wed, 18 Nov 2009 12:58:00 +0100
Subject: Replace kvm io delay pv-ops with linux magic
References: bnc#556135, FATE#306453
Patch-Mainline: Submitted to virtualization list
Currently we use pv-ops to tell linux not to do anything on io_delay.
While the basic idea is good IMHO, I don't see why we would need pv-ops
for that. The io delay function already has a switch that can do nothing
if you're so inclined.
So here's a patch (stacked on top of the previous pv-ops series) that
removes the io delay pv-ops hook and just sets the native io delay
variable instead.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/x86/Kconfig | 14 --------------
arch/x86/kernel/kvm.c | 16 +++-------------
2 files changed, 3 insertions(+), 27 deletions(-)
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -548,20 +548,6 @@ config KVM_GUEST
This option enables various optimizations for running under the KVM
hypervisor.
-config KVM_IODELAY
- bool "KVM IO-delay support"
- depends on KVM_GUEST
- select PARAVIRT_CPU
- ---help---
- Usually we wait for PIO access to complete. When inside KVM there's
- no need to do that, as we know that we're not going through a bus,
- but process PIO requests instantly.
-
- This option disables PIO waits, but drags in CPU-bound pv-ops. Thus
- you will probably get more speed loss than speedup using this option.
-
- If in doubt, say N.
-
config KVM_MMU
bool "KVM PV MMU support"
depends on KVM_GUEST
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -29,15 +29,6 @@
#include <asm/desc.h>
#include <asm/tlbflush.h>
-#ifdef CONFIG_KVM_IODELAY
-/*
- * No need for any "IO delay" on KVM
- */
-static void kvm_io_delay(void)
-{
-}
-#endif /* CONFIG_KVM_IODELAY */
-
#ifdef CONFIG_KVM_MMU
#define MMU_QUEUE_SIZE 1024
@@ -201,13 +192,12 @@ static void kvm_leave_lazy_mmu(void)
static void __init paravirt_ops_setup(void)
{
+ extern int io_delay_type;
pv_info.name = "KVM";
pv_info.paravirt_enabled = 1;
-#ifdef CONFIG_KVM_IODELAY
- if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY))
- pv_cpu_ops.io_delay = kvm_io_delay;
-#endif
+ /* Disable IO delay */
+ io_delay_type = CONFIG_IO_DELAY_TYPE_NONE;
#ifdef CONFIG_KVM_MMU
if (kvm_para_has_feature(KVM_FEATURE_MMU_OP)) {

View File

@ -0,0 +1,728 @@
From: Alexander Graf <agraf@suse.de>
Date: Wed, 18 Nov 2009 00:27:59 +0100
Subject: Split paravirt ops by functionality
References: bnc#556135, FATE#306453
Patch-Mainline: Submitted to virtualization list
Currently when using paravirt ops it's an all-or-nothing option. We can either
use pv-ops for CPU, MMU, timing, etc. or not at all.
Now there are some use cases where we don't need the full feature set, but only
a small chunk of it. KVM is a pretty prominent example for this.
So let's make everything a bit more fine-grained. We already have a splitting
by function groups, namely "cpu", "mmu", "time", "irq", "apic" and "spinlock".
Taking that existing splitting and extending it to only compile in the PV
capable bits sounded like a natural fit. That way we don't get performance hits
in MMU code from using the KVM PV clock which only needs the TIME parts of
pv-ops.
We define a new CONFIG_PARAVIRT_ALL option that basically does the same thing
the CONFIG_PARAVIRT did before this splitting. We move all users of
CONFIG_PARAVIRT to CONFIG_PARAVIRT_ALL, so they behave the same way they did
before.
So here it is - the splitting! I would have made the patch smaller, but this
was the closest I could get to atomic (for bisect) while staying sane.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/x86/Kconfig | 41 +++++++++++++++++++++++---
arch/x86/include/asm/apic.h | 2 -
arch/x86/include/asm/desc.h | 4 +-
arch/x86/include/asm/fixmap.h | 2 -
arch/x86/include/asm/io.h | 2 -
arch/x86/include/asm/irqflags.h | 21 ++++++++++---
arch/x86/include/asm/mmu_context.h | 4 +-
arch/x86/include/asm/msr.h | 4 +-
arch/x86/include/asm/paravirt.h | 44 ++++++++++++++++++++++++++--
arch/x86/include/asm/paravirt_types.h | 12 +++++++
arch/x86/include/asm/pgalloc.h | 2 -
arch/x86/include/asm/pgtable-3level_types.h | 2 -
arch/x86/include/asm/pgtable.h | 2 -
arch/x86/include/asm/processor.h | 2 -
arch/x86/include/asm/required-features.h | 2 -
arch/x86/include/asm/smp.h | 2 -
arch/x86/include/asm/system.h | 13 +++++---
arch/x86/include/asm/tlbflush.h | 4 +-
arch/x86/kernel/head_64.S | 2 -
arch/x86/kernel/paravirt.c | 2 +
arch/x86/kernel/tsc.c | 2 -
arch/x86/kernel/vsmp_64.c | 2 -
arch/x86/kernel/x8664_ksyms_64.c | 2 -
arch/x86/xen/Kconfig | 2 -
24 files changed, 140 insertions(+), 37 deletions(-)
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -367,7 +367,7 @@ endif
config X86_VSMP
bool "ScaleMP vSMP"
select PARAVIRT_GUEST
- select PARAVIRT
+ select PARAVIRT_ALL
depends on X86_64 && PCI
depends on X86_EXTENDED_PLATFORM
---help---
@@ -533,7 +533,6 @@ config VMI
config KVM_CLOCK
bool "KVM paravirtualized clock"
- select PARAVIRT
select PARAVIRT_CLOCK
---help---
Turning on this option will allow you to run a paravirtualized clock
@@ -544,7 +543,7 @@ config KVM_CLOCK
config KVM_GUEST
bool "KVM Guest support"
- select PARAVIRT
+ select PARAVIRT_ALL
---help---
This option enables various optimizations for running under the KVM
hypervisor.
@@ -572,8 +571,42 @@ config PARAVIRT_SPINLOCKS
If you are unsure how to answer this question, answer N.
+config PARAVIRT_CPU
+ bool
+ select PARAVIRT
+
+config PARAVIRT_TIME
+ bool
+ select PARAVIRT
+
+config PARAVIRT_IRQ
+ bool
+ select PARAVIRT
+
+config PARAVIRT_APIC
+ bool
+ select PARAVIRT
+
+config PARAVIRT_MMU
+ bool
+ select PARAVIRT
+
+#
+# This is a placeholder to activate the old "include all pv-ops functionality"
+# behavior. If you're using this I'd recommend looking through your code to see
+# if you can be more specific. It probably saves you a few cycles!
+#
+config PARAVIRT_ALL
+ bool
+ select PARAVIRT_CPU
+ select PARAVIRT_TIME
+ select PARAVIRT_IRQ
+ select PARAVIRT_APIC
+ select PARAVIRT_MMU
+
config PARAVIRT_CLOCK
bool
+ select PARAVIRT_TIME
endif
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -81,7 +81,7 @@ static inline bool apic_from_smp_config(
/*
* Basic functions accessing APICs.
*/
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_APIC
#include <asm/paravirt.h>
#endif
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -78,7 +78,7 @@ static inline int desc_empty(const void
return !(desc[0] | desc[1]);
}
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_CPU
#include <asm/paravirt.h>
#else
#define load_TR_desc() native_load_tr_desc()
@@ -108,7 +108,7 @@ static inline void paravirt_alloc_ldt(st
static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries)
{
}
-#endif /* CONFIG_PARAVIRT */
+#endif /* CONFIG_PARAVIRT_CPU */
#define store_ldt(ldt) asm("sldt %0" : "=m"(ldt))
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -162,7 +162,7 @@ void __native_set_fixmap(enum fixed_addr
void native_set_fixmap(enum fixed_addresses idx,
phys_addr_t phys, pgprot_t flags);
-#ifndef CONFIG_PARAVIRT
+#ifndef CONFIG_PARAVIRT_MMU
static inline void __set_fixmap(enum fixed_addresses idx,
phys_addr_t phys, pgprot_t flags)
{
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -268,7 +268,7 @@ extern void native_io_delay(void);
extern int io_delay_type;
extern void io_delay_init(void);
-#if defined(CONFIG_PARAVIRT)
+#if defined(CONFIG_PARAVIRT_CPU)
#include <asm/paravirt.h>
#else
--- a/arch/x86/include/asm/irqflags.h
+++ b/arch/x86/include/asm/irqflags.h
@@ -58,9 +58,11 @@ static inline void native_halt(void)
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
-#else
+#endif
+
#ifndef __ASSEMBLY__
+#ifndef CONFIG_PARAVIRT_IRQ
static inline unsigned long arch_local_save_flags(void)
{
return native_save_fl();
@@ -110,12 +112,17 @@ static inline unsigned long __raw_local_
arch_local_irq_disable();
return flags;
}
-#else
+#endif /* CONFIG_PARAVIRT_IRQ */
+
+#else /* __ASSEMBLY__ */
+#ifndef CONFIG_PARAVIRT_IRQ
#define ENABLE_INTERRUPTS(x) sti
#define DISABLE_INTERRUPTS(x) cli
+#endif /* !CONFIG_PARAVIRT_IRQ */
#ifdef CONFIG_X86_64
+#ifndef CONFIG_PARAVIRT_CPU
#define SWAPGS swapgs
/*
* Currently paravirt can't handle swapgs nicely when we
@@ -128,8 +135,6 @@ static inline unsigned long __raw_local_
*/
#define SWAPGS_UNSAFE_STACK swapgs
-#define PARAVIRT_ADJUST_EXCEPTION_FRAME /* */
-
#define INTERRUPT_RETURN iretq
#define USERGS_SYSRET64 \
swapgs; \
@@ -141,16 +146,22 @@ static inline unsigned long __raw_local_
swapgs; \
sti; \
sysexit
+#endif /* !CONFIG_PARAVIRT_CPU */
+
+#ifndef CONFIG_PARAVIRT_IRQ
+#define PARAVIRT_ADJUST_EXCEPTION_FRAME /* */
+#endif /* !CONFIG_PARAVIRT_IRQ */
#else
+#ifndef CONFIG_PARAVIRT_CPU
#define INTERRUPT_RETURN iret
#define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit
#define GET_CR0_INTO_EAX movl %cr0, %eax
+#endif /* !CONFIG_PARAVIRT_CPU */
#endif
#endif /* __ASSEMBLY__ */
-#endif /* CONFIG_PARAVIRT */
#ifndef __ASSEMBLY__
static inline int arch_irqs_disabled_flags(unsigned long flags)
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -6,14 +6,14 @@
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/paravirt.h>
-#ifndef CONFIG_PARAVIRT
+#ifndef CONFIG_PARAVIRT_MMU
#include <asm-generic/mm_hooks.h>
static inline void paravirt_activate_mm(struct mm_struct *prev,
struct mm_struct *next)
{
}
-#endif /* !CONFIG_PARAVIRT */
+#endif /* !CONFIG_PARAVIRT_MMU */
/*
* Used for LDT copy/destruction.
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -135,7 +135,7 @@ static inline unsigned long long native_
return EAX_EDX_VAL(val, low, high);
}
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_CPU
#include <asm/paravirt.h>
#else
#include <linux/errno.h>
@@ -246,7 +246,7 @@ do {
#define rdtscpll(val, aux) (val) = native_read_tscp(&(aux))
-#endif /* !CONFIG_PARAVIRT */
+#endif /* !CONFIG_PARAVIRT_CPU */
#define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val), \
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -18,6 +18,7 @@ static inline int paravirt_enabled(void)
return pv_info.paravirt_enabled;
}
+#ifdef CONFIG_PARAVIRT_CPU
static inline void load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
@@ -58,7 +59,9 @@ static inline void write_cr0(unsigned lo
{
PVOP_VCALL1(pv_cpu_ops.write_cr0, x);
}
+#endif /* CONFIG_PARAVIRT_CPU */
+#ifdef CONFIG_PARAVIRT_MMU
static inline unsigned long read_cr2(void)
{
return PVOP_CALL0(unsigned long, pv_mmu_ops.read_cr2);
@@ -78,7 +81,9 @@ static inline void write_cr3(unsigned lo
{
PVOP_VCALL1(pv_mmu_ops.write_cr3, x);
}
+#endif /* CONFIG_PARAVIRT_MMU */
+#ifdef CONFIG_PARAVIRT_CPU
static inline unsigned long read_cr4(void)
{
return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4);
@@ -92,8 +97,9 @@ static inline void write_cr4(unsigned lo
{
PVOP_VCALL1(pv_cpu_ops.write_cr4, x);
}
+#endif /* CONFIG_PARAVIRT_CPU */
-#ifdef CONFIG_X86_64
+#if defined(CONFIG_X86_64) && defined(CONFIG_PARAVIRT_CPU)
static inline unsigned long read_cr8(void)
{
return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr8);
@@ -105,6 +111,7 @@ static inline void write_cr8(unsigned lo
}
#endif
+#ifdef CONFIG_PARAVIRT_IRQ
static inline void arch_safe_halt(void)
{
PVOP_VCALL0(pv_irq_ops.safe_halt);
@@ -114,14 +121,18 @@ static inline void halt(void)
{
PVOP_VCALL0(pv_irq_ops.halt);
}
+#endif /* CONFIG_PARAVIRT_IRQ */
+#ifdef CONFIG_PARAVIRT_CPU
static inline void wbinvd(void)
{
PVOP_VCALL0(pv_cpu_ops.wbinvd);
}
+#endif
#define get_kernel_rpl() (pv_info.kernel_rpl)
+#ifdef CONFIG_PARAVIRT_CPU
static inline u64 paravirt_read_msr(unsigned msr, int *err)
{
return PVOP_CALL2(u64, pv_cpu_ops.read_msr, msr, err);
@@ -224,12 +235,16 @@ do { \
} while (0)
#define rdtscll(val) (val = paravirt_read_tsc())
+#endif /* CONFIG_PARAVIRT_CPU */
+#ifdef CONFIG_PARAVIRT_TIME
static inline unsigned long long paravirt_sched_clock(void)
{
return PVOP_CALL0(unsigned long long, pv_time_ops.sched_clock);
}
+#endif /* CONFIG_PARAVIRT_TIME */
+#ifdef CONFIG_PARAVIRT_CPU
static inline unsigned long long paravirt_read_pmc(int counter)
{
return PVOP_CALL1(u64, pv_cpu_ops.read_pmc, counter);
@@ -345,8 +360,9 @@ static inline void slow_down_io(void)
pv_cpu_ops.io_delay();
#endif
}
+#endif /* CONFIG_PARAVIRT_CPU */
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) && defined(CONFIG_PARAVIRT_APIC)
static inline void startup_ipi_hook(int phys_apicid, unsigned long start_eip,
unsigned long start_esp)
{
@@ -355,6 +371,7 @@ static inline void startup_ipi_hook(int
}
#endif
+#ifdef CONFIG_PARAVIRT_MMU
static inline void paravirt_activate_mm(struct mm_struct *prev,
struct mm_struct *next)
{
@@ -689,7 +706,9 @@ static inline void pmd_clear(pmd_t *pmdp
set_pmd(pmdp, __pmd(0));
}
#endif /* CONFIG_X86_PAE */
+#endif /* CONFIG_PARAVIRT_MMU */
+#ifdef CONFIG_PARAVIRT_CPU
#define __HAVE_ARCH_START_CONTEXT_SWITCH
static inline void arch_start_context_switch(struct task_struct *prev)
{
@@ -700,7 +719,9 @@ static inline void arch_end_context_swit
{
PVOP_VCALL1(pv_cpu_ops.end_context_switch, next);
}
+#endif /* CONFIG_PARAVIRT_CPU */
+#ifdef CONFIG_PARAVIRT_MMU
#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
static inline void arch_enter_lazy_mmu_mode(void)
{
@@ -719,6 +740,7 @@ static inline void __set_fixmap(unsigned
{
pv_mmu_ops.set_fixmap(idx, phys, flags);
}
+#endif /* CONFIG_PARAVIRT_MMU */
#if defined(CONFIG_SMP) && defined(CONFIG_PARAVIRT_SPINLOCKS)
@@ -829,6 +851,7 @@ static __always_inline void arch_spin_un
#define __PV_IS_CALLEE_SAVE(func) \
((struct paravirt_callee_save) { func })
+#ifdef CONFIG_PARAVIRT_IRQ
static inline notrace unsigned long arch_local_save_flags(void)
{
return PVOP_CALLEE0(unsigned long, pv_irq_ops.save_fl);
@@ -857,6 +880,7 @@ static inline unsigned long __raw_local_
arch_local_irq_disable();
return f;
}
+#endif /* CONFIG_PARAVIRT_IRQ */
/* Make sure as little as possible of this mess escapes. */
@@ -939,10 +963,13 @@ extern void default_banner(void);
#define PARA_INDIRECT(addr) *%cs:addr
#endif
+#ifdef CONFIG_PARAVIRT_CPU
#define INTERRUPT_RETURN \
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_iret), CLBR_NONE, \
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_iret))
+#endif /* CONFIG_PARAVIRT_CPU */
+#ifdef CONFIG_PARAVIRT_IRQ
#define DISABLE_INTERRUPTS(clobbers) \
PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \
PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \
@@ -954,13 +981,17 @@ extern void default_banner(void);
PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \
call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \
PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);)
+#endif /* CONFIG_PARAVIRT_IRQ */
+#ifdef CONFIG_PARAVIRT_CPU
#define USERGS_SYSRET32 \
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \
CLBR_NONE, \
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret32))
+#endif /* CONFIG_PARAVIRT_CPU */
#ifdef CONFIG_X86_32
+#ifdef CONFIG_PARAVIRT_CPU
#define GET_CR0_INTO_EAX \
push %ecx; push %edx; \
call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); \
@@ -970,10 +1001,12 @@ extern void default_banner(void);
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit), \
CLBR_NONE, \
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit))
+#endif /* CONFIG_PARAVIRT_CPU */
#else /* !CONFIG_X86_32 */
+#ifdef CONFIG_PARAVIRT_CPU
/*
* If swapgs is used while the userspace stack is still current,
* there's no way to call a pvop. The PV replacement *must* be
@@ -993,17 +1026,23 @@ extern void default_banner(void);
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \
call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs) \
)
+#endif /* CONFIG_PARAVIRT_CPU */
+#ifdef CONFIG_PARAVIRT_MMU
#define GET_CR2_INTO_RCX \
call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2); \
movq %rax, %rcx; \
xorq %rax, %rax;
+#endif /* CONFIG_PARAVIRT_MMU */
+#ifdef CONFIG_PARAVIRT_IRQ
#define PARAVIRT_ADJUST_EXCEPTION_FRAME \
PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_adjust_exception_frame), \
CLBR_NONE, \
call PARA_INDIRECT(pv_irq_ops+PV_IRQ_adjust_exception_frame))
+#endif /* CONFIG_PARAVIRT_IRQ */
+#ifdef CONFIG_PARAVIRT_CPU
#define USERGS_SYSRET64 \
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64), \
CLBR_NONE, \
@@ -1013,6 +1052,7 @@ extern void default_banner(void);
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit), \
CLBR_NONE, \
jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit))
+#endif /* CONFIG_PARAVIRT_CPU */
#endif /* CONFIG_X86_32 */
#endif /* __ASSEMBLY__ */
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -339,12 +339,24 @@ struct paravirt_patch_template {
extern struct pv_info pv_info;
extern struct pv_init_ops pv_init_ops;
+#ifdef CONFIG_PARAVIRT_TIME
extern struct pv_time_ops pv_time_ops;
+#endif
+#ifdef CONFIG_PARAVIRT_CPU
extern struct pv_cpu_ops pv_cpu_ops;
+#endif
+#ifdef CONFIG_PARAVIRT_IRQ
extern struct pv_irq_ops pv_irq_ops;
+#endif
+#ifdef CONFIG_PARAVIRT_APIC
extern struct pv_apic_ops pv_apic_ops;
+#endif
+#ifdef CONFIG_PARAVIRT_MMU
extern struct pv_mmu_ops pv_mmu_ops;
+#endif
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
extern struct pv_lock_ops pv_lock_ops;
+#endif
#define PARAVIRT_PATCH(x) \
(offsetof(struct paravirt_patch_template, x) / sizeof(void *))
--- a/arch/x86/include/asm/pgalloc.h
+++ b/arch/x86/include/asm/pgalloc.h
@@ -7,7 +7,7 @@
static inline int __paravirt_pgd_alloc(struct mm_struct *mm) { return 0; }
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_MMU
#include <asm/paravirt.h>
#else
#define paravirt_pgd_alloc(mm) __paravirt_pgd_alloc(mm)
--- a/arch/x86/include/asm/pgtable-3level_types.h
+++ b/arch/x86/include/asm/pgtable-3level_types.h
@@ -18,7 +18,7 @@ typedef union {
} pte_t;
#endif /* !__ASSEMBLY__ */
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_MMU
#define SHARED_KERNEL_PMD (pv_info.shared_kernel_pmd)
#else
#define SHARED_KERNEL_PMD 1
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -28,7 +28,7 @@ extern unsigned long empty_zero_page[PAG
extern struct mm_struct *pgd_page_get_mm(struct page *page);
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_MMU
#include <asm/paravirt.h>
#else /* !CONFIG_PARAVIRT */
#define set_pte(ptep, pte) native_set_pte(ptep, pte)
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -569,7 +569,7 @@ static inline void native_swapgs(void)
#endif
}
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_CPU
#include <asm/paravirt.h>
#else
#define __cpuid native_cpuid
--- a/arch/x86/include/asm/required-features.h
+++ b/arch/x86/include/asm/required-features.h
@@ -48,7 +48,7 @@
#endif
#ifdef CONFIG_X86_64
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_MMU
/* Paravirtualized systems may not have PSE or PGE available */
#define NEED_PSE 0
#define NEED_PGE 0
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -66,7 +66,7 @@ struct smp_ops {
extern void set_cpu_sibling_map(int cpu);
#ifdef CONFIG_SMP
-#ifndef CONFIG_PARAVIRT
+#ifndef CONFIG_PARAVIRT_APIC
#define startup_ipi_hook(phys_apicid, start_eip, start_esp) do { } while (0)
#endif
extern struct smp_ops smp_ops;
--- a/arch/x86/include/asm/system.h
+++ b/arch/x86/include/asm/system.h
@@ -304,13 +304,18 @@ static inline void native_wbinvd(void)
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
-#else
-#define read_cr0() (native_read_cr0())
-#define write_cr0(x) (native_write_cr0(x))
+#endif/* CONFIG_PARAVIRT */
+
+#ifndef CONFIG_PARAVIRT_MMU
#define read_cr2() (native_read_cr2())
#define write_cr2(x) (native_write_cr2(x))
#define read_cr3() (native_read_cr3())
#define write_cr3(x) (native_write_cr3(x))
+#endif /* CONFIG_PARAVIRT_MMU */
+
+#ifndef CONFIG_PARAVIRT_CPU
+#define read_cr0() (native_read_cr0())
+#define write_cr0(x) (native_write_cr0(x))
#define read_cr4() (native_read_cr4())
#define read_cr4_safe() (native_read_cr4_safe())
#define write_cr4(x) (native_write_cr4(x))
@@ -324,7 +329,7 @@ static inline void native_wbinvd(void)
/* Clear the 'TS' bit */
#define clts() (native_clts())
-#endif/* CONFIG_PARAVIRT */
+#endif /* CONFIG_PARAVIRT_CPU */
#define stts() write_cr0(read_cr0() | X86_CR0_TS)
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -7,7 +7,7 @@
#include <asm/processor.h>
#include <asm/system.h>
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_MMU
#include <asm/paravirt.h>
#else
#define __flush_tlb() __native_flush_tlb()
@@ -162,7 +162,7 @@ static inline void reset_lazy_tlbstate(v
#endif /* SMP */
-#ifndef CONFIG_PARAVIRT
+#ifndef CONFIG_PARAVIRT_MMU
#define flush_tlb_others(mask, mm, va) native_flush_tlb_others(mask, mm, va)
#endif
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -20,7 +20,7 @@
#include <asm/processor-flags.h>
#include <asm/percpu.h>
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_MMU
#include <asm/asm-offsets.h>
#include <asm/paravirt.h>
#else
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -155,12 +155,14 @@ unsigned paravirt_patch_default(u8 type,
else if (opfunc == _paravirt_ident_64)
ret = paravirt_patch_ident_64(insnbuf, len);
+#ifdef CONFIG_PARAVIRT_CPU
else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) ||
type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret32) ||
type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret64))
/* If operation requires a jmp, then jmp */
ret = paravirt_patch_jmp(insnbuf, opfunc, addr, len);
+#endif
else
/* Otherwise call the function; assume target could
clobber any caller-save reg */
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -66,7 +66,7 @@ u64 native_sched_clock(void)
/* We need to define a real function for sched_clock, to override the
weak default version */
-#ifdef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT_TIME
unsigned long long sched_clock(void)
{
return paravirt_sched_clock();
--- a/arch/x86/kernel/vsmp_64.c
+++ b/arch/x86/kernel/vsmp_64.c
@@ -22,7 +22,7 @@
#include <asm/paravirt.h>
#include <asm/setup.h>
-#if defined CONFIG_PCI && defined CONFIG_PARAVIRT
+#if defined CONFIG_PCI && defined CONFIG_PARAVIRT_IRQ
/*
* Interrupt control on vSMPowered systems:
* ~AC is a shadow of IF. If IF is 'on' AC should be 'off'
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -54,6 +54,6 @@ EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(__memcpy);
EXPORT_SYMBOL(empty_zero_page);
-#ifndef CONFIG_PARAVIRT
+#ifndef CONFIG_PARAVIRT_CPU
EXPORT_SYMBOL(native_load_gs_index);
#endif
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -4,7 +4,7 @@
config XEN
bool "Xen guest support"
- select PARAVIRT
+ select PARAVIRT_ALL
select PARAVIRT_CLOCK
depends on X86_64 || (X86_32 && X86_PAE && !X86_VISWS)
depends on X86_CMPXCHG && X86_TSC

View File

@ -0,0 +1,125 @@
From: Alexander Graf <agraf@suse.de>
Date: Wed, 18 Nov 2009 00:45:10 +0100
Subject: Split the KVM pv-ops support by feature
References: bnc#556135, FATE#306453
Patch-Mainline: Submitted to virtualization list
Currently selecting KVM guest support enabled multiple features at once that
not everyone necessarily wants to have, namely:
- PV MMU
- zero io delay
- apic detection workaround
Let's split them off so we don't drag in the full pv-ops framework just to
detect we're running on KVM. That gives us more chances to tweak performance!
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/x86/Kconfig | 29 ++++++++++++++++++++++++++++-
arch/x86/kernel/kvm.c | 22 +++++++++++++++-------
2 files changed, 43 insertions(+), 8 deletions(-)
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -543,11 +543,38 @@ config KVM_CLOCK
config KVM_GUEST
bool "KVM Guest support"
- select PARAVIRT_ALL
+ select PARAVIRT
---help---
This option enables various optimizations for running under the KVM
hypervisor.
+config KVM_IODELAY
+ bool "KVM IO-delay support"
+ depends on KVM_GUEST
+ select PARAVIRT_CPU
+ ---help---
+ Usually we wait for PIO access to complete. When inside KVM there's
+ no need to do that, as we know that we're not going through a bus,
+ but process PIO requests instantly.
+
+ This option disables PIO waits, but drags in CPU-bound pv-ops. Thus
+ you will probably get more speed loss than speedup using this option.
+
+ If in doubt, say N.
+
+config KVM_MMU
+ bool "KVM PV MMU support"
+ depends on KVM_GUEST
+ select PARAVIRT_MMU
+ ---help---
+ This option enables the paravirtualized MMU for KVM. In most cases
+ it's pretty useless and shouldn't be used.
+
+ It will only cost you performance, because it drags in pv-ops for
+ memory management.
+
+ If in doubt, say N.
+
source "arch/x86/lguest/Kconfig"
config PARAVIRT
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -29,6 +29,16 @@
#include <asm/desc.h>
#include <asm/tlbflush.h>
+#ifdef CONFIG_KVM_IODELAY
+/*
+ * No need for any "IO delay" on KVM
+ */
+static void kvm_io_delay(void)
+{
+}
+#endif /* CONFIG_KVM_IODELAY */
+
+#ifdef CONFIG_KVM_MMU
#define MMU_QUEUE_SIZE 1024
static int kvmapf = 1;
@@ -43,13 +53,6 @@ static struct kvm_para_state *kvm_para_s
return &per_cpu(para_state, raw_smp_processor_id());
}
-/*
- * No need for any "IO delay" on KVM
- */
-static void kvm_io_delay(void)
-{
-}
-
#define KVM_TASK_SLEEP_HASHBITS 8
#define KVM_TASK_SLEEP_HASHSIZE (1<<KVM_TASK_SLEEP_HASHBITS)
@@ -194,15 +197,19 @@ static void kvm_leave_lazy_mmu(void)
mmu_queue_flush(state);
paravirt_leave_lazy_mmu();
}
+#endif /* CONFIG_KVM_MMU */
static void __init paravirt_ops_setup(void)
{
pv_info.name = "KVM";
pv_info.paravirt_enabled = 1;
+#ifdef CONFIG_KVM_IODELAY
if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY))
pv_cpu_ops.io_delay = kvm_io_delay;
+#endif
+#ifdef CONFIG_KVM_MMU
if (kvm_para_has_feature(KVM_FEATURE_MMU_OP)) {
pv_mmu_ops.set_pte = kvm_set_pte;
pv_mmu_ops.set_pte_at = kvm_set_pte_at;
@@ -226,6 +233,7 @@ static void __init paravirt_ops_setup(vo
pv_mmu_ops.lazy_mode.enter = kvm_enter_lazy_mmu;
pv_mmu_ops.lazy_mode.leave = kvm_leave_lazy_mmu;
}
+#endif /* CONFIG_KVM_MMU */
#ifdef CONFIG_X86_IO_APIC
no_timer_check = 1;
#endif

View File

@ -0,0 +1,148 @@
From: Russ Anderson <rja@sgi.com>
Subject: mm: Avoid putting a bad page back on the LRU v8
References: 415829
Acked-by: schwab@suse.de
Patch-mainline: not yet
Prevent a page with a physical memory error from being placed back
on the LRU. A new page flag (PG_memerror) is added if
CONFIG_PAGEFLAGS_EXTENDED is defined.
Version 8 change: Removed hot path check for pages with memory
errors on the free list.
Signed-off-by: Russ Anderson <rja@sgi.com>
Reviewed-by: Christoph Lameter <cl@linux-foundation.org>
---
include/linux/page-flags.h | 16 +++++++++++++++-
mm/migrate.c | 33 +++++++++++++++++++++++++++++++++
mm/vmscan.c | 1 +
3 files changed, 49 insertions(+), 1 deletion(-)
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -88,6 +88,7 @@ enum pageflags {
PG_private_2, /* If pagecache, has fs aux data */
PG_writeback, /* Page is under writeback */
#ifdef CONFIG_PAGEFLAGS_EXTENDED
+ PG_memerror, /* Page has a physical memory error */
PG_head, /* A head page */
PG_tail, /* A tail page */
#else
@@ -167,14 +168,21 @@ static inline int TestClearPage##uname(s
static inline int __TestClearPage##uname(struct page *page) \
{ return __test_and_clear_bit(PG_##lname, &page->flags); }
+#define PAGEFLAGMASK(uname, lname) \
+static inline int PAGEMASK_##uname(void) \
+ { return (1 << PG_##lname); }
+
#define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
- SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname)
+ SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname) \
+ PAGEFLAGMASK(uname, lname)
#define __PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
__SETPAGEFLAG(uname, lname) __CLEARPAGEFLAG(uname, lname)
#define PAGEFLAG_FALSE(uname) \
static inline int Page##uname(struct page *page) \
+ { return 0; } \
+static inline int PAGEMASK_##uname(void) \
{ return 0; }
#define TESTSCFLAG(uname, lname) \
@@ -391,6 +399,12 @@ static inline void __ClearPageTail(struc
#endif /* !PAGEFLAGS_EXTENDED */
+#ifdef CONFIG_PAGEFLAGS_EXTENDED
+PAGEFLAG(MemError, memerror)
+#else
+PAGEFLAG_FALSE(MemError)
+#endif
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
/*
* PageHuge() only returns true for hugetlbfs pages, but not for
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -63,6 +63,7 @@ int migrate_prep_local(void)
return 0;
}
+EXPORT_SYMBOL(migrate_prep);
/*
* Add isolated pages on the list back to the LRU under page lock
@@ -80,6 +81,7 @@ void putback_lru_pages(struct list_head
putback_lru_page(page);
}
}
+EXPORT_SYMBOL(putback_lru_pages);
/*
* Restore a potential migration pte to a working pte entry
@@ -701,6 +703,25 @@ unlock:
* restored.
*/
list_del(&page->lru);
+ if (PageMemError(page)) {
+ if (rc == 0)
+ /*
+ * A page with a memory error that has
+ * been migrated will not be moved to
+ * the LRU.
+ */
+ goto move_newpage;
+ else
+ /*
+ * The page failed to migrate and will not
+ * be added to the bad page list. Clearing
+ * the error bit will allow another attempt
+ * to migrate if it gets another correctable
+ * error.
+ */
+ ClearPageMemError(page);
+ }
+
dec_zone_page_state(page, NR_ISOLATED_ANON +
page_is_file_cache(page));
putback_lru_page(page);
@@ -775,6 +796,17 @@ int migrate_pages(struct list_head *from
}
}
}
+
+ if (rc != 0)
+ list_for_each_entry_safe(page, page2, from, lru)
+ if (PageMemError(page))
+ /*
+ * The page failed to migrate. Clearing
+ * the error bit will allow another attempt
+ * to migrate if it gets another correctable
+ * error.
+ */
+ ClearPageMemError(page);
rc = 0;
out:
if (!swapwrite)
@@ -787,6 +819,7 @@ out:
return nr_failed + retry;
}
+EXPORT_SYMBOL(migrate_pages);
#ifdef CONFIG_NUMA
/*
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1127,6 +1127,7 @@ int isolate_lru_page(struct page *page)
}
return ret;
}
+EXPORT_SYMBOL(isolate_lru_page);
/*
* Are there way too many processes in the direct reclaim path already?

View File

@ -0,0 +1,32 @@
From: Thomas Renninger <trenn@suse.de>
Subject: Fix huge and wronge C-state drawings due to uninitialized start/end timestamps
Patch-Mainline: not yet
References: none
Signed-off-by: Thomas Renninger <trenn@suse.de>
---
tools/perf/builtin-timechart.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
Index: linux-2.6.37-master/tools/perf/builtin-timechart.c
===================================================================
--- linux-2.6.37-master.orig/tools/perf/builtin-timechart.c
+++ linux-2.6.37-master/tools/perf/builtin-timechart.c
@@ -654,8 +654,15 @@ static void draw_c_p_states(void)
* two pass drawing so that the P state bars are on top of the C state blocks
*/
while (pwr) {
- if (pwr->type == CSTATE)
+ if (pwr->type == CSTATE) {
+ /* If the first event is an _end event, start timestamp is zero
+ -> ignore these */
+ if (pwr->start_time == 0 || pwr->end_time == 0) {
+ pwr = pwr->next;
+ continue;
+ }
svg_cstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state);
+ }
pwr = pwr->next;
}

View File

@ -0,0 +1,33 @@
From: Takashi Iwai <tiwai@suse.de>
Subject: [PATCH] Fix build_error without CONFIG_PPC_83xx
Patch-mainline:
References:
fsl_deep_sleep() is defined only with CONFIG_PPC_83xx although
CONFIG_IPIC is set for CONFIG_PPC_MPC512x, too.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
---
arch/powerpc/sysdev/ipic.c | 2 ++
1 file changed, 2 insertions(+)
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -921,6 +921,7 @@ static int ipic_suspend(struct sys_devic
ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR);
ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR);
+#ifdef CONFIG_PPC_83xx
if (fsl_deep_sleep()) {
/* In deep sleep, make sure there can be no
* pending interrupts, as this can cause
@@ -931,6 +932,7 @@ static int ipic_suspend(struct sys_devic
ipic_write(ipic->regs, IPIC_SEMSR, 0);
ipic_write(ipic->regs, IPIC_SERMR, 0);
}
+#endif
return 0;
}

View File

@ -0,0 +1,19 @@
From: olh@suse.de
Subject: force speed to fix autodetection on pegasos2
Patch-mainline: never
---
arch/powerpc/platforms/chrp/setup.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -293,7 +293,7 @@ static void chrp_init_early(void)
if (!property)
goto out_put;
if (!strcmp(property, "failsafe") || !strcmp(property, "serial"))
- add_preferred_console("ttyS", 0, NULL);
+ add_preferred_console("ttyS", 0, "115200");
out_put:
of_node_put(node);
}

View File

@ -0,0 +1,77 @@
From: Olaf Hering <olh@suse.de>
Subject: new prom=nodisplay option to avoid crash in firmware on B50
Patch-mainline: not yet
add prom=nodisplay
avoid crash in firmware on IBM B50 when OF stdout is on serial.
0 > boot scsi/sd@4:1,yaboot |
yaboot starting: loaded at 00200000 00222530 (0/0/00c1a078; sp: 00efffd0)
brokenfirmware did not claim executable memory, fixed it myself
Config file 'yaboot.cnf' read, 213 bytes
Welcome to yaboot version 10.1.22-r945.SuSE
booted from '/pci@80000000/scsi@10/sd@4:1,yaboot'
Enter "help" to get some basic usage information
boot:
* linux
boot: linux 3
Please wait, loading kernel...
Allocated 00600000 bytes for executable @ 02000000
Elf32 kernel loaded...
Loading ramdisk...
ramdisk loaded 0030e057 @ 04100000
OF stdout device is: /pci@80000000/isa@b/serial@i3f8
command line: root=/dev/system/root xmon=on sysrq=1 quiet panic=12 3
memory layout at init:
memory_limit : 00000000 (16 MB aligned)
alloc_bottom : 0440f000
alloc_top : 30000000
alloc_top_hi : 40000000
rmo_top : 30000000
ram_top : 40000000
Looking for displays
found display : /pci@80000000/display@16, opening ...
Unexpected Firmware Error:
DEFAULT CATCH!, code=fff00300 at %SRR0: 00c18ccc %SRR1: 00003030
ok
0 > reset-all
---
arch/powerpc/kernel/prom_init.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -169,6 +169,7 @@ static unsigned long __initdata dt_strin
static unsigned long __initdata prom_initrd_start, prom_initrd_end;
+static int __initdata prom_no_display;
#ifdef CONFIG_PPC64
static int __initdata prom_iommu_force_on;
static int __initdata prom_iommu_off;
@@ -596,6 +597,14 @@ static void __init early_cmdline_parse(v
#endif /* CONFIG_CMDLINE */
prom_printf("command line: %s\n", RELOC(prom_cmd_line));
+ opt = strstr(RELOC(prom_cmd_line), RELOC("prom="));
+ if (opt) {
+ opt += 5;
+ while (*opt && *opt == ' ')
+ opt++;
+ if (!strncmp(opt, RELOC("nodisplay"), 9))
+ RELOC(prom_no_display) = 1;
+ }
#ifdef CONFIG_PPC64
opt = strstr(RELOC(prom_cmd_line), RELOC("iommu="));
if (opt) {
@@ -2570,6 +2579,7 @@ unsigned long __init prom_init(unsigned
/*
* Initialize display devices
*/
+ if (RELOC(prom_no_display) == 0)
prom_check_displays();
#ifdef CONFIG_PPC64

View File

@ -0,0 +1,119 @@
Subject: [PATCH] add syslog printing to xmon debugger.
From: Linas Vepstas <linas@austin.ibm.com>
Patch-mainline: Not yet
This patch 'dmesg'/printk log buffer printing to xmon. I find this
useful because crashes are almost always preceeded by interesting
printk's. This patch is simple & straightforward, except for one
possibly controversial aspect: it embeds a small snippet in
kernel/printk.c to return the location of the syslog. This is
needed because kallsyms and even CONFIG_KALLSYMS_ALL is not enough
to reveal the location of log_buf. This code is about 90%
cut-n-paste of earlier code from Keith Owens.
Signed-off-by: Olaf Hering <olh@suse.de>
---
arch/powerpc/xmon/xmon.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++
kernel/printk.c | 2 -
2 files changed, 58 insertions(+), 1 deletion(-)
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -138,6 +138,7 @@ static struct bpt *in_breakpoint_table(u
static int do_step(struct pt_regs *);
static void bpt_cmds(void);
static void cacheflush(void);
+static void xmon_show_dmesg(void);
static int cpu_cmd(void);
static void csum(void);
static void bootcmds(void);
@@ -197,6 +198,7 @@ Commands:\n\
#endif
"\
C checksum\n\
+ D show dmesg (printk) buffer\n\
d dump bytes\n\
di dump instructions\n\
df dump float values\n\
@@ -831,6 +833,9 @@ cmds(struct pt_regs *excp)
case 'd':
dump();
break;
+ case 'D':
+ xmon_show_dmesg();
+ break;
case 'l':
symbol_lookup();
break;
@@ -2607,6 +2612,58 @@ static void xmon_print_symbol(unsigned l
printf("%s", after);
}
+extern void kdb_syslog_data(char *syslog_data[]);
+#define SYSLOG_WRAP(p) if (p < syslog_data[0]) p = syslog_data[1]-1; \
+ else if (p >= syslog_data[1]) p = syslog_data[0];
+
+static void xmon_show_dmesg(void)
+{
+ char *syslog_data[4], *start, *end, c;
+ int logsize;
+
+ /* syslog_data[0,1] physical start, end+1.
+ * syslog_data[2,3] logical start, end+1.
+ */
+ kdb_syslog_data(syslog_data);
+ if (syslog_data[2] == syslog_data[3])
+ return;
+ logsize = syslog_data[1] - syslog_data[0];
+ start = syslog_data[0] + (syslog_data[2] - syslog_data[0]) % logsize;
+ end = syslog_data[0] + (syslog_data[3] - syslog_data[0]) % logsize;
+
+ /* Do a line at a time (max 200 chars) to reduce overhead */
+ c = '\0';
+ while(1) {
+ char *p;
+ int chars = 0;
+ if (!*start) {
+ while (!*start) {
+ ++start;
+ SYSLOG_WRAP(start);
+ if (start == end)
+ break;
+ }
+ if (start == end)
+ break;
+ }
+ p = start;
+ while (*start && chars < 200) {
+ c = *start;
+ ++chars;
+ ++start;
+ SYSLOG_WRAP(start);
+ if (start == end || c == '\n')
+ break;
+ }
+ if (chars)
+ printf("%.*s", chars, p);
+ if (start == end)
+ break;
+ }
+ if (c != '\n')
+ printf("\n");
+}
+
#ifdef CONFIG_PPC_BOOK3S_64
static void dump_slb(void)
{
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -416,7 +416,7 @@ SYSCALL_DEFINE3(syslog, int, type, char
return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
}
-#ifdef CONFIG_KGDB_KDB
+#if defined(CONFIG_KGDB_KDB) || defined(CONFIG_DEBUG_KERNEL)
/* kdb dmesg command needs access to the syslog buffer. do_syslog()
* uses locks so it cannot be used during debugging. Just tell kdb
* where the start and end of the physical and logical logs are. This

View File

@ -0,0 +1,43 @@
From: Jeff Mahoney <jeffm@suse.com>
Subject: [PATCH] s390: Define FREE_PTE_NR
Patch-mainline: Never, unless FREE_PTE_NR is used in generic code
Commit ba8a9229ab9e80278c28ad68b15053f65b2b0a7c from
Martin Schwidefsky <schwidefsky@de.ibm.com> removed the
#include <asm-generic/tlb.h> from asm-s390/tlb.h when he defined the
s390-specific TLB operations.
FREE_PTR_NR is generally an internal-only value, but our unmap_vmas-lat
patch uses it to make smarter decisions about dumping PTEs in chunks.
This patch restores the generic value in asm-s390/tlb.h. Since it's only
used for an optimization, this should be safe.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
arch/s390/include/asm/tlb.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -34,6 +34,19 @@
#define TLB_NR_PTRS 508
#endif
+/* Lifted from asm-generic/tlb.h; Is used by patches.suse/unmap_vmas-lat */
+/*
+ * For UP we don't need to worry about TLB flush
+ * and page free order so much..
+ */
+#ifdef CONFIG_SMP
+ #define FREE_PTE_NR 506
+ #define tlb_fast_mode(tlb) ((tlb)->nr == ~0U)
+#else
+ #define FREE_PTE_NR 1
+ #define tlb_fast_mode(tlb) 1
+#endif
+
struct mmu_gather {
struct mm_struct *mm;
unsigned int fullmm;

View File

@ -0,0 +1,23 @@
From: Jiri Slaby <jslaby@suse.cz>
Subject: fix build on s390 as of 2.6.36-rc4
Patch-mainline: never
This fixes patches.arch/s390-message-catalog.diff build.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
include/linux/device.h | 2 ++
1 file changed, 2 insertions(+)
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -660,6 +660,8 @@ int printk_dev_hash(const char *, const
#endif
+#define dev_printk(level, dev, format, arg...) \
+ dev_printk_hash(level , dev, format, ## arg)
#define dev_emerg(dev, format, arg...) \
dev_printk_hash(KERN_EMERG , dev , format , ## arg)
#define dev_alert(dev, format, arg...) \

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
From: IBM <lcm@us.ibm.com>
Subject: Use apic=bigsmp on specific xseries machines
References: bnc#440497
Patch-Mainline: not yet
Signed-off-by: Thomas Renninger <trenn@suse.de>
arch/x86/kernel/apic/bigsmp_32.c | 30 +++++++++++++++++++++++++++---
arch/x86/kernel/apic/probe_32.c | 4 ++--
2 files changed, 29 insertions(+), 5 deletions(-)
--- a/arch/x86/kernel/apic/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -156,7 +156,7 @@ static void bigsmp_send_IPI_all(int vect
static int dmi_bigsmp; /* can be set by dmi scanners */
-static int hp_ht_bigsmp(const struct dmi_system_id *d)
+static int force_bigsmp_apic(const struct dmi_system_id *d)
{
printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
dmi_bigsmp = 1;
@@ -166,17 +166,41 @@ static int hp_ht_bigsmp(const struct dmi
static const struct dmi_system_id bigsmp_dmi_table[] = {
- { hp_ht_bigsmp, "HP ProLiant DL760 G2",
+ { force_bigsmp_apic, "HP ProLiant DL760 G2",
{ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
}
},
- { hp_ht_bigsmp, "HP ProLiant DL740",
+ { force_bigsmp_apic, "HP ProLiant DL740",
{ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
DMI_MATCH(DMI_BIOS_VERSION, "P47-"),
}
},
+
+ { force_bigsmp_apic, "IBM x260 / x366 / x460",
+ { DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION, "-[ZT"),
+ }
+ },
+
+ { force_bigsmp_apic, "IBM x3800 / x3850 / x3950",
+ { DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION, "-[ZU"),
+ }
+ },
+
+ { force_bigsmp_apic, "IBM x3800 / x3850 / x3950",
+ { DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION, "-[ZS"),
+ }
+ },
+
+ { force_bigsmp_apic, "IBM x3850 M2 / x3950 M2",
+ { DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION, "-[A3"),
+ }
+ },
{ } /* NULL entry stops DMI scanning */
};
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -267,7 +267,7 @@ generic_mps_oem_check(struct mpc_table *
if (!apic_probe[i]->mps_oem_check(mpc, oem, productid))
continue;
- if (!cmdline_apic) {
+ if (!cmdline_apic && apic == &apic_default) {
apic = apic_probe[i];
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
apic->name);
@@ -287,7 +287,7 @@ int __init default_acpi_madt_oem_check(c
if (!apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id))
continue;
- if (!cmdline_apic) {
+ if (!cmdline_apic && apic == &apic_default) {
apic = apic_probe[i];
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
apic->name);

View File

@ -0,0 +1,26 @@
From: Takashi Iwai <tiwai@suse.de>
Subject: x86: workaround for mccreary HPET read problem
Patch-mainline: not yet
References: bnc#433746
On mccreacy platform, the read of HPET CMP register seems not updated
immediately after the write and returns the previous value instead.
A workaround is to read the register twice.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
---
arch/x86/kernel/hpet.c | 1 +
1 file changed, 1 insertion(+)
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -386,6 +386,7 @@ static int hpet_next_event(unsigned long
cnt += (u32) delta;
hpet_writel(cnt, HPET_Tn_CMP(timer));
+ hpet_readl(HPET_Tn_CMP(timer)); /* pre-read for bnc#433746 */
/*
* We need to read back the CMP register on certain HPET
* implementations (ATI chipsets) which seem to delay the

View File

@ -0,0 +1,38 @@
From: Tejun Heo <tj@kernel.org>
Subject: x86: disallow DAC for MCP51 PCI bridge
References: bnc#463829
Patch-mainline: not yet
MCP51 corrupts DAC transfers. Disallow it. Reported by pgnet on
bnc#463829.
https://bugzilla.novell.com/show_bug.cgi?id=463829
Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: pgnet <pgnet.trash@gmail.com>
Signed-off-by: Tejun Heo <teheo@suse.de>
---
arch/x86/kernel/pci-dma.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -322,4 +322,18 @@ static __devinit void via_no_dac(struct
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+
+/*
+ * MCP51 PCI bridge corrupts data for DAC. Disable it. Reported in
+ * bnc#463829.
+ */
+static __devinit void mcp51_no_dac(struct pci_dev *dev)
+{
+ if (forbid_dac == 0) {
+ printk(KERN_INFO
+ "PCI: MCP51 PCI bridge detected. Disabling DAC.\n");
+ forbid_dac = 1;
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x026f, mcp51_no_dac);
#endif

View File

@ -0,0 +1,223 @@
From: Jiri Bohac <jbohac@suse.cz>
Subject: allow 64-bit mode for HPET Timer0
References: bnc#456700
The kernel uses the HPET timers in 32-bit mode for clock-events.
While 32 bits, with a wrap-around time of >4 minutes, is probably
good enough for the clock-event purposes, on some chipsets this
has a negative side-effect on the HPET main counter.
Unlike the original HPET specification 1.0 from 2004, which does not
mention any side-effects of setting TN_32MODE_CNF on the
individual timers, the ICH9 documentation, for example, says:
NOTE: When this bit is set to 1, the hardware counter will
do a 32-bit operation on comparator match and rollovers, thus
the upper 32-bit of the Timer 0 Comparator Value register is
ignored. The upper 32-bit of the main counter is not involved
in any rollover from lower 32-bit of the main counter and
becomes all zeros.
(see http://www.intel.com/assets/pdf/datasheet/316972.pdf, page
819, section 21.1.5, Bit 8). I've seen this behaviour also on
ICH8. I have no idea what other chipsets are affected. But I have
seen AMD chipsets that Do The Right Thing.
This means, that when the kernel configures the Timer 0 to 32-bit
mode, on these chipsets it also cripples the 64-bit main counter
to 32 bits.
The HPET may be mmapped in userspace and the main counter
accessed directly by applications, expecting a 64-bit main
counter.
This patch allows the Timer0 to be configured in 64-bit mode
on x86_64 when a hpet64 command-line option is specified.
Updated-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Jiri Bohac <jbohac@suse.cz>
---
Documentation/kernel-parameters.txt | 2
arch/x86/kernel/hpet.c | 88 ++++++++++++++++++++++++++++++++----
2 files changed, 81 insertions(+), 9 deletions(-)
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -497,6 +497,8 @@ and is between 256 and 4096 characters.
Range: 0 - 8192
Default: 64
+ hpet64 [X86-64,HPET] enable 64-bit mode of the HPET timer (bnc#456700)
+
com20020= [HW,NET] ARCnet - COM20020 chipset
Format:
<io>[,<irq>[,<nodeID>[,<backplane>[,<ckp>[,<timeout>]]]]]
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -37,6 +37,7 @@ unsigned long hpet_address;
static unsigned long hpet_num_timers;
#endif
static void __iomem *hpet_virt_address;
+static int hpet_legacy_use_64_bits;
struct hpet_dev {
struct clock_event_device evt;
@@ -59,6 +60,33 @@ static inline void hpet_writel(unsigned
#ifdef CONFIG_X86_64
#include <asm/pgtable.h>
+static inline unsigned long hpet_read_value(unsigned long a)
+{
+ if (hpet_legacy_use_64_bits)
+ return readq(hpet_virt_address + a);
+ else
+ return readl(hpet_virt_address + a);
+}
+
+static void hpet_write_value(unsigned long d, unsigned long a)
+{
+ if (hpet_legacy_use_64_bits)
+ writeq(d, hpet_virt_address + a);
+ else
+ writel(d, hpet_virt_address + a);
+}
+
+#else
+
+static inline unsigned long hpet_read_value(unsigned long a)
+{
+ return readl(hpet_virt_address + a);
+}
+
+static void hpet_write_value(unsigned long d, unsigned long a)
+{
+ writel(d, hpet_virt_address + a);
+}
#endif
static inline void hpet_set_mapping(void)
@@ -103,6 +131,17 @@ static int __init disable_hpet(char *str
}
__setup("nohpet", disable_hpet);
+#ifdef CONFIG_X86_64
+static int hpet64 = 0;
+static int __init hpet64_setup(char *str)
+{
+ hpet64 = 1;
+ return 1;
+}
+__setup("hpet64", hpet64_setup);
+#endif
+
+
static inline int is_hpet_capable(void)
{
return !boot_hpet_disable && hpet_address;
@@ -212,6 +251,7 @@ static void hpet_reserve_platform_timers
* Common hpet info
*/
static unsigned long hpet_period;
+static int hpet_legacy_use_64_bits; /* configure T0 in 64-bit mode? */
static void hpet_legacy_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt);
@@ -278,10 +318,38 @@ static void hpet_enable_legacy_int(void)
hpet_legacy_int_enabled = 1;
}
+static int timer0_use_64_bits(void)
+{
+#ifndef CONFIG_X86_64
+ /* using the HPET in 64-bit mode without atomic 64-bit
+ * accesses is too inefficient
+ */
+ return 0;
+#else
+
+ if (unlikely(hpet64)) {
+ u32 id, t0_cfg;
+ id = hpet_readl(HPET_ID);
+ t0_cfg = hpet_readl(HPET_Tn_CFG(0));
+
+ if ((id & HPET_ID_64BIT) && (t0_cfg & HPET_TN_64BIT_CAP)) {
+ printk(KERN_DEBUG "hpet timer0 configured in 64-bit mode\n");
+ return 1;
+ }
+ else {
+ printk(KERN_DEBUG "hpet timer0 does not support 64-bit mode\n");
+ return 0;
+ }
+ }
+ else return 0;
+#endif
+}
+
static void hpet_legacy_clockevent_register(void)
{
/* Start HPET legacy interrupts */
hpet_enable_legacy_int();
+ hpet_legacy_use_64_bits = timer0_use_64_bits();
/*
* The mult factor is defined as (include/linux/clockchips.h)
@@ -328,9 +396,10 @@ static void hpet_set_mode(enum clock_eve
/* Make sure we use edge triggered interrupts */
cfg &= ~HPET_TN_LEVEL;
cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
- HPET_TN_SETVAL | HPET_TN_32BIT;
+ HPET_TN_SETVAL |
+ (hpet_legacy_use_64_bits ? 0 : HPET_TN_32BIT);
hpet_writel(cfg, HPET_Tn_CFG(timer));
- hpet_writel(cmp, HPET_Tn_CMP(timer));
+ hpet_write_value(cmp, HPET_Tn_CMP(timer));
udelay(1);
/*
* HPET on AMD 81xx needs a second write (with HPET_TN_SETVAL
@@ -339,7 +408,7 @@ static void hpet_set_mode(enum clock_eve
* (See AMD-8111 HyperTransport I/O Hub Data Sheet,
* Publication # 24674)
*/
- hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
+ hpet_write_value((unsigned long) delta, HPET_Tn_CMP(timer));
hpet_start_counter();
hpet_print_config();
break;
@@ -347,7 +416,8 @@ static void hpet_set_mode(enum clock_eve
case CLOCK_EVT_MODE_ONESHOT:
cfg = hpet_readl(HPET_Tn_CFG(timer));
cfg &= ~HPET_TN_PERIODIC;
- cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
+ cfg |= HPET_TN_ENABLE |
+ (hpet_legacy_use_64_bits ? 0 : HPET_TN_32BIT);
hpet_writel(cfg, HPET_Tn_CFG(timer));
break;
@@ -376,11 +446,11 @@ static void hpet_set_mode(enum clock_eve
static int hpet_next_event(unsigned long delta,
struct clock_event_device *evt, int timer)
{
- u32 cnt;
+ unsigned long cnt;
- cnt = hpet_readl(HPET_COUNTER);
+ cnt = hpet_read_value(HPET_COUNTER);
cnt += (u32) delta;
- hpet_writel(cnt, HPET_Tn_CMP(timer));
+ hpet_write_value(cnt, HPET_Tn_CMP(timer));
hpet_readl(HPET_Tn_CMP(timer)); /* pre-read for bnc#433746 */
/*
@@ -388,9 +458,9 @@ static int hpet_next_event(unsigned long
* what we wrote hit the chip before we compare it to the
* counter.
*/
- WARN_ON_ONCE((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt);
+ WARN_ON_ONCE((u32)hpet_readl(HPET_Tn_CMP(timer)) != (u32)cnt);
- return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
+ return (s32)((u32)hpet_readl(HPET_COUNTER) - (u32)cnt) >= 0 ? -ETIME : 0;
}
static void hpet_legacy_set_mode(enum clock_event_mode mode,

View File

@ -0,0 +1,439 @@
From: jbeulich@novell.com
Subject: fix unwind annotations
Patch-mainline: tbd
References: bnc#472783, bnc#588458
---
arch/x86/kernel/entry_64.S | 131 +++++++++++++++++++++++----------------------
arch/x86/kernel/head_64.S | 13 ++++
lib/rwsem_64.S | 56 ++++++++++++++---------
3 files changed, 114 insertions(+), 84 deletions(-)
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -234,21 +234,21 @@ ENDPROC(native_usergs_sysret64)
/*
* initial frame state for interrupts (and exceptions without error code)
*/
- .macro EMPTY_FRAME start=1 offset=0
- .if \start
+ .macro EMPTY_FRAME offset=0
CFI_STARTPROC simple
CFI_SIGNAL_FRAME
- CFI_DEF_CFA rsp,8+\offset
- .else
- CFI_DEF_CFA_OFFSET 8+\offset
- .endif
+ CFI_DEF_CFA rsp,\offset
.endm
/*
* initial frame state for interrupts (and exceptions without error code)
*/
.macro INTR_FRAME start=1 offset=0
- EMPTY_FRAME \start, SS+8+\offset-RIP
+ .if \start
+ EMPTY_FRAME SS+8+\offset-RIP
+ .else
+ CFI_DEF_CFA_OFFSET SS+8+\offset-RIP
+ .endif
/*CFI_REL_OFFSET ss, SS+\offset-RIP*/
CFI_REL_OFFSET rsp, RSP+\offset-RIP
/*CFI_REL_OFFSET rflags, EFLAGS+\offset-RIP*/
@@ -262,14 +262,15 @@ ENDPROC(native_usergs_sysret64)
*/
.macro XCPT_FRAME start=1 offset=0
INTR_FRAME \start, RIP+\offset-ORIG_RAX
- /*CFI_REL_OFFSET orig_rax, ORIG_RAX-ORIG_RAX*/
.endm
/*
* frame that enables calling into C.
*/
.macro PARTIAL_FRAME start=1 offset=0
+ .if \start >= 0
XCPT_FRAME \start, ORIG_RAX+\offset-ARGOFFSET
+ .endif
CFI_REL_OFFSET rdi, RDI+\offset-ARGOFFSET
CFI_REL_OFFSET rsi, RSI+\offset-ARGOFFSET
CFI_REL_OFFSET rdx, RDX+\offset-ARGOFFSET
@@ -285,7 +286,9 @@ ENDPROC(native_usergs_sysret64)
* frame that enables passing a complete pt_regs to a C function.
*/
.macro DEFAULT_FRAME start=1 offset=0
+ .if \start >= -1
PARTIAL_FRAME \start, R11+\offset-R15
+ .endif
CFI_REL_OFFSET rbx, RBX+\offset
CFI_REL_OFFSET rbp, RBP+\offset
CFI_REL_OFFSET r12, R12+\offset
@@ -297,25 +300,27 @@ ENDPROC(native_usergs_sysret64)
/* save partial stack frame */
.pushsection .kprobes.text, "ax"
ENTRY(save_args)
- XCPT_FRAME
+ XCPT_FRAME offset=ORIG_RAX-RBP+8
cld
/*
* start from rbp in pt_regs and jump over
* return address.
*/
movq_cfi rdi, RDI+8-RBP
- movq_cfi rsi, RSI+8-RBP
- movq_cfi rdx, RDX+8-RBP
- movq_cfi rcx, RCX+8-RBP
+ movq %rsi, RSI+8-RBP(%rsp)
+ movq %rdx, RDX+8-RBP(%rsp)
+ movq %rcx, RCX+8-RBP(%rsp)
movq_cfi rax, RAX+8-RBP
- movq_cfi r8, R8+8-RBP
- movq_cfi r9, R9+8-RBP
- movq_cfi r10, R10+8-RBP
- movq_cfi r11, R11+8-RBP
+ movq %r8, R8+8-RBP(%rsp)
+ movq %r9, R9+8-RBP(%rsp)
+ movq %r10, R10+8-RBP(%rsp)
+ movq %r11, R11+8-RBP(%rsp)
leaq -RBP+8(%rsp),%rdi /* arg1 for handler */
movq_cfi rbp, 8 /* push %rbp */
leaq 8(%rsp), %rbp /* mov %rsp, %ebp */
+ CFI_DEF_CFA_REGISTER rbp
+ CFI_ADJUST_CFA_OFFSET -8
testl $3, CS(%rdi)
je 1f
SWAPGS
@@ -327,11 +332,10 @@ ENTRY(save_args)
*/
1: incl PER_CPU_VAR(irq_count)
jne 2f
- popq_cfi %rax /* move return address... */
+ popq %rax /* move return address... */
mov PER_CPU_VAR(irq_stack_ptr),%rsp
- EMPTY_FRAME 0
- pushq_cfi %rbp /* backlink for unwinder */
- pushq_cfi %rax /* ... to the new stack */
+ pushq %rbp /* backlink for unwinder */
+ pushq %rax /* ... to the new stack */
/*
* We entered an interrupt context - irqs are off:
*/
@@ -342,14 +346,14 @@ END(save_args)
.popsection
ENTRY(save_rest)
- PARTIAL_FRAME 1 REST_SKIP+8
+ CFI_STARTPROC
movq 5*8+16(%rsp), %r11 /* save return address */
- movq_cfi rbx, RBX+16
- movq_cfi rbp, RBP+16
- movq_cfi r12, R12+16
- movq_cfi r13, R13+16
- movq_cfi r14, R14+16
- movq_cfi r15, R15+16
+ movq %rbx, RBX+16(%rsp)
+ movq %rbp, RBP+16(%rsp)
+ movq %r12, R12+16(%rsp)
+ movq %r13, R13+16(%rsp)
+ movq %r14, R14+16(%rsp)
+ movq %r15, R15+16(%rsp)
movq %r11, 8(%rsp) /* return address */
FIXUP_TOP_OF_STACK %r11, 16
ret
@@ -359,23 +363,23 @@ END(save_rest)
/* save complete stack frame */
.pushsection .kprobes.text, "ax"
ENTRY(save_paranoid)
- XCPT_FRAME 1 RDI+8
+ XCPT_FRAME offset=ORIG_RAX-R15+8
cld
- movq_cfi rdi, RDI+8
- movq_cfi rsi, RSI+8
+ movq %rdi, RDI+8(%rsp)
+ movq %rsi, RSI+8(%rsp)
movq_cfi rdx, RDX+8
movq_cfi rcx, RCX+8
movq_cfi rax, RAX+8
- movq_cfi r8, R8+8
- movq_cfi r9, R9+8
- movq_cfi r10, R10+8
- movq_cfi r11, R11+8
+ movq %r8, R8+8(%rsp)
+ movq %r9, R9+8(%rsp)
+ movq %r10, R10+8(%rsp)
+ movq %r11, R11+8(%rsp)
movq_cfi rbx, RBX+8
- movq_cfi rbp, RBP+8
- movq_cfi r12, R12+8
- movq_cfi r13, R13+8
- movq_cfi r14, R14+8
- movq_cfi r15, R15+8
+ movq %rbp, RBP+8(%rsp)
+ movq %r12, R12+8(%rsp)
+ movq %r13, R13+8(%rsp)
+ movq %r14, R14+8(%rsp)
+ movq %r15, R15+8(%rsp)
movl $1,%ebx
movl $MSR_GS_BASE,%ecx
rdmsr
@@ -677,7 +681,7 @@ ENTRY(\label)
subq $REST_SKIP, %rsp
CFI_ADJUST_CFA_OFFSET REST_SKIP
call save_rest
- DEFAULT_FRAME 0 8 /* offset 8: return address */
+ DEFAULT_FRAME -2 8 /* offset 8: return address */
leaq 8(%rsp), \arg /* pt_regs pointer */
call \func
jmp ptregscall_common
@@ -794,7 +798,9 @@ END(interrupt)
subq $ORIG_RAX-RBP, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
call save_args
- PARTIAL_FRAME 0
+ PARTIAL_FRAME -1 ARGOFFSET-RBP
+ CFI_REL_OFFSET rbp, 0
+ CFI_DEF_CFA_REGISTER rbp
call \func
.endm
@@ -813,7 +819,6 @@ ret_from_intr:
TRACE_IRQS_OFF
decl PER_CPU_VAR(irq_count)
leaveq
-
CFI_RESTORE rbp
CFI_DEF_CFA_REGISTER rsp
CFI_ADJUST_CFA_OFFSET -8
@@ -1021,7 +1026,7 @@ ENTRY(\sym)
subq $ORIG_RAX-R15, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call error_entry
- DEFAULT_FRAME 0
+ DEFAULT_FRAME -1
movq %rsp,%rdi /* pt_regs pointer */
xorl %esi,%esi /* no error code */
call \do_sym
@@ -1038,6 +1043,7 @@ ENTRY(\sym)
subq $ORIG_RAX-R15, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call save_paranoid
+ DEFAULT_FRAME -1
TRACE_IRQS_OFF
movq %rsp,%rdi /* pt_regs pointer */
xorl %esi,%esi /* no error code */
@@ -1056,6 +1062,7 @@ ENTRY(\sym)
subq $ORIG_RAX-R15, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call save_paranoid
+ DEFAULT_FRAME -1
TRACE_IRQS_OFF
movq %rsp,%rdi /* pt_regs pointer */
xorl %esi,%esi /* no error code */
@@ -1074,7 +1081,7 @@ ENTRY(\sym)
subq $ORIG_RAX-R15, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call error_entry
- DEFAULT_FRAME 0
+ DEFAULT_FRAME -1
movq %rsp,%rdi /* pt_regs pointer */
movq ORIG_RAX(%rsp),%rsi /* get error code */
movq $-1,ORIG_RAX(%rsp) /* no syscall to restart */
@@ -1092,7 +1099,7 @@ ENTRY(\sym)
subq $ORIG_RAX-R15, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call save_paranoid
- DEFAULT_FRAME 0
+ DEFAULT_FRAME -1
TRACE_IRQS_OFF
movq %rsp,%rdi /* pt_regs pointer */
movq ORIG_RAX(%rsp),%rsi /* get error code */
@@ -1435,25 +1442,24 @@ END(paranoid_exit)
* returns in "no swapgs flag" in %ebx.
*/
ENTRY(error_entry)
- XCPT_FRAME
- CFI_ADJUST_CFA_OFFSET 15*8
+ XCPT_FRAME offset=ORIG_RAX-R15+8
/* oldrax contains error code */
cld
- movq_cfi rdi, RDI+8
- movq_cfi rsi, RSI+8
- movq_cfi rdx, RDX+8
- movq_cfi rcx, RCX+8
- movq_cfi rax, RAX+8
- movq_cfi r8, R8+8
- movq_cfi r9, R9+8
- movq_cfi r10, R10+8
- movq_cfi r11, R11+8
+ movq %rdi, RDI+8(%rsp)
+ movq %rsi, RSI+8(%rsp)
+ movq %rdx, RDX+8(%rsp)
+ movq %rcx, RCX+8(%rsp)
+ movq %rax, RAX+8(%rsp)
+ movq %r8, R8+8(%rsp)
+ movq %r9, R9+8(%rsp)
+ movq %r10, R10+8(%rsp)
+ movq %r11, R11+8(%rsp)
movq_cfi rbx, RBX+8
- movq_cfi rbp, RBP+8
- movq_cfi r12, R12+8
- movq_cfi r13, R13+8
- movq_cfi r14, R14+8
- movq_cfi r15, R15+8
+ movq %rbp, RBP+8(%rsp)
+ movq %r12, R12+8(%rsp)
+ movq %r13, R13+8(%rsp)
+ movq %r14, R14+8(%rsp)
+ movq %r15, R15+8(%rsp)
xorl %ebx,%ebx
testl $3,CS+8(%rsp)
je error_kernelspace
@@ -1471,6 +1477,7 @@ error_sti:
* compat mode. Check for these here too.
*/
error_kernelspace:
+ CFI_REL_OFFSET rcx, RCX+8
incl %ebx
leaq irq_return(%rip),%rcx
cmpq %rcx,RIP+8(%rsp)
@@ -1518,7 +1523,7 @@ ENTRY(nmi)
subq $ORIG_RAX-R15, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call save_paranoid
- DEFAULT_FRAME 0
+ DEFAULT_FRAME -1
/* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
movq %rsp,%rdi
movq $-1,%rsi
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -284,6 +284,8 @@ early_idt_handlers:
ENTRY(early_idt_handler)
#ifdef CONFIG_EARLY_PRINTK
+#include <asm/calling.h>
+#include <asm/dwarf2.h>
cmpl $2,early_recursion_flag(%rip)
jz 1f
incl early_recursion_flag(%rip)
@@ -299,6 +301,16 @@ ENTRY(early_idt_handler)
testl $0x27d00,%eax
je 0f
popq %r8 # get error code
+
+ CFI_STARTPROC simple
+ CFI_SIGNAL_FRAME
+ CFI_DEF_CFA rsp, SS+8-RIP
+# CFI_REL_OFFSET ss, SS-RIP
+ CFI_REL_OFFSET rsp, RSP-RIP
+# CFI_REL_OFFSET rflags, EFLAGS-RIP
+# CFI_REL_OFFSET cs, CS-RIP
+ CFI_REL_OFFSET rip, RIP-RIP
+
0: movq 0(%rsp),%rcx # get ip
movq 8(%rsp),%rdx # get cs
xorl %eax,%eax
@@ -312,6 +324,7 @@ ENTRY(early_idt_handler)
movq 0(%rsp),%rsi # get rip again
call __print_symbol
#endif
+ CFI_ENDPROC
#endif /* EARLY_PRINTK */
1: hlt
jmp 1b
--- a/arch/x86/lib/rwsem_64.S
+++ b/arch/x86/lib/rwsem_64.S
@@ -23,43 +23,50 @@
#include <asm/dwarf2.h>
#define save_common_regs \
- pushq %rdi; \
- pushq %rsi; \
- pushq %rcx; \
- pushq %r8; \
- pushq %r9; \
- pushq %r10; \
- pushq %r11
+ pushq_cfi %rdi; CFI_REL_OFFSET rdi, 0; \
+ pushq_cfi %rsi; CFI_REL_OFFSET rsi, 0; \
+ pushq_cfi %rcx; CFI_REL_OFFSET rcx, 0; \
+ pushq_cfi %r8; CFI_REL_OFFSET r8, 0; \
+ pushq_cfi %r9; CFI_REL_OFFSET r9, 0; \
+ pushq_cfi %r10; CFI_REL_OFFSET r10, 0; \
+ pushq_cfi %r11; CFI_REL_OFFSET r11, 0
#define restore_common_regs \
- popq %r11; \
- popq %r10; \
- popq %r9; \
- popq %r8; \
- popq %rcx; \
- popq %rsi; \
- popq %rdi
+ popq_cfi %r11; CFI_RESTORE r11; \
+ popq_cfi %r10; CFI_RESTORE r10; \
+ popq_cfi %r9; CFI_RESTORE r9; \
+ popq_cfi %r8; CFI_RESTORE r8; \
+ popq_cfi %rcx; CFI_RESTORE rcx; \
+ popq_cfi %rsi; CFI_RESTORE rsi; \
+ popq_cfi %rdi; CFI_RESTORE rdi
/* Fix up special calling conventions */
ENTRY(call_rwsem_down_read_failed)
+ CFI_STARTPROC
save_common_regs
- pushq %rdx
+ pushq_cfi %rdx
+ CFI_REL_OFFSET rdx, 0
movq %rax,%rdi
call rwsem_down_read_failed
- popq %rdx
+ popq_cfi %rdx
+ CFI_RESTORE rdx
restore_common_regs
ret
- ENDPROC(call_rwsem_down_read_failed)
+ CFI_ENDPROC
+ENDPROC(call_rwsem_down_read_failed)
ENTRY(call_rwsem_down_write_failed)
+ CFI_STARTPROC
save_common_regs
movq %rax,%rdi
call rwsem_down_write_failed
restore_common_regs
ret
- ENDPROC(call_rwsem_down_write_failed)
+ CFI_ENDPROC
+ENDPROC(call_rwsem_down_write_failed)
ENTRY(call_rwsem_wake)
+ CFI_STARTPROC
decl %edx /* do nothing if still outstanding active readers */
jnz 1f
save_common_regs
@@ -67,15 +74,20 @@ ENTRY(call_rwsem_wake)
call rwsem_wake
restore_common_regs
1: ret
- ENDPROC(call_rwsem_wake)
+ CFI_ENDPROC
+ENDPROC(call_rwsem_wake)
/* Fix up special calling conventions */
ENTRY(call_rwsem_downgrade_wake)
+ CFI_STARTPROC
save_common_regs
- pushq %rdx
+ pushq_cfi %rdx
+ CFI_REL_OFFSET rdx, 0
movq %rax,%rdi
call rwsem_downgrade_wake
- popq %rdx
+ popq_cfi %rdx
+ CFI_RESTORE rdx
restore_common_regs
ret
- ENDPROC(call_rwsem_downgrade_wake)
+ CFI_ENDPROC
+ENDPROC(call_rwsem_downgrade_wake)

View File

@ -0,0 +1,74 @@
From: Brandon Philips <bphilips@suse.de>
Subject: Avoid oops on G33 in 1MB stolen Mem case
References: bnc#391261
Patch-Mainline: soon (see bug for ref)
This is similar to f443675affe3f16dd428e46f0f7fd3f4d703eeab which was
reverted because it broke with older XOrg driver. This patch only fixes
the 1MB stolen case since it causes an oops due to a calculation
problem.
This will not work with older X drivers without the accompanying patch
but I think avoiding an oops and making it possible to work with an
up-to-date xorg driver is reasonable.
Explanation of the oops:
> static void intel_i830_init_gtt_entries(void)
...
> } else if (IS_G33) {
> /* G33's GTT size defined in gmch_ctrl */
> switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
> case G33_PGETBL_SIZE_1M:
> size = 1024;
> break;
...
> size += 4;
size = 1028
Then since we have the BIOS setting 1MB for the device in the GMCH
control we get to here:
> } else {
> switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
> case I855_GMCH_GMS_STOLEN_1M:
> gtt_entries = MB(1) - KB(size);
> break;
MB(1) = 1 * 1024 * 1024
KB(1028) = 1028 * 1024
MB(1) - KB(1028) = -4096
> gtt_entries /= KB(4);
> intel_private.gtt_entries = gtt_entries;
We end up with -1 in gtt_entries.
This leads to intel_i915_configure reading/writing to areas outside of
mapped memory and the oops.
Signed-off-by: Brandon Philips <bphilips@suse.de>
Acked-by: Thomas Renninger <trenn@suse.de>
---
drivers/char/agp/intel-gtt.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -648,6 +648,13 @@ static void intel_i830_init_gtt_entries(
} else {
switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
case I855_GMCH_GMS_STOLEN_1M:
+ if (IS_G33) {
+ size = 0;
+ printk(KERN_WARNING PFX
+ "Warning: G33 chipset with 1MB"
+ " allocated. Older X.org Intel drivers"
+ " will not work.\n");
+ }
gtt_entries = MB(1) - KB(size);
break;
case I855_GMCH_GMS_STOLEN_4M:

View File

@ -0,0 +1,35 @@
From 4a122c10fbfe9020df469f0f669da129c5757671 Mon Sep 17 00:00:00 2001
From: Dan Rosenberg <drosenberg@vsecurity.com>
Date: Thu, 17 Mar 2011 18:32:24 -0400
Subject: [PATCH] ALSA: sound/pci/asihpi: check adapter index in hpi_ioctl
Git-commit: 4a122c10fbfe9020df469f0f669da129c5757671
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
Patch-mainline: 2.6.39-rc1
References: bnc#680816
The user-supplied index into the adapters array needs to be checked, or
an out-of-bounds kernel pointer could be accessed and used, leading to
potentially exploitable memory corruption.
Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>
Cc: <stable@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/asihpi/hpioctl.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/sound/pci/asihpi/hpioctl.c
+++ b/sound/pci/asihpi/hpioctl.c
@@ -155,6 +155,11 @@
goto out;
}
+ if (hm->h.adapter_index >= HPI_MAX_ADAPTERS) {
+ err = -EINVAL;
+ goto out;
+ }
+
pa = &adapters[hm->h.adapter_index];
hr->h.size = 0;
if (hm->h.object == HPI_OBJ_SUBSYSTEM) {

View File

@ -0,0 +1,96 @@
From c6b358748e19ce7e230b0926ac42696bc485a562 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 28 Mar 2011 12:05:31 +0200
Subject: [PATCH] ALSA: hda - Fix pin-config of Gigabyte mobo
Git-commit: c6b358748e19ce7e230b0926ac42696bc485a562
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
Patch-mainline: (to be) 2.6.39-rc2
References: bnc#677256
Use pin-fix instead of the static quirk for Gigabyte mobos 1458:a002.
Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=677256
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/patch_realtek.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -9932,7 +9932,6 @@ static struct snd_pci_quirk alc882_cfg_t
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
- SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
@@ -10769,6 +10768,7 @@ enum {
PINFIX_LENOVO_Y530,
PINFIX_PB_M5210,
PINFIX_ACER_ASPIRE_7736,
+ PINFIX_GIGABYTE_880GM,
};
static const struct alc_fixup alc882_fixups[] = {
@@ -10800,6 +10800,13 @@ static const struct alc_fixup alc882_fix
.type = ALC_FIXUP_SKU,
.v.sku = ALC_FIXUP_SKU_IGNORE,
},
+ [PINFIX_GIGABYTE_880GM] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x1114410 }, /* set as speaker */
+ { }
+ }
+ },
};
static struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -10807,6 +10814,7 @@ static struct snd_pci_quirk alc882_fixup
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
+ SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", PINFIX_GIGABYTE_880GM),
{}
};
@@ -18851,8 +18859,6 @@ static struct snd_pci_quirk alc662_cfg_t
ALC662_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
- SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
- ALC662_3ST_6ch_DIG),
SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
@@ -19526,6 +19532,7 @@ enum {
ALC662_FIXUP_IDEAPAD,
ALC272_FIXUP_MARIO,
ALC662_FIXUP_CZC_P10T,
+ ALC662_FIXUP_GIGABYTE,
};
static const struct alc_fixup alc662_fixups[] = {
@@ -19554,12 +19561,20 @@ static const struct alc_fixup alc662_fix
{}
}
},
+ [ALC662_FIXUP_GIGABYTE] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x1114410 }, /* set as speaker */
+ { }
+ }
+ },
};
static struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
+ SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", ALC662_FIXUP_GIGABYTE),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),

View File

@ -0,0 +1,22 @@
From: Takashi Iwai <tiwai@suse.de>
Subject: ALSA: hda - Increase the default buffer size
Patch-mainline: Never
References: 682725
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/hda/hda_intel.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2057,7 +2057,7 @@
/* buffer pre-allocation */
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
snd_dma_pci_data(chip->pci),
- 1024 * 64, 32 * 1024 * 1024);
+ 1024 * 1024, 32 * 1024 * 1024);
return 0;
}

View File

@ -0,0 +1,40 @@
From: Brandon Philips <bphilips@suse.de>
Subject: [PATCH] bnx2: entropy source
Patch-mainline: never
References: FATE#307517
Current disk-less systems have no entropy source whatsoever. Therefore, the
network drivers tg3, bnx2, e1000, e1000e, igb and ixgbe should be enabled to
feed entropy to the kernel via the IRQF_SAMPLE_RANDOM flag when loaded. This
option shall not be enabled by default but implemented via a module option to
be activated by the administrator.
Signed-off-by: Brandon Philips <bphilips@suse.de>
---
drivers/net/bnx2.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -84,6 +84,10 @@ MODULE_FIRMWARE(FW_MIPS_FILE_09);
MODULE_FIRMWARE(FW_RV2P_FILE_09);
MODULE_FIRMWARE(FW_RV2P_FILE_09_Ax);
+static int entropy = 0;
+module_param(entropy, int, 0);
+MODULE_PARM_DESC(entropy, "Allow bnx2 to populate the /dev/random entropy pool");
+
static int disable_msi = 0;
module_param(disable_msi, int, 0);
@@ -6116,6 +6120,9 @@ bnx2_request_irq(struct bnx2 *bp)
else
flags = IRQF_SHARED;
+ if (entropy)
+ flags |= IRQF_SAMPLE_RANDOM;
+
for (i = 0; i < bp->irq_nvecs; i++) {
irq = &bp->irq_tbl[i];
rc = request_irq(irq->vector, irq->handler, flags, irq->name,

View File

@ -0,0 +1,45 @@
From: Xiuling Ma <xma@us.ibm.com>
Subject: [PATCH] disable catas_reset by default to avoid problems with EEH
References: bnc#456389
Patch-mainline: not yet
PPC machines with EEH and Mellanox ib/net cards with catastrophic error
recovery that encounter a PCI bus error can crash and become
unresponsive.
Disable the card reset to avoid this.
NOTE: an upstream fix will come later once IBM can review a couple of
approaches I suggested since this fix is brute force. This driver didn't have
this reset on error feature in SLES10 so it isn't a feature removal.
Signed-off-by: Xiuling Ma <xma@us.ibm.com>
Acked-by: Brandon Philips <bphilips@suse.de>
---
drivers/infiniband/hw/mthca/mthca_catas.c | 2 +-
drivers/net/mlx4/catas.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/infiniband/hw/mthca/mthca_catas.c
+++ b/drivers/infiniband/hw/mthca/mthca_catas.c
@@ -51,7 +51,7 @@ static LIST_HEAD(catas_list);
static struct workqueue_struct *catas_wq;
static struct work_struct catas_work;
-static int catas_reset_disable;
+static int catas_reset_disable = 1;
module_param_named(catas_reset_disable, catas_reset_disable, int, 0644);
MODULE_PARM_DESC(catas_reset_disable, "disable reset on catastrophic event if nonzero");
--- a/drivers/net/mlx4/catas.c
+++ b/drivers/net/mlx4/catas.c
@@ -44,7 +44,7 @@ static DEFINE_SPINLOCK(catas_lock);
static LIST_HEAD(catas_list);
static struct work_struct catas_work;
-static int internal_err_reset = 1;
+static int internal_err_reset = 0;
module_param(internal_err_reset, int, 0644);
MODULE_PARM_DESC(internal_err_reset,
"Reset device on internal errors if non-zero (default 1)");

View File

@ -0,0 +1,47 @@
From: Jiri Benc <jbenc@suse.cz>
Subject: Enable e1000 as entropy source (disabled by default)
References: FATE#307517
Patch-mainline: never
Based on the patch by Oracle:
> e1000: Add IRQF_SAMPLE_RANDOM flag to e1000 as a module option
>
> This patch allows for the bnx2 to add to the /dev/random entropy pool
> via a module parameter, entropy.
>
> 0 - default for EL5 - do not populate the entropy pool
> 1 - optional - Uses IRQF_SAMPLE_RANDOM flag on request_irq calls to populate
> the /dev/random pool
>
> Signed-off-by: John Sobecki <john.sobecki@oracle.com>
Signed-off-by: Brandon Philips <bphilips@suse.de>
---
drivers/net/e1000/e1000_main.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -213,6 +213,10 @@ static int debug = NETIF_MSG_DRV | NETIF
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+static int entropy = 0;
+module_param(entropy, int, 0);
+MODULE_PARM_DESC(entropy, "Allow e1000 to populate the /dev/random entropy pool");
+
/**
* e1000_get_hw_dev - return device
* used by hardware layer to print debugging information
@@ -272,6 +276,9 @@ static int e1000_request_irq(struct e100
int irq_flags = IRQF_SHARED;
int err;
+ if (entropy)
+ irq_flags |= IRQF_SAMPLE_RANDOM;
+
err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
netdev);
if (err) {

View File

@ -0,0 +1,86 @@
From: Jiri Benc <jbenc@suse.cz>
Subject: Enable e1000e as entropy source (disabled by default)
References: FATE#307517
Patch-mainline: never
Current disk-less systems have no entropy source whatsoever. Therefore, the
network drivers tg3, bnx2, e1000, e1000e, igb and ixgbe should be enabled to
feed entropy to the kernel via the IRQF_SAMPLE_RANDOM flag when loaded. This
option shall not be enabled by default but implemented via a module option to
be activated by the administrator.
Signed-off-by: Brandon Philips <bphilips@suse.de>
---
drivers/net/e1000e/e1000.h | 1 +
drivers/net/e1000e/netdev.c | 14 +++++++++-----
drivers/net/e1000e/param.c | 4 ++++
3 files changed, 14 insertions(+), 5 deletions(-)
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -467,6 +467,7 @@ extern void e1000e_reset_interrupt_capab
extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);
extern unsigned int copybreak;
+extern int entropy;
extern char *e1000e_get_hw_dev_name(struct e1000_hw *hw);
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -1847,8 +1847,8 @@ static int e1000_request_msix(struct e10
else
memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ);
err = request_irq(adapter->msix_entries[vector].vector,
- e1000_intr_msix_rx, 0, adapter->rx_ring->name,
- netdev);
+ e1000_intr_msix_rx, entropy ? IRQF_SAMPLE_RANDOM : 0,
+ adapter->rx_ring->name, netdev);
if (err)
goto out;
adapter->rx_ring->itr_register = E1000_EITR_82574(vector);
@@ -1889,6 +1889,7 @@ static int e1000_request_irq(struct e100
{
struct net_device *netdev = adapter->netdev;
int err;
+ int irq_flags = 0;
if (adapter->msix_entries) {
err = e1000_request_msix(adapter);
@@ -1900,7 +1901,8 @@ static int e1000_request_irq(struct e100
e1000e_set_interrupt_capability(adapter);
}
if (adapter->flags & FLAG_MSI_ENABLED) {
- err = request_irq(adapter->pdev->irq, e1000_intr_msi, 0,
+ err = request_irq(adapter->pdev->irq, e1000_intr_msi,
+ entropy ? IRQF_SAMPLE_RANDOM : 0,
netdev->name, netdev);
if (!err)
return err;
@@ -1910,8 +1912,10 @@ static int e1000_request_irq(struct e100
adapter->int_mode = E1000E_INT_MODE_LEGACY;
}
- err = request_irq(adapter->pdev->irq, e1000_intr, IRQF_SHARED,
- netdev->name, netdev);
+ if (entropy)
+ irq_flags |= IRQF_SAMPLE_RANDOM;
+ err = request_irq(adapter->pdev->irq, e1000_intr,
+ irq_flags | IRQF_SHARED, netdev->name, netdev);
if (err)
e_err("Unable to allocate interrupt, Error: %d\n", err);
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -31,6 +31,10 @@
#include "e1000.h"
+int entropy = 0;
+module_param(entropy, int, 0);
+MODULE_PARM_DESC(entropy, "Allow e1000e to populate the /dev/random entropy pool");
+
/*
* This is the only thing that needs to be changed to adjust the
* maximum number of ports that the driver can manage.

View File

@ -0,0 +1,43 @@
Subject: add alias entry for portN properties
From: olh@suse.de
References: 435215 - LTC48564
Patch-mainline: not yet
Use separate table for alias entries in the ehea module,
otherwise the probe() function will operate on the separate ports
instead of the lhea-"root" entry of the device-tree
---
drivers/net/ehea/ehea_main.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -112,6 +112,19 @@ static int __devinit ehea_probe_adapter(
static int __devexit ehea_remove(struct platform_device *dev);
+static struct of_device_id ehea_module_device_table[] = {
+ {
+ .name = "lhea",
+ .compatible = "IBM,lhea",
+ },
+ {
+ .type = "network",
+ .compatible = "IBM,lhea-ethernet",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ehea_module_device_table);
+
static struct of_device_id ehea_device_table[] = {
{
.name = "lhea",
@@ -119,7 +132,6 @@ static struct of_device_id ehea_device_t
},
{},
};
-MODULE_DEVICE_TABLE(of, ehea_device_table);
static struct of_platform_driver ehea_driver = {
.driver = {

View File

@ -0,0 +1,380 @@
From: Jiri Kosina <jkosina@suse.cz>
Subject: Elo USB touchscreen driver
Patch-mainline: will be submitted for 2.6.28
References: FATE#304972
This is a driver for Elo USB touchscreen devices.
Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
Acked-by: Jiri Kosina <jkosina@suse.cz>
---
drivers/hid/hid-core.c | 2
drivers/hid/hid-ids.h | 2
drivers/input/touchscreen/Kconfig | 12 +
drivers/input/touchscreen/Makefile | 1
drivers/input/touchscreen/elousb.c | 305 +++++++++++++++++++++++++++++++++++++
5 files changed, 322 insertions(+)
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1643,6 +1643,8 @@ static const struct hid_device_id hid_ig
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_4000U) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_4500U) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -216,7 +216,9 @@
#define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34
#define USB_VENDOR_ID_ELO 0x04E7
+#define USB_DEVICE_ID_ELO_4000U 0x0009
#define USB_DEVICE_ID_ELO_TS2700 0x0020
+#define USB_DEVICE_ID_ELO_4500U 0x0030
#define USB_VENDOR_ID_EMS 0x2006
#define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -214,6 +214,18 @@ config TOUCHSCREEN_ELO
To compile this driver as a module, choose M here: the
module will be called elo.
+config TOUCHSCREEN_ELOUSB
+ tristate "Elo USB touchscreens"
+ select USB
+ help
+ Say Y here if you have an Elo USB touchscreen connected to
+ your system.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called elousb.
+
config TOUCHSCREEN_WACOM_W8001
tristate "Wacom W8001 penabled serial touchscreen"
select SERIO
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += h
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
+obj-$(CONFIG_TOUCHSCREEN_ELOUSB) += elousb.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
--- /dev/null
+++ b/drivers/input/touchscreen/elousb.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 1999-2001 Vojtech Pavlik
+ *
+ * Elo USB touchscreen support
+ */
+
+/*
+ * 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.
+ *
+ * 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
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.1"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "Elo USB touchscreen driver"
+#define DRIVER_LICENSE "GPL"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+struct elousb {
+ char name[128];
+ char phys[64];
+ struct usb_device *usbdev;
+ struct input_dev *dev;
+ struct urb *irq;
+
+ unsigned char *data;
+ dma_addr_t data_dma;
+};
+
+static void elousb_irq(struct urb *urb)
+{
+ struct elousb *elo = urb->context;
+ unsigned char *data = elo->data;
+ struct input_dev *dev = elo->dev;
+ int status;
+
+ switch (urb->status) {
+ case 0: /* success */
+ break;
+ case -ECONNRESET: /* unlink */
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ /* -EPIPE: should clear the halt */
+ default: /* error */
+ goto resubmit;
+ }
+
+ if (data[0] != 'T') /* Mandatory ELO packet marker */
+ return;
+
+
+ input_report_abs(dev, ABS_X, ((u32)data[3] << 8) | data[2]);
+ input_report_abs(dev, ABS_Y, ((u32)data[5] << 8) | data[4]);
+
+ input_report_abs(dev, ABS_PRESSURE,
+ (data[1] & 0x80) ? (((u32)data[7] << 8) | data[6]): 0);
+
+ if (data[1] & 0x03) {
+ input_report_key(dev, BTN_TOUCH, 1);
+ input_sync(dev);
+ }
+
+ if (data[1] & 0x04)
+ input_report_key(dev, BTN_TOUCH, 0);
+
+ input_sync(dev);
+
+resubmit:
+ status = usb_submit_urb (urb, GFP_ATOMIC);
+ if (status)
+ err ("can't resubmit intr, %s-%s/input0, status %d",
+ elo->usbdev->bus->bus_name,
+ elo->usbdev->devpath, status);
+}
+
+static int elousb_open(struct input_dev *dev)
+{
+ struct elousb *elo = input_get_drvdata(dev);
+
+ elo->irq->dev = elo->usbdev;
+ if (usb_submit_urb(elo->irq, GFP_KERNEL))
+ return -EIO;
+
+ return 0;
+}
+
+static void elousb_close(struct input_dev *dev)
+{
+ struct elousb *elo = input_get_drvdata(dev);
+
+ usb_kill_urb(elo->irq);
+}
+
+static int elousb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+ struct hid_descriptor *hdesc;
+ struct elousb *elo;
+ struct input_dev *input_dev;
+ int pipe, i;
+ unsigned int rsize = 0;
+ int error = -ENOMEM;
+ char *rdesc;
+
+ interface = intf->cur_altsetting;
+
+ if (interface->desc.bNumEndpoints != 1)
+ return -ENODEV;
+
+ endpoint = &interface->endpoint[0].desc;
+ if (!(endpoint->bEndpointAddress & USB_DIR_IN))
+ return -ENODEV;
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+ return -ENODEV;
+
+ if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
+ (!interface->desc.bNumEndpoints ||
+ usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
+ err("HID class descriptor not present");
+ return -ENODEV;
+ }
+
+ for (i = 0; i < hdesc->bNumDescriptors; i++)
+ if (hdesc->desc[i].bDescriptorType == HID_DT_REPORT)
+ rsize = le16_to_cpu(hdesc->desc[i].wDescriptorLength);
+
+ if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
+ err("weird size of report descriptor (%u)", rsize);
+ return -ENODEV;
+ }
+
+
+ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+
+ elo = kzalloc(sizeof(struct elousb), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!elo || !input_dev)
+ goto fail1;
+
+ elo->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &elo->data_dma);
+ if (!elo->data)
+ goto fail1;
+
+ elo->irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!elo->irq)
+ goto fail2;
+
+ if (!(rdesc = kmalloc(rsize, GFP_KERNEL)))
+ goto fail3;
+
+ elo->usbdev = dev;
+ elo->dev = input_dev;
+
+ if ((error = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
+ interface->desc.bInterfaceNumber,
+ NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
+ err("setting HID idle timeout failed, error %d", error);
+ error = -ENODEV;
+ goto fail4;
+ }
+
+ if ((error = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
+ HID_DT_REPORT << 8, interface->desc.bInterfaceNumber,
+ rdesc, rsize, USB_CTRL_GET_TIMEOUT)) < rsize) {
+ err("reading HID report descriptor failed, error %d", error);
+ error = -ENODEV;
+ goto fail4;
+ }
+
+ if (dev->manufacturer)
+ strlcpy(elo->name, dev->manufacturer, sizeof(elo->name));
+
+ if (dev->product) {
+ if (dev->manufacturer)
+ strlcat(elo->name, " ", sizeof(elo->name));
+ strlcat(elo->name, dev->product, sizeof(elo->name));
+ }
+
+ if (!strlen(elo->name))
+ snprintf(elo->name, sizeof(elo->name),
+ "Elo touchscreen %04x:%04x",
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
+
+ usb_make_path(dev, elo->phys, sizeof(elo->phys));
+ strlcat(elo->phys, "/input0", sizeof(elo->phys));
+
+ input_dev->name = elo->name;
+ input_dev->phys = elo->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->dev.parent = &intf->dev;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ set_bit(BTN_TOUCH, input_dev->keybit);
+ input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ set_bit(ABS_PRESSURE, input_dev->absbit);
+
+ input_set_abs_params(input_dev, ABS_X, 0, 4000, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 3840, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 256, 0, 0);
+
+ input_set_drvdata(input_dev, elo);
+
+ input_dev->open = elousb_open;
+ input_dev->close = elousb_close;
+
+ usb_fill_int_urb(elo->irq, dev, pipe, elo->data, 8,
+ elousb_irq, elo, endpoint->bInterval);
+ elo->irq->transfer_dma = elo->data_dma;
+ elo->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ input_register_device(elo->dev);
+
+ usb_set_intfdata(intf, elo);
+ return 0;
+
+fail4:
+ kfree(rdesc);
+fail3:
+ usb_free_urb(elo->irq);
+fail2:
+ usb_buffer_free(dev, 8, elo->data, elo->data_dma);
+fail1:
+ input_free_device(input_dev);
+ kfree(elo);
+ return -ENOMEM;
+}
+
+static void elousb_disconnect(struct usb_interface *intf)
+{
+ struct elousb *elo = usb_get_intfdata (intf);
+
+ usb_set_intfdata(intf, NULL);
+ if (elo) {
+ usb_kill_urb(elo->irq);
+ input_unregister_device(elo->dev);
+ usb_free_urb(elo->irq);
+ usb_buffer_free(interface_to_usbdev(intf), 8, elo->data, elo->data_dma);
+ kfree(elo);
+ }
+}
+
+static struct usb_device_id elousb_id_table [] = {
+ { USB_DEVICE(0x04e7, 0x0009) }, /* CarrolTouch 4000U */
+ { USB_DEVICE(0x04e7, 0x0030) }, /* CarrolTouch 4500U */
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, elousb_id_table);
+
+static struct usb_driver elousb_driver = {
+ .name = "elousb",
+ .probe = elousb_probe,
+ .disconnect = elousb_disconnect,
+ .id_table = elousb_id_table,
+};
+
+static int __init elousb_init(void)
+{
+ int retval = usb_register(&elousb_driver);
+ if (retval == 0)
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC);
+ return retval;
+}
+
+static void __exit elousb_exit(void)
+{
+ usb_deregister(&elousb_driver);
+}
+
+module_init(elousb_init);
+module_exit(elousb_exit);

View File

@ -0,0 +1,70 @@
From: Jiri Benc <jbenc@suse.cz>
Subject: Enable igb as entropy source (disabled by default)
References: FATE#307517
Patch-mainline: never
Current disk-less systems have no entropy source whatsoever. Therefore, the
network drivers tg3, bnx2, e1000, e1000e, igb and ixgbe should be enabled to
feed entropy to the kernel via the IRQF_SAMPLE_RANDOM flag when loaded. This
option shall not be enabled by default but implemented via a module option to
be activated by the administrator.
Signed-off-by: Brandon Philips <bphilips@suse.de>
---
drivers/net/igb/igb_main.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -61,6 +61,10 @@ static const struct e1000_info *igb_info
[board_82575] = &e1000_82575_info,
};
+static int entropy = 0;
+module_param(entropy, int, 0);
+MODULE_PARM_DESC(entropy, "Allow igb to populate the /dev/random entropy pool");
+
static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_COPPER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_FIBER), board_82575 },
@@ -897,7 +901,8 @@ static int igb_request_msix(struct igb_a
int i, err = 0, vector = 0;
err = request_irq(adapter->msix_entries[vector].vector,
- igb_msix_other, 0, netdev->name, adapter);
+ igb_msix_other, entropy ? IRQF_SAMPLE_RANDOM : 0,
+ netdev->name, adapter);
if (err)
goto out;
vector++;
@@ -1194,6 +1199,10 @@ static int igb_request_irq(struct igb_ad
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
int err = 0;
+ int irq_flags = 0;
+
+ if (entropy)
+ irq_flags = IRQF_SAMPLE_RANDOM;
if (adapter->msix_entries) {
err = igb_request_msix(adapter);
@@ -1228,7 +1237,7 @@ static int igb_request_irq(struct igb_ad
}
if (adapter->flags & IGB_FLAG_HAS_MSI) {
- err = request_irq(adapter->pdev->irq, igb_intr_msi, 0,
+ err = request_irq(adapter->pdev->irq, igb_intr_msi, irq_flags,
netdev->name, adapter);
if (!err)
goto request_done;
@@ -1238,7 +1247,8 @@ static int igb_request_irq(struct igb_ad
adapter->flags &= ~IGB_FLAG_HAS_MSI;
}
- err = request_irq(adapter->pdev->irq, igb_intr, IRQF_SHARED,
+ irq_flags |= IRQF_SHARED;
+ err = request_irq(adapter->pdev->irq, igb_intr, irq_flags,
netdev->name, adapter);
if (err)

View File

@ -0,0 +1,218 @@
From: Takashi Iwai <tiwai@suse.de>
Subject: [PATCH 2/2] input: Add LED support to Synaptics device
Patch-mainline: Submitted
References: bnc#547370,bnc#582529,bnc#589014
The new Synaptics devices have an LED on the top-left corner.
This patch adds a new LED class device to control it. It's created
dynamically upon synaptics device probing.
The LED is controlled via the command 0x0a with parameters 0x88 or 0x10.
This seems only on/off control although other value might be accepted.
The detection of the LED isn't clear yet. It should have been the new
capability bits that indicate the presence, but on real machines, it
doesn't fit. So, for the time being, the driver checks the product id
in the ext capability bits and assumes that LED exists on the known
devices.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
drivers/input/mouse/Kconfig | 9 +++
drivers/input/mouse/synaptics.c | 111 ++++++++++++++++++++++++++++++++++++++++
drivers/input/mouse/synaptics.h | 3 +
3 files changed, 123 insertions(+)
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -19,6 +19,7 @@ config MOUSE_PS2
select SERIO_LIBPS2
select SERIO_I8042 if X86
select SERIO_GSCPS2 if GSC
+ select LEDS_CLASS if MOUSE_PS2_SYNAPICS_LED
help
Say Y here if you have a PS/2 mouse connected to your system. This
includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
@@ -67,6 +68,14 @@ config MOUSE_PS2_SYNAPTICS
If unsure, say Y.
+config MOUSE_PS2_SYNAPTICS_LED
+ bool "Support embedded LED on Synaptics devices"
+ depends on MOUSE_PS2_SYNAPTICS
+ select NEW_LEDS
+ help
+ Say Y here if you have a Synaptics device with an embedded LED.
+ This will enable LED class driver to control the LED device.
+
config MOUSE_PS2_LIFEBOOK
bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT
default y
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -28,6 +28,7 @@
#include <linux/input/mt.h>
#include <linux/serio.h>
#include <linux/libps2.h>
+#include <linux/leds.h>
#include <linux/slab.h>
#include "psmouse.h"
#include "synaptics.h"
@@ -353,6 +354,110 @@ static void synaptics_pt_create(struct p
serio_register_port(serio);
}
+#ifdef CONFIG_MOUSE_PS2_SYNAPTICS_LED
+/*
+ * LED handling:
+ * Some Synaptics devices have an embeded LED at the top-left corner.
+ */
+
+struct synaptics_led {
+ struct psmouse *psmouse;
+ struct work_struct work;
+ struct led_classdev cdev;
+};
+
+static void synaptics_set_led(struct psmouse *psmouse, int on)
+{
+ int i;
+ unsigned char cmd = on ? 0x88 : 0x10;
+
+ ps2_begin_command(&psmouse->ps2dev);
+ if (__ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11))
+ goto out;
+ for (i = 6; i >= 0; i -= 2) {
+ unsigned char d = (cmd >> i) & 3;
+ if (__ps2_command(&psmouse->ps2dev, &d, PSMOUSE_CMD_SETRES))
+ goto out;
+ }
+ cmd = 0x0a;
+ __ps2_command(&psmouse->ps2dev, &cmd, PSMOUSE_CMD_SETRATE);
+ out:
+ ps2_end_command(&psmouse->ps2dev);
+}
+
+static void synaptics_led_work(struct work_struct *work)
+{
+ struct synaptics_led *led;
+
+ led = container_of(work, struct synaptics_led, work);
+ synaptics_set_led(led->psmouse, led->cdev.brightness);
+}
+
+static void synaptics_led_cdev_brightness_set(struct led_classdev *cdev,
+ enum led_brightness value)
+{
+ struct synaptics_led *led;
+
+ led = container_of(cdev, struct synaptics_led, cdev);
+ schedule_work(&led->work);
+}
+
+static void synaptics_sync_led(struct psmouse *psmouse)
+{
+ struct synaptics_data *priv = psmouse->private;
+
+ if (priv->led)
+ synaptics_set_led(psmouse, priv->led->cdev.brightness);
+}
+
+static int synaptics_init_led(struct psmouse *psmouse)
+{
+ struct synaptics_data *priv = psmouse->private;
+ struct synaptics_led *led;
+ int err;
+
+ /* FIXME: LED is supposedly detectable in cap0c[1] 0x20, but it seems
+ * not working on real machines.
+ * So we check the product id to be sure.
+ */
+ if (!priv->ext_cap_0c || SYN_CAP_PRODUCT_ID(priv->ext_cap) != 0xe4)
+ return 0;
+
+ printk(KERN_INFO "synaptics: support LED control\n");
+ led = kzalloc(sizeof(struct synaptics_led), GFP_KERNEL);
+ if (!led)
+ return -ENOMEM;
+ led->psmouse = psmouse;
+ INIT_WORK(&led->work, synaptics_led_work);
+ led->cdev.name = "psmouse::synaptics";
+ led->cdev.brightness_set = synaptics_led_cdev_brightness_set;
+ led->cdev.flags = LED_CORE_SUSPENDRESUME;
+ err = led_classdev_register(NULL, &led->cdev);
+ if (err < 0) {
+ kfree(led);
+ return err;
+ }
+ priv->led = led;
+ return 0;
+}
+
+static void synaptics_free_led(struct psmouse *psmouse)
+{
+ struct synaptics_data *priv = psmouse->private;
+
+ if (!priv->led)
+ return;
+ cancel_work_sync(&priv->led->work);
+ synaptics_set_led(psmouse, 0);
+ led_classdev_unregister(&priv->led->cdev);
+ kfree(priv->led);
+}
+#else
+#define synaptics_init_led(ps) 0
+#define synaptics_free_led(ps) do {} while (0)
+#define synaptics_sync_led(ps) do {} while (0)
+#endif
+
/*****************************************************************************
* Functions to interpret the absolute mode packets
****************************************************************************/
@@ -647,6 +752,7 @@ static void set_input_params(struct inpu
static void synaptics_disconnect(struct psmouse *psmouse)
{
+ synaptics_free_led(psmouse);
synaptics_reset(psmouse);
kfree(psmouse->private);
psmouse->private = NULL;
@@ -678,6 +784,8 @@ static int synaptics_reconnect(struct ps
return -1;
}
+ synaptics_sync_led(psmouse);
+
return 0;
}
@@ -752,6 +860,9 @@ int synaptics_init(struct psmouse *psmou
SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
+ if (synaptics_init_led(psmouse) < 0)
+ goto init_fail;
+
set_input_params(psmouse->dev, priv);
/*
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -97,6 +97,8 @@ struct synaptics_hw_state {
signed char scroll;
};
+struct synaptics_led;
+
struct synaptics_data {
/* Data read from the touchpad */
unsigned long int model_id; /* Model-ID */
@@ -110,6 +112,7 @@ struct synaptics_data {
struct serio *pt_port; /* Pass-through serio port */
struct synaptics_hw_state mt; /* current gesture packet */
+ struct synaptics_led *led;
};
void synaptics_module_init(void);

View File

@ -0,0 +1,90 @@
From: Jiri Benc <jbenc@suse.cz>
Subject: Enable ixgbe as entropy source (disabled by default)
References: FATE#307517
Patch-mainline: never
Current disk-less systems have no entropy source whatsoever. Therefore, the
network drivers tg3, bnx2, e1000, e1000e, igb and ixgbe should be enabled to
feed entropy to the kernel via the IRQF_SAMPLE_RANDOM flag when loaded. This
option shall not be enabled by default but implemented via a module option to
be activated by the administrator.
Signed-off-by: Brandon Philips <bphilips@suse.de>
---
drivers/net/ixgbe/ixgbe_main.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -56,6 +56,11 @@ static const char ixgbe_driver_string[]
const char ixgbe_driver_version[] = DRV_VERSION;
static char ixgbe_copyright[] = "Copyright (c) 1999-2010 Intel Corporation.";
+static int entropy = 0;
+module_param(entropy, int, 0);
+MODULE_PARM_DESC(entropy, "Allow ixgbe to populate the /dev/random entropy pool");
+
+
static const struct ixgbe_info *ixgbe_info_tbl[] = {
[board_82598] = &ixgbe_82598_info,
[board_82599] = &ixgbe_82599_info,
@@ -2317,6 +2322,7 @@ static int ixgbe_request_msix_irqs(struc
irqreturn_t (*handler)(int, void *);
int i, vector, q_vectors, err;
int ri = 0, ti = 0;
+ int irq_flags;
/* Decrement for Other and TCP Timer vectors */
q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
@@ -2334,22 +2340,27 @@ static int ixgbe_request_msix_irqs(struc
struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];
handler = SET_HANDLER(q_vector);
+ irq_flags = 0;
if (handler == &ixgbe_msix_clean_rx) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
"%s-%s-%d", netdev->name, "rx", ri++);
+ if (entropy)
+ irq_flags = IRQF_SAMPLE_RANDOM;
} else if (handler == &ixgbe_msix_clean_tx) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
"%s-%s-%d", netdev->name, "tx", ti++);
} else if (handler == &ixgbe_msix_clean_many) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
"%s-%s-%d", netdev->name, "TxRx", ri++);
+ if (entropy)
+ irq_flags = IRQF_SAMPLE_RANDOM;
ti++;
} else {
/* skip this unused q_vector */
continue;
}
err = request_irq(adapter->msix_entries[vector].vector,
- handler, 0, q_vector->name,
+ handler, irq_flags, q_vector->name,
q_vector);
if (err) {
e_err(probe, "request_irq failed for MSIX interrupt "
@@ -2563,14 +2574,19 @@ static int ixgbe_request_irq(struct ixgb
{
struct net_device *netdev = adapter->netdev;
int err;
+ int irq_flags = 0;
+
+ if (entropy)
+ irq_flags = IRQF_SAMPLE_RANDOM;
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
err = ixgbe_request_msix_irqs(adapter);
} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
- err = request_irq(adapter->pdev->irq, ixgbe_intr, 0,
+ err = request_irq(adapter->pdev->irq, ixgbe_intr, irq_flags,
netdev->name, netdev);
} else {
- err = request_irq(adapter->pdev->irq, ixgbe_intr, IRQF_SHARED,
+ irq_flags |= IRQF_SHARED;
+ err = request_irq(adapter->pdev->irq, ixgbe_intr, irq_flags,
netdev->name, netdev);
}

View File

@ -0,0 +1,24 @@
From: Tejun Heo <teheo@suse.de>
Subject: [PATCH] libata: unlock HPA by default
References: 299267
Patch-mainline: not yet
Unlock HPA by default. This is to stay compatible with the old IDE
drivers.
Signed-off-by: Tejun Heo <teheo@suse.de>
---
drivers/ata/libata-core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -138,7 +138,7 @@ int libata_fua = 0;
module_param_named(fua, libata_fua, int, 0444);
MODULE_PARM_DESC(fua, "FUA support (0=off [default], 1=on)");
-static int ata_ignore_hpa;
+static int ata_ignore_hpa = 1;
module_param_named(ignore_hpa, ata_ignore_hpa, int, 0644);
MODULE_PARM_DESC(ignore_hpa, "Ignore HPA limit (0=keep BIOS limits, 1=ignore limits, using full disk)");

View File

@ -0,0 +1,70 @@
From: Martin Wilck <martin.wilck@fujitsu-siemens.com>
Subject: megaraid_mbox: Oops on SG_IO
References: bnc#475619
Patch-mainline: not yet
This patch fixes an Oops in megaraid_mbox that happens when a
MODE_SENSE command for a logical drive is started viaioctl(SG_IO).
The problem only occurs if the buffer specified by the user to receive
the mode data resides in highmem and if the buffer is aligned for
direct dma (no bounce buffer necessary). megaraid_mbox emulates
the MODE_SENSE command and writes the data using memset() directly
into user buffer. If the buffer is at a currently unmapped highmem
page, this leads to an Oops.
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/megaraid/megaraid_mbox.c | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -1586,13 +1586,20 @@ megaraid_mbox_build_cmd(adapter_t *adapt
case MODE_SENSE:
{
struct scatterlist *sgl;
- caddr_t vaddr;
+ struct page *pg;
+ unsigned char *vaddr;
+ unsigned long flags;
sgl = scsi_sglist(scp);
- if (sg_page(sgl)) {
- vaddr = (caddr_t) sg_virt(&sgl[0]);
+ pg = sg_page(sgl);
+ if (pg) {
+ local_irq_save(flags);
+ vaddr = kmap_atomic(pg, KM_BIO_SRC_IRQ) + sgl->offset;
memset(vaddr, 0, scp->cmnd[4]);
+
+ kunmap_atomic(vaddr, KM_BIO_SRC_IRQ);
+ local_irq_restore(flags);
}
else {
con_log(CL_ANN, (KERN_WARNING
@@ -2330,9 +2337,20 @@ megaraid_mbox_dpc(unsigned long devp)
if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0
&& IS_RAID_CH(raid_dev, scb->dev_channel)) {
+ struct page *pg;
+ unsigned char *vaddr;
+ unsigned long flags;
+
sgl = scsi_sglist(scp);
- if (sg_page(sgl)) {
- c = *(unsigned char *) sg_virt(&sgl[0]);
+ pg = sg_page(sgl);
+ if (pg) {
+ local_irq_save(flags);
+ vaddr = kmap_atomic(pg, KM_BIO_SRC_IRQ) + sgl->offset;
+
+ c = *vaddr;
+
+ kunmap_atomic(vaddr, KM_BIO_SRC_IRQ);
+ local_irq_restore(flags);
} else {
con_log(CL_ANN, (KERN_WARNING
"megaraid mailbox: invalid sg:%d\n",

File diff suppressed because it is too large Load Diff

53
patches.drivers/ppc64-adb Normal file
View File

@ -0,0 +1,53 @@
From: Olaf Hering <olh@suse.de>
Subject: enable mouse button emulation also for G5
Patch-mainline: never
fix compile errors
drivers/macintosh/Kconfig | 2 +-
drivers/macintosh/adb.c | 4 ++++
drivers/macintosh/adbhid.c | 6 +++++-
3 files changed, 10 insertions(+), 2 deletions(-)
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -13,7 +13,7 @@ if MACINTOSH_DRIVERS
config ADB
bool "Apple Desktop Bus (ADB) support"
- depends on MAC || (PPC_PMAC && PPC32)
+ depends on MAC || PPC_PMAC
help
Apple Desktop Bus (ADB) support is for support of devices which
are connected to an ADB port. ADB devices tend to have 4 pins.
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -298,6 +298,10 @@ static int __init adb_init(void)
if (!machine_is(chrp) && !machine_is(powermac))
return 0;
#endif
+#ifdef CONFIG_PPC64
+ if (!machine_is(powermac))
+ return 0;
+#endif
#ifdef CONFIG_MAC
if (!MACH_IS_MAC)
return 0;
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -1264,10 +1264,14 @@ init_ms_a3(int id)
static int __init adbhid_init(void)
{
-#ifndef CONFIG_MAC
+#ifdef CONFIG_PPC32
if (!machine_is(chrp) && !machine_is(powermac))
return 0;
#endif
+#ifdef CONFIG_PPC64
+ if (!machine_is(powermac))
+ return 0;
+#endif
led_request.complete = 1;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,707 @@
From foo@baz Wed Feb 9 13:35:10 PST 2011
Date: Wed, 09 Feb 2011 13:35:10 -0800
To: Greg KH <greg@kroah.com>
From: Greg Kroah-Hartman <gregkh@suse.de>
Subject: Staging: samsung-laptop: add support for lots of laptops
References: bnc#661682
Patch-mainline: 2.6.39
This is a backport of the upstream version of the driver that added support for
all samsung laptop devices.
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c
index 701e8d5..51ec621 100644
--- a/drivers/staging/samsung-laptop/samsung-laptop.c
+++ b/drivers/staging/samsung-laptop/samsung-laptop.c
@@ -1,5 +1,5 @@
/*
- * Samsung N130 Laptop driver
+ * Samsung Laptop driver
*
* Copyright (C) 2009 Greg Kroah-Hartman (gregkh@suse.de)
* Copyright (C) 2009 Novell Inc.
@@ -33,51 +33,6 @@
*/
#define MAX_BRIGHT 0x07
-/* Brightness is 0 - 8, as described above. Value 0 is for the BIOS to use */
-#define GET_BRIGHTNESS 0x00
-#define SET_BRIGHTNESS 0x01
-
-/* first byte:
- * 0x00 - wireless is off
- * 0x01 - wireless is on
- * second byte:
- * 0x02 - 3G is off
- * 0x03 - 3G is on
- * TODO, verify 3G is correct, that doesn't seem right...
- */
-#define GET_WIRELESS_BUTTON 0x02
-#define SET_WIRELESS_BUTTON 0x03
-
-/* 0 is off, 1 is on */
-#define GET_BACKLIGHT 0x04
-#define SET_BACKLIGHT 0x05
-
-/*
- * 0x80 or 0x00 - no action
- * 0x81 - recovery key pressed
- */
-#define GET_RECOVERY_METHOD 0x06
-#define SET_RECOVERY_METHOD 0x07
-
-/* 0 is low, 1 is high */
-#define GET_PERFORMANCE_LEVEL 0x08
-#define SET_PERFORMANCE_LEVEL 0x09
-
-/*
- * Tell the BIOS that Linux is running on this machine.
- * 81 is on, 80 is off
- */
-#define SET_LINUX 0x0a
-
-
-#define MAIN_FUNCTION 0x4c49
-
-#define SABI_HEADER_PORT 0x00
-#define SABI_HEADER_RE_MEM 0x02
-#define SABI_HEADER_IFACEFUNC 0x03
-#define SABI_HEADER_EN_MEM 0x04
-#define SABI_HEADER_DATA_OFFSET 0x05
-#define SABI_HEADER_DATA_SEGMENT 0x07
#define SABI_IFACE_MAIN 0x00
#define SABI_IFACE_SUB 0x02
@@ -89,6 +44,173 @@ struct sabi_retval {
u8 retval[20];
};
+struct sabi_header_offsets {
+ u8 port;
+ u8 re_mem;
+ u8 iface_func;
+ u8 en_mem;
+ u8 data_offset;
+ u8 data_segment;
+};
+
+struct sabi_commands {
+ /*
+ * Brightness is 0 - 8, as described above.
+ * Value 0 is for the BIOS to use
+ */
+ u8 get_brightness;
+ u8 set_brightness;
+
+ /*
+ * first byte:
+ * 0x00 - wireless is off
+ * 0x01 - wireless is on
+ * second byte:
+ * 0x02 - 3G is off
+ * 0x03 - 3G is on
+ * TODO, verify 3G is correct, that doesn't seem right...
+ */
+ u8 get_wireless_button;
+ u8 set_wireless_button;
+
+ /* 0 is off, 1 is on */
+ u8 get_backlight;
+ u8 set_backlight;
+
+ /*
+ * 0x80 or 0x00 - no action
+ * 0x81 - recovery key pressed
+ */
+ u8 get_recovery_mode;
+ u8 set_recovery_mode;
+
+ /*
+ * on seclinux: 0 is low, 1 is high,
+ * on swsmi: 0 is normal, 1 is silent, 2 is turbo
+ */
+ u8 get_performance_level;
+ u8 set_performance_level;
+
+ /*
+ * Tell the BIOS that Linux is running on this machine.
+ * 81 is on, 80 is off
+ */
+ u8 set_linux;
+};
+
+struct sabi_performance_level {
+ const char *name;
+ u8 value;
+};
+
+struct sabi_config {
+ const char *test_string;
+ u16 main_function;
+ struct sabi_header_offsets header_offsets;
+ struct sabi_commands commands;
+ struct sabi_performance_level performance_levels[4];
+};
+
+static struct sabi_config sabi_configs[] = {
+ {
+ .test_string = "SECLINUX",
+
+ .main_function = 0x4c59,
+
+ .header_offsets = {
+ .port = 0x00,
+ .re_mem = 0x02,
+ .iface_func = 0x03,
+ .en_mem = 0x04,
+ .data_offset = 0x05,
+ .data_segment = 0x07,
+ },
+
+ .commands = {
+ .get_brightness = 0x00,
+ .set_brightness = 0x01,
+
+ .get_wireless_button = 0x02,
+ .set_wireless_button = 0x03,
+
+ .get_backlight = 0x04,
+ .set_backlight = 0x05,
+
+ .get_recovery_mode = 0x06,
+ .set_recovery_mode = 0x07,
+
+ .get_performance_level = 0x08,
+ .set_performance_level = 0x09,
+
+ .set_linux = 0x0a,
+ },
+
+ .performance_levels = {
+ {
+ .name = "silent",
+ .value = 0,
+ },
+ {
+ .name = "normal",
+ .value = 1,
+ },
+ { },
+ },
+ },
+ {
+ .test_string = "SwSmi@",
+
+ .main_function = 0x5843,
+
+ .header_offsets = {
+ .port = 0x00,
+ .re_mem = 0x04,
+ .iface_func = 0x02,
+ .en_mem = 0x03,
+ .data_offset = 0x05,
+ .data_segment = 0x07,
+ },
+
+ .commands = {
+ .get_brightness = 0x10,
+ .set_brightness = 0x11,
+
+ .get_wireless_button = 0x12,
+ .set_wireless_button = 0x13,
+
+ .get_backlight = 0x2d,
+ .set_backlight = 0x2e,
+
+ .get_recovery_mode = 0xff,
+ .set_recovery_mode = 0xff,
+
+ .get_performance_level = 0x31,
+ .set_performance_level = 0x32,
+
+ .set_linux = 0xff,
+ },
+
+ .performance_levels = {
+ {
+ .name = "normal",
+ .value = 0,
+ },
+ {
+ .name = "silent",
+ .value = 1,
+ },
+ {
+ .name = "overclock",
+ .value = 2,
+ },
+ { },
+ },
+ },
+ { },
+};
+
+static struct sabi_config *sabi_config;
+
static void __iomem *sabi;
static void __iomem *sabi_iface;
static void __iomem *f0000_segment;
@@ -109,21 +231,21 @@ MODULE_PARM_DESC(debug, "Debug enabled or not");
static int sabi_get_command(u8 command, struct sabi_retval *sretval)
{
int retval = 0;
- u16 port = readw(sabi + SABI_HEADER_PORT);
+ u16 port = readw(sabi + sabi_config->header_offsets.port);
mutex_lock(&sabi_mutex);
/* enable memory to be able to write to it */
- outb(readb(sabi + SABI_HEADER_EN_MEM), port);
+ outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
/* write out the command */
- writew(MAIN_FUNCTION, sabi_iface + SABI_IFACE_MAIN);
+ writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
writew(command, sabi_iface + SABI_IFACE_SUB);
writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
- outb(readb(sabi + SABI_HEADER_IFACEFUNC), port);
+ outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
/* write protect memory to make it safe */
- outb(readb(sabi + SABI_HEADER_RE_MEM), port);
+ outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
/* see if the command actually succeeded */
if (readb(sabi_iface + SABI_IFACE_COMPLETE) == 0xaa &&
@@ -156,22 +278,22 @@ exit:
static int sabi_set_command(u8 command, u8 data)
{
int retval = 0;
- u16 port = readw(sabi + SABI_HEADER_PORT);
+ u16 port = readw(sabi + sabi_config->header_offsets.port);
mutex_lock(&sabi_mutex);
/* enable memory to be able to write to it */
- outb(readb(sabi + SABI_HEADER_EN_MEM), port);
+ outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
/* write out the command */
- writew(MAIN_FUNCTION, sabi_iface + SABI_IFACE_MAIN);
+ writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
writew(command, sabi_iface + SABI_IFACE_SUB);
writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
writeb(data, sabi_iface + SABI_IFACE_DATA);
- outb(readb(sabi + SABI_HEADER_IFACEFUNC), port);
+ outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
/* write protect memory to make it safe */
- outb(readb(sabi + SABI_HEADER_RE_MEM), port);
+ outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
/* see if the command actually succeeded */
if (readb(sabi_iface + SABI_IFACE_COMPLETE) == 0xaa &&
@@ -194,21 +316,21 @@ static void test_backlight(void)
{
struct sabi_retval sretval;
- sabi_get_command(GET_BACKLIGHT, &sretval);
+ sabi_get_command(sabi_config->commands.get_backlight, &sretval);
printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
- sabi_set_command(SET_BACKLIGHT, 0);
+ sabi_set_command(sabi_config->commands.set_backlight, 0);
printk(KERN_DEBUG "backlight should be off\n");
- sabi_get_command(GET_BACKLIGHT, &sretval);
+ sabi_get_command(sabi_config->commands.get_backlight, &sretval);
printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
msleep(1000);
- sabi_set_command(SET_BACKLIGHT, 1);
+ sabi_set_command(sabi_config->commands.set_backlight, 1);
printk(KERN_DEBUG "backlight should be on\n");
- sabi_get_command(GET_BACKLIGHT, &sretval);
+ sabi_get_command(sabi_config->commands.get_backlight, &sretval);
printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
}
@@ -216,21 +338,21 @@ static void test_wireless(void)
{
struct sabi_retval sretval;
- sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
+ sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
- sabi_set_command(SET_WIRELESS_BUTTON, 0);
+ sabi_set_command(sabi_config->commands.set_wireless_button, 0);
printk(KERN_DEBUG "wireless led should be off\n");
- sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
+ sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
msleep(1000);
- sabi_set_command(SET_WIRELESS_BUTTON, 1);
+ sabi_set_command(sabi_config->commands.set_wireless_button, 1);
printk(KERN_DEBUG "wireless led should be on\n");
- sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
+ sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
}
@@ -240,7 +362,8 @@ static u8 read_brightness(void)
int user_brightness = 0;
int retval;
- retval = sabi_get_command(GET_BRIGHTNESS, &sretval);
+ retval = sabi_get_command(sabi_config->commands.get_brightness,
+ &sretval);
if (!retval)
user_brightness = sretval.retval[0];
if (user_brightness != 0)
@@ -250,7 +373,8 @@ static u8 read_brightness(void)
static void set_brightness(u8 user_brightness)
{
- sabi_set_command(SET_BRIGHTNESS, user_brightness + 1);
+ sabi_set_command(sabi_config->commands.set_brightness,
+ user_brightness + 1);
}
static int get_brightness(struct backlight_device *bd)
@@ -263,9 +387,9 @@ static int update_status(struct backlight_device *bd)
set_brightness(bd->props.brightness);
if (bd->props.power == FB_BLANK_UNBLANK)
- sabi_set_command(SET_BACKLIGHT, 1);
+ sabi_set_command(sabi_config->commands.set_backlight, 1);
else
- sabi_set_command(SET_BACKLIGHT, 0);
+ sabi_set_command(sabi_config->commands.set_backlight, 0);
return 0;
}
@@ -282,9 +406,9 @@ static int rfkill_set(void *data, bool blocked)
* blocked == true is off
*/
if (blocked)
- sabi_set_command(SET_WIRELESS_BUTTON, 0);
+ sabi_set_command(sabi_config->commands.set_wireless_button, 0);
else
- sabi_set_command(SET_WIRELESS_BUTTON, 1);
+ sabi_set_command(sabi_config->commands.set_wireless_button, 1);
return 0;
}
@@ -317,47 +441,49 @@ static void destroy_wireless(void)
rfkill_destroy(rfk);
}
-static ssize_t get_silent_state(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t get_performance_level(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct sabi_retval sretval;
int retval;
+ int i;
/* Read the state */
- retval = sabi_get_command(GET_PERFORMANCE_LEVEL, &sretval);
+ retval = sabi_get_command(sabi_config->commands.get_performance_level,
+ &sretval);
if (retval)
return retval;
/* The logic is backwards, yeah, lots of fun... */
- if (sretval.retval[0] == 0)
- retval = 1;
- else
- retval = 0;
- return sprintf(buf, "%d\n", retval);
+ for (i = 0; sabi_config->performance_levels[i].name; ++i) {
+ if (sretval.retval[0] == sabi_config->performance_levels[i].value)
+ return sprintf(buf, "%s\n", sabi_config->performance_levels[i].name);
+ }
+ return sprintf(buf, "%s\n", "unknown");
}
-static ssize_t set_silent_state(struct device *dev,
+static ssize_t set_performance_level(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
- char value;
-
if (count >= 1) {
- value = buf[0];
- if ((value == '0') || (value == 'n') || (value == 'N')) {
- /* Turn speed up */
- sabi_set_command(SET_PERFORMANCE_LEVEL, 0x01);
- } else if ((value == '1') || (value == 'y') || (value == 'Y')) {
- /* Turn speed down */
- sabi_set_command(SET_PERFORMANCE_LEVEL, 0x00);
- } else {
- return -EINVAL;
+ int i;
+ for (i = 0; sabi_config->performance_levels[i].name; ++i) {
+ struct sabi_performance_level *level =
+ &sabi_config->performance_levels[i];
+ if (!strncasecmp(level->name, buf, strlen(level->name))) {
+ sabi_set_command(sabi_config->commands.set_performance_level,
+ level->value);
+ break;
+ }
}
+ if (!sabi_config->performance_levels[i].name)
+ return -EINVAL;
}
return count;
}
-static DEVICE_ATTR(silent, S_IWUSR | S_IRUGO,
- get_silent_state, set_silent_state);
+static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
+ get_performance_level, set_performance_level);
static int __init dmi_check_cb(const struct dmi_system_id *id)
@@ -388,18 +514,113 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
},
.callback = dmi_check_cb,
},
+ {
+ .ident = "X125",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X125"),
+ DMI_MATCH(DMI_BOARD_NAME, "X125"),
+ },
+ .callback = dmi_check_cb,
+ },
+ {
+ .ident = "NC10",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
+ DMI_MATCH(DMI_BOARD_NAME, "NC10"),
+ },
+ .callback = dmi_check_cb,
+ },
+ {
+ .ident = "NP-Q45",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
+ DMI_MATCH(DMI_BOARD_NAME, "SQ45S70S"),
+ },
+ .callback = dmi_check_cb,
+ },
+ {
+ .ident = "X360",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
+ DMI_MATCH(DMI_BOARD_NAME, "X360"),
+ },
+ .callback = dmi_check_cb,
+ },
+ {
+ .ident = "R518",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "R518"),
+ DMI_MATCH(DMI_BOARD_NAME, "R518"),
+ },
+ .callback = dmi_check_cb,
+ },
+ {
+ .ident = "N150/N210/N220",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
+ DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
+ },
+ .callback = dmi_check_cb,
+ },
+ {
+ .ident = "R530/R730",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "R530/R730"),
+ DMI_MATCH(DMI_BOARD_NAME, "R530/R730"),
+ },
+ .callback = dmi_check_cb,
+ },
+ {
+ .ident = "NF110/NF210/NF310",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
+ DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
+ },
+ .callback = dmi_check_cb,
+ },
{ },
};
MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
+static int find_signature(void __iomem *memcheck, const char *testStr)
+{
+ int i = 0;
+ int loca;
+
+ for (loca = 0; loca < 0xffff; loca++) {
+ char temp = readb(memcheck + loca);
+
+ if (temp == testStr[i]) {
+ if (i == strlen(testStr)-1)
+ break;
+ ++i;
+ } else {
+ i = 0;
+ }
+ }
+ return loca;
+}
+
static int __init samsung_init(void)
{
struct backlight_properties props;
struct sabi_retval sretval;
- const char *testStr = "SECLINUX";
- void __iomem *memcheck;
unsigned int ifaceP;
- int pStr;
+ int i;
int loca;
int retval;
@@ -414,50 +635,44 @@ static int __init samsung_init(void)
return -EINVAL;
}
- /* Try to find the signature "SECLINUX" in memory to find the header */
- pStr = 0;
- memcheck = f0000_segment;
- for (loca = 0; loca < 0xffff; loca++) {
- char temp = readb(memcheck + loca);
-
- if (temp == testStr[pStr]) {
- if (pStr == strlen(testStr)-1)
- break;
- ++pStr;
- } else {
- pStr = 0;
- }
+ /* Try to find one of the signatures in memory to find the header */
+ for (i = 0; sabi_configs[i].test_string != 0; ++i) {
+ sabi_config = &sabi_configs[i];
+ loca = find_signature(f0000_segment, sabi_config->test_string);
+ if (loca != 0xffff)
+ break;
}
+
if (loca == 0xffff) {
printk(KERN_ERR "This computer does not support SABI\n");
goto error_no_signature;
- }
+ }
/* point to the SMI port Number */
loca += 1;
- sabi = (memcheck + loca);
+ sabi = (f0000_segment + loca);
if (debug) {
printk(KERN_DEBUG "This computer supports SABI==%x\n",
loca + 0xf0000 - 6);
printk(KERN_DEBUG "SABI header:\n");
printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
- readw(sabi + SABI_HEADER_PORT));
+ readw(sabi + sabi_config->header_offsets.port));
printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
- readb(sabi + SABI_HEADER_IFACEFUNC));
+ readb(sabi + sabi_config->header_offsets.iface_func));
printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
- readb(sabi + SABI_HEADER_EN_MEM));
+ readb(sabi + sabi_config->header_offsets.en_mem));
printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
- readb(sabi + SABI_HEADER_RE_MEM));
+ readb(sabi + sabi_config->header_offsets.re_mem));
printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
- readw(sabi + SABI_HEADER_DATA_OFFSET));
+ readw(sabi + sabi_config->header_offsets.data_offset));
printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
- readw(sabi + SABI_HEADER_DATA_SEGMENT));
+ readw(sabi + sabi_config->header_offsets.data_segment));
}
/* Get a pointer to the SABI Interface */
- ifaceP = (readw(sabi + SABI_HEADER_DATA_SEGMENT) & 0x0ffff) << 4;
- ifaceP += readw(sabi + SABI_HEADER_DATA_OFFSET) & 0x0ffff;
+ ifaceP = (readw(sabi + sabi_config->header_offsets.data_segment) & 0x0ffff) << 4;
+ ifaceP += readw(sabi + sabi_config->header_offsets.data_offset) & 0x0ffff;
sabi_iface = ioremap(ifaceP, 16);
if (!sabi_iface) {
printk(KERN_ERR "Can't remap %x\n", ifaceP);
@@ -470,15 +685,19 @@ static int __init samsung_init(void)
test_backlight();
test_wireless();
- retval = sabi_get_command(GET_BRIGHTNESS, &sretval);
+ retval = sabi_get_command(sabi_config->commands.get_brightness,
+ &sretval);
printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
}
/* Turn on "Linux" mode in the BIOS */
- retval = sabi_set_command(SET_LINUX, 0x81);
- if (retval) {
- printk(KERN_ERR KBUILD_MODNAME ": Linux mode was not set!\n");
- goto error_no_platform;
+ if (sabi_config->commands.set_linux != 0xff) {
+ retval = sabi_set_command(sabi_config->commands.set_linux,
+ 0x81);
+ if (retval) {
+ printk(KERN_ERR KBUILD_MODNAME ": Linux mode was not set!\n");
+ goto error_no_platform;
+ }
}
/* knock up a platform device to hang stuff off of */
@@ -503,7 +722,7 @@ static int __init samsung_init(void)
if (retval)
goto error_no_rfk;
- retval = device_create_file(&sdev->dev, &dev_attr_silent);
+ retval = device_create_file(&sdev->dev, &dev_attr_performance_level);
if (retval)
goto error_file_create;
@@ -530,9 +749,10 @@ error_no_signature:
static void __exit samsung_exit(void)
{
/* Turn off "Linux" mode in the BIOS */
- sabi_set_command(SET_LINUX, 0x80);
+ if (sabi_config->commands.set_linux != 0xff)
+ sabi_set_command(sabi_config->commands.set_linux, 0x80);
- device_remove_file(&sdev->dev, &dev_attr_silent);
+ device_remove_file(&sdev->dev, &dev_attr_performance_level);
backlight_device_unregister(backlight_device);
destroy_wireless();
iounmap(sabi_iface);

View File

@ -0,0 +1,193 @@
From: Matt Carlson <mcarlson@broadcom.com>
Subject: tg3: 5785 and 57780 asic revs not working
References: bnc#580780
Patch-mainline: Never
There is a known problem with phylib that causes a lot of problems.
Phylib does not load phy modules as it detects devices on the MDIO bus.
If the phylib module gets loaded as a dependancy of tg3, there will be
no opportunity to load the needed broadcom.ko module before tg3 requests
phylib to probe the MDIO bus. The result will be that tg3 will fail to
attach to 5785 and 57780 devices.
There are several known solutions to this problem. (None of these
should go upstream. The upstream fix should be to get phylib to load
modules for devices it encounters.) Only one of them need be applied.
1) Statically link in the broadcom.ko module into the kernel.
2) Add the following to /etc/modprobe.d/local.conf or its equivalent:
install tg3 /sbin/modprobe broadcom; /sbin/modprobe --ignore-install tg3
3) Apply the following patch:
Signed-off-by: Brandon Philips <bphilips@suse.de>
---
drivers/net/tg3.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/net/tg3.h | 9 +++++
2 files changed, 92 insertions(+)
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1998,6 +1998,58 @@ static int tg3_phy_reset(struct tg3 *tp)
tg3_phy_toggle_apd(tp, false);
out:
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM50610 ||
+ (tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM50610M) {
+ u32 reg;
+
+ /* Enable SM_DSP clock and tx 6dB coding. */
+ reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+ MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
+ MII_TG3_AUXCTL_ACTL_TX_6DB;
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
+
+ reg = MII_TG3_DSP_EXP8_REJ2MHz;
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, reg);
+
+ /* Apply workaround to A0 revision parts only. */
+ if (tp->phy_id == TG3_PHY_ID_BCM50610 ||
+ tp->phy_id == TG3_PHY_ID_BCM50610M) {
+ tg3_phydsp_write(tp, 0x001F, 0x0300);
+ tg3_phydsp_write(tp, 0x601F, 0x0002);
+ tg3_phydsp_write(tp, 0x0F75, 0x003C);
+ tg3_phydsp_write(tp, 0x0F96, 0x0010);
+ tg3_phydsp_write(tp, 0x0F97, 0x0C0C);
+ }
+
+ /* Turn off SM_DSP clock. */
+ reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+ MII_TG3_AUXCTL_ACTL_TX_6DB;
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
+
+ /* Clear all mode configuration bits. */
+ reg = MII_TG3_MISC_SHDW_WREN |
+ MII_TG3_MISC_SHDW_RGMII_SEL;
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
+ }
+ if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM57780) {
+ u32 reg;
+
+ /* Enable SM_DSP clock and tx 6dB coding. */
+ reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+ MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
+ MII_TG3_AUXCTL_ACTL_TX_6DB;
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
+
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, MII_TG3_DSP_EXP75);
+ tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &reg);
+ reg |= MII_TG3_DSP_EXP75_SUP_CM_OSC;
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, reg);
+
+ /* Turn off SM_DSP clock. */
+ reg = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+ MII_TG3_AUXCTL_ACTL_TX_6DB;
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, reg);
+ }
if (tp->phy_flags & TG3_PHYFLG_ADC_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
tg3_phydsp_write(tp, 0x201f, 0x2aaa);
@@ -2054,6 +2106,22 @@ out:
/* adjust output voltage */
tg3_writephy(tp, MII_TG3_FET_PTEST, 0x12);
}
+ else if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
+ u32 brcmtest;
+ if (!tg3_readphy(tp, MII_TG3_FET_TEST, &brcmtest) &&
+ !tg3_writephy(tp, MII_TG3_FET_TEST,
+ brcmtest | MII_TG3_FET_SHADOW_EN)) {
+ u32 val, reg = MII_TG3_FET_SHDW_AUXMODE4;
+
+ if (!tg3_readphy(tp, reg, &val)) {
+ val &= ~MII_TG3_FET_SHDW_AM4_LED_MASK;
+ val |= MII_TG3_FET_SHDW_AM4_LED_MODE1;
+ tg3_writephy(tp, reg, val);
+ }
+
+ tg3_writephy(tp, MII_TG3_FET_TEST, brcmtest);
+ }
+ }
tg3_phy_toggle_automdix(tp, 1);
tg3_phy_set_wirespeed(tp);
@@ -3288,6 +3356,15 @@ relink:
tg3_phy_eee_adjust(tp, current_link_up);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ if (tp->link_config.active_speed == SPEED_10)
+ tw32(MAC_MI_STAT,
+ MAC_MI_STAT_10MBPS_MODE |
+ MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+ else
+ tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+ }
+
if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
/* Polled via timer. */
tw32_f(MAC_EVENT, 0);
@@ -13411,9 +13488,11 @@ static int __devinit tg3_get_invariants(
GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
+#if 0
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB;
+#endif
err = tg3_mdio_init(tp);
if (err)
@@ -14203,6 +14282,10 @@ static char * __devinit tg3_phy_string(s
case TG3_PHY_ID_BCM5718S: return "5718S";
case TG3_PHY_ID_BCM57765: return "57765";
case TG3_PHY_ID_BCM5719C: return "5719C";
+ case TG3_PHY_ID_BCM50610: return "50610";
+ case TG3_PHY_ID_BCM50610M: return "50610M";
+ case TG3_PHY_ID_BCMAC131: return "AC131";
+ case TG3_PHY_ID_BCM57780: return "57780";
case TG3_PHY_ID_BCM8002: return "8002/serdes";
case 0: return "serdes";
default: return "unknown";
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2072,6 +2072,7 @@
#define MII_TG3_DSP_EXP8_REJ2MHz 0x0001
#define MII_TG3_DSP_EXP8_AEDW 0x0200
#define MII_TG3_DSP_EXP75 0x0f75
+#define MII_TG3_DSP_EXP75_SUP_CM_OSC 0x0001
#define MII_TG3_DSP_EXP96 0x0f96
#define MII_TG3_DSP_EXP97 0x0f97
@@ -2127,6 +2128,8 @@
#define MII_TG3_MISC_SHDW_SCR5_LPED 0x0010
#define MII_TG3_MISC_SHDW_SCR5_SEL 0x1400
+#define MII_TG3_MISC_SHDW_RGMII_SEL 0x2c00
+
#define MII_TG3_TEST1 0x1e
#define MII_TG3_TEST1_TRIM_EN 0x0010
#define MII_TG3_TEST1_CRC_EN 0x8000
@@ -2144,6 +2147,8 @@
#define MII_TG3_FET_SHDW_MISCCTRL_MDIX 0x4000
#define MII_TG3_FET_SHDW_AUXMODE4 0x1a
+#define MII_TG3_FET_SHDW_AM4_LED_MODE1 0x0001
+#define MII_TG3_FET_SHDW_AM4_LED_MASK 0x0003
#define MII_TG3_FET_SHDW_AUXMODE4_SBPD 0x0008
#define MII_TG3_FET_SHDW_AUXSTAT2 0x1b
@@ -2922,6 +2927,10 @@ struct tg3 {
#define TG3_PHY_ID_BCM5719C 0x5c0d8a20
#define TG3_PHY_ID_BCM5906 0xdc00ac40
#define TG3_PHY_ID_BCM8002 0x60010140
+#define TG3_PHY_ID_BCM50610 0xbc050d60
+#define TG3_PHY_ID_BCM50610M 0xbc050d70
+#define TG3_PHY_ID_BCMAC131 0xbc050c70
+#define TG3_PHY_ID_BCM57780 0x5c0d8990
#define TG3_PHY_ID_INVALID 0xffffffff
#define PHY_ID_RTL8211C 0x001cc910

View File

@ -0,0 +1,61 @@
From: Brandon Philips <bphilips@suse.de>
Subject: [PATCH] tg3: entropy source
Patch-mainline: never
References: FATE#307517
Signed-off-by: Brandon Philips <bphilips@suse.de>
---
drivers/net/tg3.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -15,7 +15,6 @@
* notice is accompanying it.
*/
-
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/stringify.h>
@@ -67,6 +66,10 @@
#include "tg3.h"
+static int entropy = 0;
+module_param(entropy, int, 0);
+MODULE_PARM_DESC(entropy, "Allow tg3 to populate the /dev/random entropy pool");
+
#define DRV_MODULE_NAME "tg3"
#define TG3_MAJ_NUM 3
#define TG3_MIN_NUM 116
@@ -8590,10 +8593,13 @@ restart_timer:
static int tg3_request_irq(struct tg3 *tp, int irq_num)
{
irq_handler_t fn;
- unsigned long flags;
+ unsigned long flags = 0;
char *name;
struct tg3_napi *tnapi = &tp->napi[irq_num];
+ if (entropy)
+ flags = IRQF_SAMPLE_RANDOM;
+
if (tp->irq_cnt == 1)
name = tp->dev->name;
else {
@@ -8606,12 +8612,11 @@ static int tg3_request_irq(struct tg3 *t
fn = tg3_msi;
if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
fn = tg3_msi_1shot;
- flags = IRQF_SAMPLE_RANDOM;
} else {
fn = tg3_interrupt;
if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
fn = tg3_interrupt_tagged;
- flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM;
+ flags |= IRQF_SHARED;
}
return request_irq(tnapi->irq_vec, fn, flags, name, tnapi);

View File

@ -0,0 +1,78 @@
From: Vasiliy Kulikov <segooon@gmail.com>
Subject: acpi: ec_sys: access user space with get_user()/put_user()
Patch-Mainline: hopefully still 2.6.36
References: none
User space pointer may not be dereferenced. Use get_user()/put_user()
instead and check their return codes.
Signed-off-by: Vasiliy Kulikov <segooon@gmail.com>
Signed-off-by: Thomas Renninger <trenn@suse.de>
---
Compile tested.
drivers/acpi/ec_sys.c | 18 ++++++++++++++----
1 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
index 0e869b3..cc007d8 100644
--- a/drivers/acpi/ec_sys.c
+++ b/drivers/acpi/ec_sys.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/acpi.h>
#include <linux/debugfs.h>
+#include <linux/uaccess.h>
#include "internal.h"
MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>");
@@ -43,7 +44,6 @@ static ssize_t acpi_ec_read_io(struct file *f, char __user *buf,
* struct acpi_ec *ec = ((struct seq_file *)f->private_data)->private;
*/
unsigned int size = EC_SPACE_SIZE;
- u8 *data = (u8 *) buf;
loff_t init_off = *off;
int err = 0;
@@ -56,9 +56,15 @@ static ssize_t acpi_ec_read_io(struct file *f, char __user *buf,
size = count;
while (size) {
- err = ec_read(*off, &data[*off - init_off]);
+ u8 byte_read;
+ err = ec_read(*off, &byte_read);
if (err)
return err;
+ if (put_user(byte_read, buf + *off - init_off)) {
+ if (*off - init_off)
+ return *off - init_off; /* partial read */
+ return -EFAULT;
+ }
*off += 1;
size--;
}
@@ -74,7 +80,6 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf,
unsigned int size = count;
loff_t init_off = *off;
- u8 *data = (u8 *) buf;
int err = 0;
if (*off >= EC_SPACE_SIZE)
@@ -85,7 +90,12 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf,
}
while (size) {
- u8 byte_write = data[*off - init_off];
+ u8 byte_write;
+ if (get_user(byte_write, buf + *off - init_off)) {
+ if (*off - init_off)
+ return *off - init_off; /* partial write */
+ return -EFAULT;
+ }
err = ec_write(*off, byte_write);
if (err)
return err;
--
1.7.0.4

View File

@ -0,0 +1,67 @@
From: Nick Piggin <npiggin@suse.de>
Subject: be more aggressive with zone reclaims
References: bnc#476525
Patch-mainline: no
The zone reclaim design is not very good for parallel allocations.
The primary problem is that only one thread is allowed to perform
zone-reclaim at a time. If another thread needs memory from that
zone/node, then its zone-reclaim will fail and it will be forced
to fall back to allocating from another zone.
Additionally, the default zone reclaim priority is insufficient
for massively parallel allocations. Lower ZONE_RECLAIM_PRIORITY
to fix it. This can result in higher latency spikes, but similar
kind of page allocation latency can often be encountered as
normal part of page reclaim when pagecache fills memory.
Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
---
mm/vmscan.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2515,7 +2515,7 @@ int zone_reclaim_mode __read_mostly;
* of a node considered for each zone_reclaim. 4 scans 1/16th of
* a zone.
*/
-#define ZONE_RECLAIM_PRIORITY 4
+#define ZONE_RECLAIM_PRIORITY 0
/*
* Percentage of pages in a zone that must be unmapped for zone_reclaim to
@@ -2620,6 +2620,8 @@ static int __zone_reclaim(struct zone *z
slab_reclaimable = zone_page_state(zone, NR_SLAB_RECLAIMABLE);
if (slab_reclaimable > zone->min_slab_pages) {
+ unsigned long lru_pages = zone_reclaimable_pages(zone);
+
/*
* shrink_slab() does not currently allow us to determine how
* many pages were freed in this zone. So we take the current
@@ -2630,10 +2632,7 @@ static int __zone_reclaim(struct zone *z
* Note that shrink_slab will free memory on all zones and may
* take a long time.
*/
- while (shrink_slab(sc.nr_scanned, gfp_mask, order) &&
- zone_page_state(zone, NR_SLAB_RECLAIMABLE) >
- slab_reclaimable - nr_pages)
- ;
+ shrink_slab(sc.nr_scanned, gfp_mask, lru_pages);
/*
* Update nr_reclaimed by the number of slab pages we
@@ -2687,11 +2686,7 @@ int zone_reclaim(struct zone *zone, gfp_
if (node_state(node_id, N_CPU) && node_id != numa_node_id())
return ZONE_RECLAIM_NOSCAN;
- if (zone_test_and_set_flag(zone, ZONE_RECLAIM_LOCKED))
- return ZONE_RECLAIM_NOSCAN;
-
ret = __zone_reclaim(zone, gfp_mask, order);
- zone_clear_flag(zone, ZONE_RECLAIM_LOCKED);
if (!ret)
count_vm_event(PGSCAN_ZONE_RECLAIM_FAILED);

View File

@ -0,0 +1,61 @@
From fd0e435b0fe85622f167b84432552885a4856ac8 Mon Sep 17 00:00:00 2001
From: Phil Oester <kernel@linuxace.com>
Date: Mon, 14 Mar 2011 06:22:04 +0000
Subject: [PATCH] bonding: Incorrect TX queue offset
Git-commit: fd0e435b0fe85622f167b84432552885a4856ac8
Patch-mainline: v2.6.39-rc1~468^2~15
Reference: bnc#687116, CVE-2011-1581
When packets come in from a device with >= 16 receive queues
headed out a bonding interface, syslog gets filled with this:
kernel: bond0 selects TX queue 16, but real number of TX queues is 16
because queue_mapping is offset by 1. Adjust return value
to account for the offset.
This is a revision of my earlier patch (which did not use the
skb_rx_queue_* helpers - thanks to Ben for the suggestion).
Andy submitted a similar patch which emits a pr_warning on
invalid queue selection, but I believe the log spew is
not useful. We can revisit that question in the future,
but in the interim I believe fixing the core problem is
worthwhile.
Signed-off-by: Phil Oester <kernel@linuxace.com>
Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Brandon Philips <bphilips@suse.de>
---
drivers/net/bonding/bond_main.c | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 3ad4f50..a93d941 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4341,11 +4341,18 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)
{
/*
* This helper function exists to help dev_pick_tx get the correct
- * destination queue. Using a helper function skips the a call to
+ * destination queue. Using a helper function skips a call to
* skb_tx_hash and will put the skbs in the queue we expect on their
* way down to the bonding driver.
*/
- return skb->queue_mapping;
+ u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
+
+ if (unlikely(txq >= dev->real_num_tx_queues)) {
+ do
+ txq -= dev->real_num_tx_queues;
+ while (txq >= dev->real_num_tx_queues);
+ }
+ return txq;
}
static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
--
1.7.3.4

View File

@ -0,0 +1,45 @@
From: jbeulich@novell.com
Subject: Module use count must be updated as bridges are created/destroyed
Patch-mainline: unknown
References: 267651
Otherwise 'modprobe -r' on a module having a dependency on bridge will
implicitly unload bridge, bringing down all connectivity that was using
bridges.
---
net/bridge/br_if.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -291,6 +291,11 @@ int br_add_bridge(struct net *net, const
if (!dev)
return -ENOMEM;
+ if (!try_module_get(THIS_MODULE)) {
+ free_netdev(dev);
+ return -ENOENT;
+ }
+
rtnl_lock();
if (strchr(dev->name, '%')) {
ret = dev_alloc_name(dev, dev->name);
@@ -309,6 +314,8 @@ int br_add_bridge(struct net *net, const
unregister_netdevice(dev);
out:
rtnl_unlock();
+ if (ret)
+ module_put(THIS_MODULE);
return ret;
out_free:
@@ -340,6 +347,8 @@ int br_del_bridge(struct net *net, const
del_br(netdev_priv(dev), NULL);
rtnl_unlock();
+ if (ret == 0)
+ module_put(THIS_MODULE);
return ret;
}

View File

@ -0,0 +1,74 @@
From 468c3f924f043cad7a04f4f4d5224a2c9bc886c1 Mon Sep 17 00:00:00 2001
From: Jiri Slaby <jslaby@suse.cz>
Date: Sun, 13 Mar 2011 06:54:31 +0000
Subject: NET: cdc-phonet, handle empty phonet header
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Git-commit: 468c3f924f043cad7a04f4f4d5224a2c9bc886c1
Patch-mainline: yes
References: bnc#673992
Currently, for N 5800 XM I get:
cdc_phonet: probe of 1-6:1.10 failed with error -22
It's because phonet_header is empty. Extra altsetting looks like
there:
E 05 24 00 01 10 03 24 ab 05 24 06 0a 0b 04 24 fd .$....$..$....$.
E 00 .
I don't see the header used anywhere so just check if the phonet
descriptor is there, not the structure itself.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Cc: David S. Miller <davem@davemloft.net>
Acked-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/usb/cdc-phonet.c | 9 +++------
1 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index 4cf4e36..f967913 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -328,13 +328,13 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
static const char ifname[] = "usbpn%d";
const struct usb_cdc_union_desc *union_header = NULL;
- const struct usb_cdc_header_desc *phonet_header = NULL;
const struct usb_host_interface *data_desc;
struct usb_interface *data_intf;
struct usb_device *usbdev = interface_to_usbdev(intf);
struct net_device *dev;
struct usbpn_dev *pnd;
u8 *data;
+ int phonet = 0;
int len, err;
data = intf->altsetting->extra;
@@ -355,10 +355,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
(struct usb_cdc_union_desc *)data;
break;
case 0xAB:
- if (phonet_header || dlen < 5)
- break;
- phonet_header =
- (struct usb_cdc_header_desc *)data;
+ phonet = 1;
break;
}
}
@@ -366,7 +363,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
len -= dlen;
}
- if (!union_header || !phonet_header)
+ if (!union_header || !phonet)
return -EINVAL;
data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
--
1.7.4.1

View File

@ -0,0 +1,65 @@
From: Thomas Renninger <trenn@suse.de>
Subject: CPUFREQ: ondemand: Limit default sampling rate to 300ms max.
References: bnc#464461
Patch-Mainline: never, SLE11 only
Modified for SP1 by Jiri Bohac <jbohac@suse.cz>
HW cpufreq drivers (e.g. all non-acpi AMD) may report too high latency values.
The default sampling rate (how often the ondemand/conservative governor
checks for frequency adjustments) may therefore be much too high,
resulting in performance loss.
Restrict default sampling rate to 300ms. 333ms sampling rate is field
tested with userspace governors, 300ms should be a fine maximum default
value for the ondemand kernel governor for all HW out there.
Set default up_threshold to 40 on multi core systems.
This should avoid effects where two CPU intensive threads are waiting on
each other on separate cores. On a single core machine these would all be
processed on one core resulting in higher utilization of the one core.
---
drivers/cpufreq/cpufreq_ondemand.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -35,6 +35,7 @@
#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000)
#define MIN_FREQUENCY_UP_THRESHOLD (11)
#define MAX_FREQUENCY_UP_THRESHOLD (100)
+#define MAX_DEFAULT_SAMPLING_RATE (300 * 1000U)
/*
* The polling frequency of this governor depends on the capability of
@@ -736,6 +737,29 @@ static int cpufreq_governor_dbs(struct c
dbs_tuners_ins.sampling_rate =
max(min_sampling_rate,
latency * LATENCY_MULTIPLIER);
+ /*
+ * Cut def_sampling rate to 300ms if it was above,
+ * still consider to not set it above latency
+ * transition * 100
+ */
+ if (dbs_tuners_ins.sampling_rate > MAX_DEFAULT_SAMPLING_RATE) {
+ dbs_tuners_ins.sampling_rate =
+ max(min_sampling_rate, MAX_DEFAULT_SAMPLING_RATE);
+ printk(KERN_INFO "CPUFREQ: ondemand sampling "
+ "rate set to %d ms\n",
+ dbs_tuners_ins.sampling_rate / 1000);
+ }
+ /*
+ * Be conservative in respect to performance.
+ * If an application calculates using two threads
+ * depending on each other, they will be run on several
+ * CPU cores resulting on 50% load on both.
+ * SLED might still want to prefer 80% up_threshold
+ * by default, but we cannot differ that here.
+ */
+ if (num_online_cpus() > 1)
+ dbs_tuners_ins.up_threshold =
+ DEF_FREQUENCY_UP_THRESHOLD / 2;
dbs_tuners_ins.io_is_busy = should_io_be_busy();
}
mutex_unlock(&dbs_mutex);

View File

@ -0,0 +1,29 @@
From: Hannes Reinecke <hare@suse.de>
Subject: Reattach device handler for multipath devices
References: bnc#435688
Patch-mainline: not yet
The multipath daemon might have specified a different device_handler
than the one a device is attached to by default.
So we should try to re-attach with the user-specified device_handler
and only return an error if that fails.
And we should _not_ detach existing hardware handlers. This will
set the path to failed during failover.
Signed-off-by: Hannes Reinecke <hare@suse.de
---
drivers/md/dm-mpath.c | 2 --
1 file changed, 2 deletions(-)
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -168,8 +168,6 @@ static void free_pgpaths(struct list_hea
list_for_each_entry_safe(pgpath, tmp, pgpaths, list) {
list_del(&pgpath->list);
- if (m->hw_handler_name)
- scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
dm_put_device(ti, pgpath->path.dev);
free_pgpath(pgpath);
}

View File

@ -0,0 +1,37 @@
From: Nikanth Karthikesan <knikanth@suse.de>
Subject: Release md->map_lock before set_disk_ro
Patch-mainline: No
References: bnc#556899 bnc#479784
Signed-off-by: Nikanth Karthikesan <knikanth@suse.de>
Calling set_disk_ro() with irqs disabled triggers a warning.
set_disk_ro() can be called outside the
write_lock_irqsave(&md->map_lock)? And to get the
dm_table_get_mode(md->map), we just need to hold a reference
with dm_get_table() and dm_table_put()
---
drivers/md/dm.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -2174,12 +2174,15 @@ static struct dm_table *__bind(struct ma
old_map = md->map;
md->map = t;
dm_table_set_restrictions(t, q, limits);
+ write_unlock_irqrestore(&md->map_lock, flags);
+
+ dm_table_get(md->map);
if (!(dm_table_get_mode(t) & FMODE_WRITE)) {
set_disk_ro(md->disk, 1);
} else {
set_disk_ro(md->disk, 0);
}
- write_unlock_irqrestore(&md->map_lock, flags);
+ dm_table_put(md->map);
return old_map;
}

View File

@ -0,0 +1,90 @@
From: Hannes Reinecke <hare@suse.de>
Subject: dm multipath devices are not getting created for readonly devices
References: bnc#382705
Patch-mainline: not yet
Currently we cannot create device-mapper tables for multipath devices
whenever they are read-only.
This patch modifies the device-mapper to set the 'READ-ONLY' flag
automatically whenever a read-only is added to the table.
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/md/dm-table.c | 10 +++++++++-
drivers/md/dm.c | 18 ++++++++++++++++--
2 files changed, 25 insertions(+), 3 deletions(-)
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -465,11 +465,19 @@ static int __table_get_device(struct dm_
dd->dm_dev.mode = mode;
dd->dm_dev.bdev = NULL;
- if ((r = open_dev(dd, dev, t->md))) {
+ r = open_dev(dd, dev, t->md);
+ if (r == -EROFS) {
+ dd->dm_dev.mode &= ~FMODE_WRITE;
+ r = open_dev(dd, dev, t->md);
+ }
+ if (r) {
kfree(dd);
return r;
}
+ if (dd->dm_dev.mode != mode)
+ t->mode = dd->dm_dev.mode;
+
format_dev_t(dd->dm_dev.name, dev);
atomic_set(&dd->count, 0);
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -343,16 +343,25 @@ int dm_deleting_md(struct mapped_device
static int dm_blk_open(struct block_device *bdev, fmode_t mode)
{
struct mapped_device *md;
+ int retval = 0;
spin_lock(&_minor_lock);
md = bdev->bd_disk->private_data;
- if (!md)
+ if (!md) {
+ retval = -ENXIO;
goto out;
+ }
if (test_bit(DMF_FREEING, &md->flags) ||
dm_deleting_md(md)) {
md = NULL;
+ retval = -ENXIO;
+ goto out;
+ }
+ if (get_disk_ro(md->disk) && (mode & FMODE_WRITE)) {
+ md = NULL;
+ retval = -EROFS;
goto out;
}
@@ -364,7 +373,7 @@ out:
out:
spin_unlock(&_minor_lock);
- return md ? 0 : -ENXIO;
+ return retval;
}
static int dm_blk_close(struct gendisk *disk, fmode_t mode)
@@ -2165,6 +2174,11 @@ static struct dm_table *__bind(struct ma
old_map = md->map;
md->map = t;
dm_table_set_restrictions(t, q, limits);
+ if (!(dm_table_get_mode(t) & FMODE_WRITE)) {
+ set_disk_ro(md->disk, 1);
+ } else {
+ set_disk_ro(md->disk, 0);
+ }
write_unlock_irqrestore(&md->map_lock, flags);
return old_map;

View File

@ -0,0 +1,63 @@
From: Ludwig Nussel <lnussel@novell.com>
Subject: make nf_conntrack_slp actually work
References: bnc#470963
Patch-mainline: not yet, depends on patches.suse/netfilter-ip_conntrack_slp.patch
Acked-by: Jeff Mahoney <jeffm@suse.com>
---
net/netfilter/nf_conntrack_slp.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
--- a/net/netfilter/nf_conntrack_slp.c
+++ b/net/netfilter/nf_conntrack_slp.c
@@ -47,15 +47,15 @@ static int help(struct sk_buff *skb, uns
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
struct nf_conntrack_expect *exp;
- struct iphdr *iph = ip_hdr(skb);
struct rtable *rt = skb_rtable(skb);
struct in_device *in_dev;
__be32 mask = 0;
+ __be32 src = 0;
/* we're only interested in locally generated packets */
if (skb->sk == NULL)
goto out;
- if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
+ if (rt == NULL || !(rt->rt_flags & (RTCF_MULTICAST|RTCF_BROADCAST)))
goto out;
if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
goto out;
@@ -64,15 +64,18 @@ static int help(struct sk_buff *skb, uns
in_dev = __in_dev_get_rcu(rt->dst.dev);
if (in_dev != NULL) {
for_primary_ifa(in_dev) {
- if (ifa->ifa_broadcast == iph->daddr) {
- mask = ifa->ifa_mask;
- break;
- }
+ /* this is a hack as slp uses multicast we can't match
+ * the destination address to some broadcast address. So
+ * just take the first one. Better would be to install
+ * expectations for all addresses */
+ mask = ifa->ifa_mask;
+ src = ifa->ifa_broadcast;
+ break;
} endfor_ifa(in_dev);
}
rcu_read_unlock();
- if (mask == 0)
+ if (mask == 0 || src == 0)
goto out;
exp = nf_ct_expect_alloc(ct);
@@ -80,6 +83,7 @@ static int help(struct sk_buff *skb, uns
goto out;
exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+ exp->tuple.src.u3.ip = src;
exp->tuple.src.u.udp.port = htons(SLP_PORT);
exp->mask.src.u3.ip = mask;

View File

@ -0,0 +1,43 @@
From: Kyle McMartin <kyle@dreadnought.i.jkkm.org>
Subject: flexcop: fix registering braindead stupid names
References: brc#575873 bnc#661429
Patch-mainline: Unsubmitted by author
This patch fixes an issue where the flexcop driver passes DRIVER_NAME to
request_irq, which ultimately sets up proc files. The invalid name
contains slashes so the proc file creation fails and we get a WARN_ON.
Acked-by: Jeff Mahoney <jeffm@suse.com>
---
drivers/media/dvb/b2c2/flexcop-pci.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/media/dvb/b2c2/flexcop-pci.c
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -39,6 +39,7 @@ MODULE_PARM_DESC(debug,
#define DRIVER_VERSION "0.1"
#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
+#define FLEXCOP_MODULE_NAME "b2c2-flexcop"
#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
struct flexcop_pci {
@@ -299,7 +300,7 @@ static int flexcop_pci_init(struct flexc
return ret;
pci_set_master(fc_pci->pdev);
- if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0)
+ if ((ret = pci_request_regions(fc_pci->pdev, FLEXCOP_MODULE_NAME)) != 0)
goto err_pci_disable_device;
fc_pci->io_mem = pci_iomap(fc_pci->pdev, 0, 0x800);
@@ -313,7 +314,7 @@ static int flexcop_pci_init(struct flexc
pci_set_drvdata(fc_pci->pdev, fc_pci);
spin_lock_init(&fc_pci->irq_lock);
if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_isr,
- IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0)
+ IRQF_SHARED, FLEXCOP_MODULE_NAME, fc_pci)) != 0)
goto err_pci_iounmap;
fc_pci->init_state |= FC_PCI_INIT;

View File

@ -0,0 +1,54 @@
From: Timo Warns <Warns@pre-sense.de>
Subject: fs/partitions/efi.c: corrupted GUID partition tables can cause kernel oops
References: bnc#687113 CVE-2011-1577
Patch-mainline: Probably 2.6.39; In -mm already
The kernel automatically evaluates partition tables of storage devices.
The code for evaluating GUID partitions (in fs/partitions/efi.c) contains
a bug that causes a kernel oops on certain corrupted GUID partition
tables.
This bug has security impacts, because it allows, for example, to
prepare a storage device that crashes a kernel subsystem upon connecting
the device (e.g., a "USB Stick of (Partial) Death").
crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size));
computes a CRC32 checksum over gpt covering (*gpt)->header_size bytes.
There is no validation of (*gpt)->header_size before the efi_crc32 call.
A corrupted partition table may have large values for (*gpt)->header_size.
In this case, the CRC32 computation access memory beyond the memory
allocated for gpt, which may cause a kernel heap overflow.
Validate value of GUID partition table header size.
Signed-off-by: Timo Warns <warns@pre-sense.de>
Cc: Matt Domsch <Matt_Domsch@dell.com>
Cc: Eugene Teo <eugeneteo@kernel.sg>
Cc: Dave Jones <davej@codemonkey.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Jeff Mahoney <jeffm@suse.com>
---
fs/partitions/efi.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/fs/partitions/efi.c
+++ b/fs/partitions/efi.c
@@ -310,6 +310,15 @@ static int is_gpt_valid(struct parsed_pa
goto fail;
}
+ /* Check the GUID Partition Table header size */
+ if (le32_to_cpu((*gpt)->header_size) >
+ bdev_logical_block_size(state->bdev)) {
+ pr_debug("GUID Partition Table Header size is wrong: %u > %u\n",
+ le32_to_cpu((*gpt)->header_size),
+ bdev_logical_block_size(state->bdev));
+ goto fail;
+ }
+
/* Check the GUID Partition Table CRC */
origcrc = le32_to_cpu((*gpt)->header_crc32);
(*gpt)->header_crc32 = 0;

View File

@ -0,0 +1,30 @@
From: Dean Roe <roe@sgi.com>
Subject: Prevent NULL pointer deref in grab_swap_token
References: 159260
Patch-mainline: not yet
grab_swap_token() assumes that the current process has an mm struct,
which is not true for kernel threads invoking get_user_pages(). Since
this should be extremely rare, just return from grab_swap_token()
without doing anything.
Signed-off-by: Dean Roe <roe@sgi.com>
Acked-by: mason@suse.de
Acked-by: okir@suse.de
mm/thrash.c | 3 +++
1 file changed, 3 insertions(+)
--- a/mm/thrash.c
+++ b/mm/thrash.c
@@ -31,6 +31,9 @@ void grab_swap_token(struct mm_struct *m
int current_interval;
global_faults++;
+ if (mm == NULL)
+ return;
+
current_interval = global_faults - mm->faultstamp;

View File

@ -0,0 +1,30 @@
From: Jeff Mahoney <jeffm@suse.com>
Subject: hfs: avoid crash in hfs_bnode_create
Patch-mainline: not yet
References: bnc#552250
Commit 634725a92938b0f282b17cec0b007dca77adebd2 removed the BUG_ON
in hfs_bnode_create in hfsplus. This patch removes it from the hfs
version and avoids an fsfuzzer crash.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Acked-by: Jeff Mahoney <jeffm@suse.com>
---
fs/hfs/bnode.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -413,7 +413,11 @@ struct hfs_bnode *hfs_bnode_create(struc
spin_lock(&tree->hash_lock);
node = hfs_bnode_findhash(tree, num);
spin_unlock(&tree->hash_lock);
- BUG_ON(node);
+ if (node) {
+ printk(KERN_CRIT "new node %u already hashed?\n", num);
+ WARN_ON(1);
+ return node;
+ }
node = __hfs_bnode_create(tree, num);
if (!node)
return ERR_PTR(-ENOMEM);

View File

@ -0,0 +1,102 @@
From: Jiri Kosina <jkosina@suse.cz>
Subject: [PATCH] HID: add support for Skycable 0x3f07 wireless presenter
References: bnc#681297
Patch-mainline: not yet, queued in subsystem tree
This device contains the very same bug in report descriptor as the
Ortek ones do (i.e. LogicalMinimum == 1, which is wrong for the key
array).
As we have more reports for the Ortek devices, we are keeping the driver
name for now. Apparently there is a chip producer which sells chip with
this buggy descriptor to multiple vendors. Thus if such reports start
to come at highger frequency, we'll either have to rename the driver
accordingly, or come up with more generic workaround.
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
drivers/hid/Kconfig | 9 +++++++--
drivers/hid/hid-core.c | 1 +
drivers/hid/hid-ids.h | 3 +++
drivers/hid/hid-ortek.c | 15 +++++++++++----
4 files changed, 22 insertions(+), 6 deletions(-)
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -325,10 +325,15 @@ config HID_NTRIG
Support for N-Trig touch screen.
config HID_ORTEK
- tristate "Ortek PKB-1700/WKB-2000 wireless keyboard and mouse trackpad"
+ tristate "Ortek WKB-2000/Skycable wireless keyboard and mouse trackpad"
depends on USB_HID
---help---
- Support for Ortek PKB-1700/WKB-2000 wireless keyboard + mouse trackpad.
+ There are certain devices which have LogicalMaximum wrong in the keyboard
+ usage page of their report descriptor. The most prevailing ones so far
+ are manufactured by Ortek, thus the name of the driver. Currently
+ supported devices by this driver are
+ - Ortek WKB-2000
+ - Skycable wireless presenter
config HID_PANTHERLORD
tristate "Pantherlord/GreenAsia game controller"
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1411,6 +1411,7 @@ static const struct hid_device_id hid_ha
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -514,6 +514,9 @@
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
#define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600
+#define USB_VENDOR_ID_SKYCABLE 0x1223
+#define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07
+
#define USB_VENDOR_ID_SONY 0x054c
#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
--- a/drivers/hid/hid-ortek.c
+++ b/drivers/hid/hid-ortek.c
@@ -1,9 +1,12 @@
-/*
- * HID driver for Ortek PKB-1700/WKB-2000 (wireless keyboard + mouse trackpad).
- * Fixes LogicalMaximum error in USB report description, see
- * http://bugzilla.kernel.org/show_bug.cgi?id=14787
+/* HID driver for various devices which are apparently based on the same chipset
+ * from certain vendor which produces chips that contain wrong LogicalMaximum
+ * value in their HID report descriptor. Currently supported devices are:
+ *
+ * Ortek WKB-2000
+ * Skycable wireless presenter
*
* Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com>
+ * Copyright (c) 2011 Jiri Kosina
*/
/*
@@ -25,6 +28,9 @@ static __u8 *ortek_report_fixup(struct h
if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) {
hid_info(hdev, "Fixing up Ortek WKB-2000 report descriptor\n");
rdesc[55] = 0x92;
+ } else if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) {
+ hid_info(hdev, "Fixing up logical minimum in report descriptor (Skycable)\n");
+ rdesc[53] = 0x65;
}
return rdesc;
}
@@ -32,6 +38,7 @@ static __u8 *ortek_report_fixup(struct h
static const struct hid_device_id ortek_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
{ }
};
MODULE_DEVICE_TABLE(hid, ortek_devices);

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