Update to 3.17-rc4
- Drop and refresh various patches which are included in or conflict with upstream - Drop the patch restoring sm7xxfb, as no-one is maintaining it - Disable aufs temporarily svn path=/dists/trunk/linux/; revision=21840
This commit is contained in:
parent
cf68605af6
commit
fc56a07b4e
|
@ -1,3 +1,9 @@
|
|||
linux (3.17~rc4-1~exp1) UNRELEASED; urgency=medium
|
||||
|
||||
* New upstream release candidate
|
||||
|
||||
-- Ben Hutchings <ben@decadent.org.uk> Sat, 13 Sep 2014 06:42:35 +0100
|
||||
|
||||
linux (3.16.2-3) unstable; urgency=medium
|
||||
|
||||
[ Ben Hutchings ]
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
From: Benjamin LaHaise <bcrl@kvack.org>
|
||||
Date: Sun, 24 Aug 2014 13:14:05 -0400
|
||||
Subject: aio: fix reqs_available handling
|
||||
Origin: https://git.kernel.org/linus/d856f32a86b2b015ab180ab7a55e455ed8d3ccc5
|
||||
|
||||
As reported by Dan Aloni, commit f8567a3845ac ("aio: fix aio request
|
||||
leak when events are reaped by userspace") introduces a regression when
|
||||
user code attempts to perform io_submit() with more events than are
|
||||
available in the ring buffer. Reverting that commit would reintroduce a
|
||||
regression when user space event reaping is used.
|
||||
|
||||
Fixing this bug is a bit more involved than the previous attempts to fix
|
||||
this regression. Since we do not have a single point at which we can
|
||||
count events as being reaped by user space and io_getevents(), we have
|
||||
to track event completion by looking at the number of events left in the
|
||||
event ring. So long as there are as many events in the ring buffer as
|
||||
there have been completion events generate, we cannot call
|
||||
put_reqs_available(). The code to check for this is now placed in
|
||||
refill_reqs_available().
|
||||
|
||||
A test program from Dan and modified by me for verifying this bug is available
|
||||
at http://www.kvack.org/~bcrl/20140824-aio_bug.c .
|
||||
|
||||
Reported-by: Dan Aloni <dan@kernelim.com>
|
||||
Signed-off-by: Benjamin LaHaise <bcrl@kvack.org>
|
||||
Acked-by: Dan Aloni <dan@kernelim.com>
|
||||
Cc: Kent Overstreet <kmo@daterainc.com>
|
||||
Cc: Mateusz Guzik <mguzik@redhat.com>
|
||||
Cc: Petr Matousek <pmatouse@redhat.com>
|
||||
Cc: stable@vger.kernel.org # v3.16 and anything that f8567a3845ac was backported to
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
fs/aio.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 73 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/fs/aio.c
|
||||
+++ b/fs/aio.c
|
||||
@@ -141,6 +141,7 @@ struct kioctx {
|
||||
|
||||
struct {
|
||||
unsigned tail;
|
||||
+ unsigned completed_events;
|
||||
spinlock_t completion_lock;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
@@ -880,6 +881,68 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* refill_reqs_available
|
||||
+ * Updates the reqs_available reference counts used for tracking the
|
||||
+ * number of free slots in the completion ring. This can be called
|
||||
+ * from aio_complete() (to optimistically update reqs_available) or
|
||||
+ * from aio_get_req() (the we're out of events case). It must be
|
||||
+ * called holding ctx->completion_lock.
|
||||
+ */
|
||||
+static void refill_reqs_available(struct kioctx *ctx, unsigned head,
|
||||
+ unsigned tail)
|
||||
+{
|
||||
+ unsigned events_in_ring, completed;
|
||||
+
|
||||
+ /* Clamp head since userland can write to it. */
|
||||
+ head %= ctx->nr_events;
|
||||
+ if (head <= tail)
|
||||
+ events_in_ring = tail - head;
|
||||
+ else
|
||||
+ events_in_ring = ctx->nr_events - (head - tail);
|
||||
+
|
||||
+ completed = ctx->completed_events;
|
||||
+ if (events_in_ring < completed)
|
||||
+ completed -= events_in_ring;
|
||||
+ else
|
||||
+ completed = 0;
|
||||
+
|
||||
+ if (!completed)
|
||||
+ return;
|
||||
+
|
||||
+ ctx->completed_events -= completed;
|
||||
+ put_reqs_available(ctx, completed);
|
||||
+}
|
||||
+
|
||||
+/* user_refill_reqs_available
|
||||
+ * Called to refill reqs_available when aio_get_req() encounters an
|
||||
+ * out of space in the completion ring.
|
||||
+ */
|
||||
+static void user_refill_reqs_available(struct kioctx *ctx)
|
||||
+{
|
||||
+ spin_lock_irq(&ctx->completion_lock);
|
||||
+ if (ctx->completed_events) {
|
||||
+ struct aio_ring *ring;
|
||||
+ unsigned head;
|
||||
+
|
||||
+ /* Access of ring->head may race with aio_read_events_ring()
|
||||
+ * here, but that's okay since whether we read the old version
|
||||
+ * or the new version, and either will be valid. The important
|
||||
+ * part is that head cannot pass tail since we prevent
|
||||
+ * aio_complete() from updating tail by holding
|
||||
+ * ctx->completion_lock. Even if head is invalid, the check
|
||||
+ * against ctx->completed_events below will make sure we do the
|
||||
+ * safe/right thing.
|
||||
+ */
|
||||
+ ring = kmap_atomic(ctx->ring_pages[0]);
|
||||
+ head = ring->head;
|
||||
+ kunmap_atomic(ring);
|
||||
+
|
||||
+ refill_reqs_available(ctx, head, ctx->tail);
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock_irq(&ctx->completion_lock);
|
||||
+}
|
||||
+
|
||||
/* aio_get_req
|
||||
* Allocate a slot for an aio request.
|
||||
* Returns NULL if no requests are free.
|
||||
@@ -888,8 +951,11 @@ static inline struct kiocb *aio_get_req(
|
||||
{
|
||||
struct kiocb *req;
|
||||
|
||||
- if (!get_reqs_available(ctx))
|
||||
- return NULL;
|
||||
+ if (!get_reqs_available(ctx)) {
|
||||
+ user_refill_reqs_available(ctx);
|
||||
+ if (!get_reqs_available(ctx))
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL|__GFP_ZERO);
|
||||
if (unlikely(!req))
|
||||
@@ -948,8 +1014,8 @@ void aio_complete(struct kiocb *iocb, lo
|
||||
struct kioctx *ctx = iocb->ki_ctx;
|
||||
struct aio_ring *ring;
|
||||
struct io_event *ev_page, *event;
|
||||
+ unsigned tail, pos, head;
|
||||
unsigned long flags;
|
||||
- unsigned tail, pos;
|
||||
|
||||
/*
|
||||
* Special case handling for sync iocbs:
|
||||
@@ -1010,10 +1076,14 @@ void aio_complete(struct kiocb *iocb, lo
|
||||
ctx->tail = tail;
|
||||
|
||||
ring = kmap_atomic(ctx->ring_pages[0]);
|
||||
+ head = ring->head;
|
||||
ring->tail = tail;
|
||||
kunmap_atomic(ring);
|
||||
flush_dcache_page(ctx->ring_pages[0]);
|
||||
|
||||
+ ctx->completed_events++;
|
||||
+ if (ctx->completed_events > 1)
|
||||
+ refill_reqs_available(ctx, head, tail);
|
||||
spin_unlock_irqrestore(&ctx->completion_lock, flags);
|
||||
|
||||
pr_debug("added to ring %p at [%u]\n", iocb, tail);
|
||||
@@ -1028,7 +1098,6 @@ void aio_complete(struct kiocb *iocb, lo
|
||||
|
||||
/* everything turned out well, dispose of the aiocb. */
|
||||
kiocb_free(iocb);
|
||||
- put_reqs_available(ctx, 1);
|
||||
|
||||
/*
|
||||
* We have to order our ring_info tail store above and test
|
|
@ -96,8 +96,8 @@ upstream submission.
|
|||
fw_size = firmware->size / sizeof(u32);
|
||||
--- a/drivers/bluetooth/ath3k.c
|
||||
+++ b/drivers/bluetooth/ath3k.c
|
||||
@@ -370,10 +370,8 @@ static int ath3k_load_patch(struct usb_d
|
||||
le32_to_cpu(fw_version.rom_version));
|
||||
@@ -375,10 +375,8 @@ static int ath3k_load_patch(struct usb_d
|
||||
le32_to_cpu(fw_version.rom_version));
|
||||
|
||||
ret = request_firmware(&firmware, filename, &udev->dev);
|
||||
- if (ret < 0) {
|
||||
|
@ -106,9 +106,9 @@ upstream submission.
|
|||
return ret;
|
||||
- }
|
||||
|
||||
pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8);
|
||||
pt_version.build_version = *(int *)
|
||||
@@ -432,10 +430,8 @@ static int ath3k_load_syscfg(struct usb_
|
||||
pt_rom_version = get_unaligned_le32(firmware->data +
|
||||
firmware->size - 8);
|
||||
@@ -438,10 +436,8 @@ static int ath3k_load_syscfg(struct usb_
|
||||
le32_to_cpu(fw_version.rom_version), clk_value, ".dfu");
|
||||
|
||||
ret = request_firmware(&firmware, filename, &udev->dev);
|
||||
|
@ -168,7 +168,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/bluetooth/btmrvl_sdio.c
|
||||
+++ b/drivers/bluetooth/btmrvl_sdio.c
|
||||
@@ -288,8 +288,6 @@ static int btmrvl_sdio_download_helper(s
|
||||
@@ -297,8 +297,6 @@ static int btmrvl_sdio_download_helper(s
|
||||
ret = request_firmware(&fw_helper, card->helper,
|
||||
&card->func->dev);
|
||||
if ((ret < 0) || !fw_helper) {
|
||||
|
@ -177,7 +177,7 @@ upstream submission.
|
|||
ret = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
@@ -388,8 +386,6 @@ static int btmrvl_sdio_download_fw_w_hel
|
||||
@@ -397,8 +395,6 @@ static int btmrvl_sdio_download_fw_w_hel
|
||||
ret = request_firmware(&fw_firmware, card->firmware,
|
||||
&card->func->dev);
|
||||
if ((ret < 0) || !fw_firmware) {
|
||||
|
@ -203,7 +203,7 @@ upstream submission.
|
|||
fw->size, fw_name);
|
||||
--- a/drivers/dma/imx-sdma.c
|
||||
+++ b/drivers/dma/imx-sdma.c
|
||||
@@ -1269,10 +1269,8 @@ static void sdma_load_firmware(const str
|
||||
@@ -1286,10 +1286,8 @@ static void sdma_load_firmware(const str
|
||||
const struct sdma_script_start_addrs *addr;
|
||||
unsigned short *ram_code;
|
||||
|
||||
|
@ -232,7 +232,7 @@ upstream submission.
|
|||
where = 0;
|
||||
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
|
||||
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
|
||||
@@ -1221,10 +1221,8 @@ nvc0_graph_ctor_fw(struct nvc0_graph_pri
|
||||
@@ -1496,10 +1496,8 @@ nvc0_graph_ctor_fw(struct nvc0_graph_pri
|
||||
if (ret) {
|
||||
snprintf(f, sizeof(f), "nouveau/%s", fwname);
|
||||
ret = request_firmware(&fw, f, nv_device_base(device));
|
||||
|
@ -274,7 +274,7 @@ upstream submission.
|
|||
release_firmware(rdev->me_fw);
|
||||
--- a/drivers/gpu/drm/radeon/r100.c
|
||||
+++ b/drivers/gpu/drm/radeon/r100.c
|
||||
@@ -1036,10 +1036,7 @@ static int r100_cp_init_microcode(struct
|
||||
@@ -1012,10 +1012,7 @@ static int r100_cp_init_microcode(struct
|
||||
}
|
||||
|
||||
err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
|
||||
|
@ -288,7 +288,7 @@ upstream submission.
|
|||
rdev->me_fw->size, fw_name);
|
||||
--- a/drivers/gpu/drm/radeon/r600.c
|
||||
+++ b/drivers/gpu/drm/radeon/r600.c
|
||||
@@ -2434,10 +2434,6 @@ int r600_init_microcode(struct radeon_de
|
||||
@@ -2426,10 +2426,6 @@ int r600_init_microcode(struct radeon_de
|
||||
|
||||
out:
|
||||
if (err) {
|
||||
|
@ -342,7 +342,7 @@ upstream submission.
|
|||
ret = qib_ibsd_ucode_loaded(dd->pport, fw);
|
||||
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
|
||||
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
|
||||
@@ -1236,10 +1236,8 @@ static int mxt_load_fw(struct device *de
|
||||
@@ -1932,10 +1932,8 @@ static int mxt_load_fw(struct device *de
|
||||
int ret;
|
||||
|
||||
ret = request_firmware(&fw, fn, dev);
|
||||
|
@ -381,7 +381,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
|
||||
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
|
||||
@@ -2256,12 +2256,9 @@ static int stk9090m_frontend_attach(stru
|
||||
@@ -2372,12 +2372,9 @@ static int stk9090m_frontend_attach(stru
|
||||
|
||||
dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80);
|
||||
|
||||
|
@ -396,7 +396,7 @@ upstream submission.
|
|||
stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size;
|
||||
stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data;
|
||||
|
||||
@@ -2322,12 +2319,9 @@ static int nim9090md_frontend_attach(str
|
||||
@@ -2438,12 +2435,9 @@ static int nim9090md_frontend_attach(str
|
||||
msleep(20);
|
||||
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
|
||||
|
||||
|
@ -468,7 +468,7 @@ upstream submission.
|
|||
p = kmalloc(fw->size, GFP_KERNEL);
|
||||
--- a/drivers/media/dvb-frontends/af9013.c
|
||||
+++ b/drivers/media/dvb-frontends/af9013.c
|
||||
@@ -1373,16 +1373,8 @@ static int af9013_download_firmware(stru
|
||||
@@ -1372,16 +1372,8 @@ static int af9013_download_firmware(stru
|
||||
|
||||
/* request the firmware, this will block and timeout */
|
||||
ret = request_firmware(&fw, fw_file, state->i2c->dev.parent);
|
||||
|
@ -685,7 +685,7 @@ upstream submission.
|
|||
printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n",
|
||||
--- a/drivers/media/dvb-frontends/tda10071.c
|
||||
+++ b/drivers/media/dvb-frontends/tda10071.c
|
||||
@@ -952,12 +952,8 @@ static int tda10071_init(struct dvb_fron
|
||||
@@ -956,12 +956,8 @@ static int tda10071_init(struct dvb_fron
|
||||
|
||||
/* request the firmware, this will block and timeout */
|
||||
ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
|
||||
|
@ -701,7 +701,7 @@ upstream submission.
|
|||
for (i = 0; i < ARRAY_SIZE(tab2); i++) {
|
||||
--- a/drivers/media/pci/ngene/ngene-core.c
|
||||
+++ b/drivers/media/pci/ngene/ngene-core.c
|
||||
@@ -1266,13 +1266,8 @@ static int ngene_load_firm(struct ngene
|
||||
@@ -1262,13 +1262,8 @@ static int ngene_load_firm(struct ngene
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -716,7 +716,7 @@ upstream submission.
|
|||
if (size == 0)
|
||||
size = fw->size;
|
||||
if (size != fw->size) {
|
||||
@@ -1280,8 +1275,6 @@ static int ngene_load_firm(struct ngene
|
||||
@@ -1276,8 +1271,6 @@ static int ngene_load_firm(struct ngene
|
||||
": Firmware %s has invalid size!", fw_name);
|
||||
err = -1;
|
||||
} else {
|
||||
|
@ -791,7 +791,7 @@ upstream submission.
|
|||
b[0] = 0xaa;
|
||||
--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c
|
||||
+++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c
|
||||
@@ -1302,11 +1302,8 @@ static int ttusb_dec_boot_dsp(struct ttu
|
||||
@@ -1297,11 +1297,8 @@ static int ttusb_dec_boot_dsp(struct ttu
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
result = request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev);
|
||||
|
@ -835,7 +835,7 @@ upstream submission.
|
|||
fw_data = (void *)fw_entry->data;
|
||||
--- a/drivers/media/pci/bt8xx/bttv-cards.c
|
||||
+++ b/drivers/media/pci/bt8xx/bttv-cards.c
|
||||
@@ -3814,10 +3814,8 @@ static int pvr_boot(struct bttv *btv)
|
||||
@@ -3834,10 +3834,8 @@ static int pvr_boot(struct bttv *btv)
|
||||
int rc;
|
||||
|
||||
rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev);
|
||||
|
@ -958,7 +958,7 @@ upstream submission.
|
|||
printk(KERN_ERR "ERROR: Firmware size mismatch "
|
||||
--- a/drivers/media/pci/cx23885/cx23885-cards.c
|
||||
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
|
||||
@@ -1905,11 +1905,7 @@ void cx23885_card_setup(struct cx23885_d
|
||||
@@ -1958,11 +1958,7 @@ void cx23885_card_setup(struct cx23885_d
|
||||
cinfo.rev, filename);
|
||||
|
||||
ret = request_firmware(&fw, filename, &dev->pci->dev);
|
||||
|
@ -1061,7 +1061,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/media/usb/s2255/s2255drv.c
|
||||
+++ b/drivers/media/usb/s2255/s2255drv.c
|
||||
@@ -2306,10 +2306,8 @@ static int s2255_probe(struct usb_interf
|
||||
@@ -2304,10 +2304,8 @@ static int s2255_probe(struct usb_interf
|
||||
}
|
||||
/* load the first chunk */
|
||||
if (request_firmware(&dev->fw_data->fw,
|
||||
|
@ -1075,22 +1075,10 @@ upstream submission.
|
|||
pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8];
|
||||
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
|
||||
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
|
||||
@@ -86,10 +86,8 @@ int s5p_mfc_load_firmware(struct s5p_mfc
|
||||
@@ -94,10 +94,8 @@ int s5p_mfc_load_firmware(struct s5p_mfc
|
||||
}
|
||||
}
|
||||
|
||||
err = request_firmware((const struct firmware **)&fw_blob,
|
||||
dev->variant->fw_name, dev->v4l2_dev.dev);
|
||||
- if (err != 0) {
|
||||
- mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
|
||||
+ if (err != 0)
|
||||
return -EINVAL;
|
||||
- }
|
||||
if (fw_blob->size > dev->fw_size) {
|
||||
mfc_err("MFC firmware is too big to be loaded\n");
|
||||
release_firmware(fw_blob);
|
||||
@@ -119,10 +117,8 @@ int s5p_mfc_reload_firmware(struct s5p_m
|
||||
|
||||
err = request_firmware((const struct firmware **)&fw_blob,
|
||||
dev->variant->fw_name, dev->v4l2_dev.dev);
|
||||
- if (err != 0) {
|
||||
- mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
|
||||
+ if (err != 0)
|
||||
|
@ -1130,7 +1118,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/misc/ti-st/st_kim.c
|
||||
+++ b/drivers/misc/ti-st/st_kim.c
|
||||
@@ -301,11 +301,8 @@ static long download_firmware(struct kim
|
||||
@@ -302,11 +302,8 @@ static long download_firmware(struct kim
|
||||
request_firmware(&kim_gdata->fw_entry, bts_scr_name,
|
||||
&kim_gdata->kim_pdev->dev);
|
||||
if (unlikely((err != 0) || (kim_gdata->fw_entry->data == NULL) ||
|
||||
|
@ -1218,7 +1206,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/net/ethernet/broadcom/bnx2.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bnx2.c
|
||||
@@ -3700,16 +3700,13 @@ static int bnx2_request_uncached_firmwar
|
||||
@@ -3701,16 +3701,13 @@ static int bnx2_request_uncached_firmwar
|
||||
}
|
||||
|
||||
rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev);
|
||||
|
@ -1240,7 +1228,7 @@ upstream submission.
|
|||
if (bp->mips_firmware->size < sizeof(*mips_fw) ||
|
||||
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
|
||||
@@ -12775,11 +12775,8 @@ static int bnx2x_init_firmware(struct bn
|
||||
@@ -12747,11 +12747,8 @@ static int bnx2x_init_firmware(struct bn
|
||||
BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
|
||||
|
||||
rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev);
|
||||
|
@ -1255,7 +1243,7 @@ upstream submission.
|
|||
if (rc) {
|
||||
--- a/drivers/net/ethernet/broadcom/tg3.c
|
||||
+++ b/drivers/net/ethernet/broadcom/tg3.c
|
||||
@@ -11286,11 +11286,8 @@ static int tg3_request_firmware(struct t
|
||||
@@ -11305,11 +11305,8 @@ static int tg3_request_firmware(struct t
|
||||
{
|
||||
const struct tg3_firmware_hdr *fw_hdr;
|
||||
|
||||
|
@ -1338,7 +1326,7 @@ upstream submission.
|
|||
netif_info(nic, probe, nic->netdev,
|
||||
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
|
||||
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
|
||||
@@ -600,8 +600,6 @@ static int myri10ge_load_hotplug_firmwar
|
||||
@@ -601,8 +601,6 @@ static int myri10ge_load_hotplug_firmwar
|
||||
unsigned i;
|
||||
|
||||
if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) {
|
||||
|
@ -1431,7 +1419,7 @@ upstream submission.
|
|||
} else
|
||||
--- a/drivers/net/wireless/at76c50x-usb.c
|
||||
+++ b/drivers/net/wireless/at76c50x-usb.c
|
||||
@@ -1553,13 +1553,8 @@ static struct fwentry *at76_load_firmwar
|
||||
@@ -1622,13 +1622,8 @@ static struct fwentry *at76_load_firmwar
|
||||
|
||||
at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname);
|
||||
ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev);
|
||||
|
@ -1464,7 +1452,7 @@ upstream submission.
|
|||
&hif_dev->udev->dev);
|
||||
--- a/drivers/net/wireless/ath/carl9170/usb.c
|
||||
+++ b/drivers/net/wireless/ath/carl9170/usb.c
|
||||
@@ -1025,7 +1025,6 @@ static void carl9170_usb_firmware_step2(
|
||||
@@ -1032,7 +1032,6 @@ static void carl9170_usb_firmware_step2(
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1490,7 +1478,7 @@ upstream submission.
|
|||
int success = 0;
|
||||
--- a/drivers/net/wireless/b43/main.c
|
||||
+++ b/drivers/net/wireless/b43/main.c
|
||||
@@ -2160,19 +2160,8 @@ int b43_do_request_fw(struct b43_request
|
||||
@@ -2185,19 +2185,8 @@ int b43_do_request_fw(struct b43_request
|
||||
}
|
||||
err = request_firmware(&ctx->blob, ctx->fwname,
|
||||
ctx->dev->dev->dev);
|
||||
|
@ -1552,7 +1540,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
|
||||
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
|
||||
@@ -8425,12 +8425,8 @@ static int ipw2100_get_firmware(struct i
|
||||
@@ -8419,12 +8419,8 @@ static int ipw2100_get_firmware(struct i
|
||||
|
||||
rc = request_firmware(&fw->fw_entry, fw_name, &priv->pci_dev->dev);
|
||||
|
||||
|
@ -1592,7 +1580,7 @@ upstream submission.
|
|||
else
|
||||
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
|
||||
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
|
||||
@@ -979,13 +979,8 @@ static void iwl_req_fw_callback(const st
|
||||
@@ -990,13 +990,8 @@ static void iwl_req_fw_callback(const st
|
||||
|
||||
memset(&pieces, 0, sizeof(pieces));
|
||||
|
||||
|
@ -1620,7 +1608,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/net/wireless/mwifiex/main.c
|
||||
+++ b/drivers/net/wireless/mwifiex/main.c
|
||||
@@ -421,11 +421,8 @@ static void mwifiex_fw_dpc(const struct
|
||||
@@ -427,11 +427,8 @@ static void mwifiex_fw_dpc(const struct
|
||||
bool init_failed = false;
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
|
@ -1635,7 +1623,7 @@ upstream submission.
|
|||
adapter->firmware = firmware;
|
||||
--- a/drivers/net/wireless/mwl8k.c
|
||||
+++ b/drivers/net/wireless/mwl8k.c
|
||||
@@ -5715,16 +5715,12 @@ static int mwl8k_firmware_load_success(s
|
||||
@@ -5708,16 +5708,12 @@ static int mwl8k_firmware_load_success(s
|
||||
static void mwl8k_fw_state_machine(const struct firmware *fw, void *context)
|
||||
{
|
||||
struct mwl8k_priv *priv = context;
|
||||
|
@ -1653,7 +1641,7 @@ upstream submission.
|
|||
priv->fw_helper = fw;
|
||||
rc = mwl8k_request_fw(priv, priv->fw_pref, &priv->fw_ucode,
|
||||
true);
|
||||
@@ -5759,11 +5755,8 @@ static void mwl8k_fw_state_machine(const
|
||||
@@ -5752,11 +5748,8 @@ static void mwl8k_fw_state_machine(const
|
||||
break;
|
||||
|
||||
case FW_STATE_LOADING_ALT:
|
||||
|
@ -1666,7 +1654,7 @@ upstream submission.
|
|||
priv->fw_ucode = fw;
|
||||
rc = mwl8k_firmware_load_success(priv);
|
||||
if (rc)
|
||||
@@ -5801,10 +5794,8 @@ retry:
|
||||
@@ -5794,10 +5787,8 @@ retry:
|
||||
|
||||
/* Ask userland hotplug daemon for the device firmware */
|
||||
rc = mwl8k_request_firmware(priv, fw_image, nowait);
|
||||
|
@ -1714,7 +1702,7 @@ upstream submission.
|
|||
|
||||
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
|
||||
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
|
||||
@@ -1690,7 +1690,6 @@ static int ezusb_probe(struct usb_interf
|
||||
@@ -1675,7 +1675,6 @@ static int ezusb_probe(struct usb_interf
|
||||
if (ezusb_firmware_download(upriv, &firmware) < 0)
|
||||
goto error;
|
||||
} else {
|
||||
|
@ -1835,7 +1823,7 @@ upstream submission.
|
|||
wl1251_error("nvs size is not multiple of 32 bits: %zu",
|
||||
--- a/drivers/net/wireless/ti/wlcore/main.c
|
||||
+++ b/drivers/net/wireless/ti/wlcore/main.c
|
||||
@@ -748,10 +748,8 @@ static int wl12xx_fetch_firmware(struct
|
||||
@@ -749,10 +749,8 @@ static int wl12xx_fetch_firmware(struct
|
||||
|
||||
ret = request_firmware(&fw, fw_name, wl->dev);
|
||||
|
||||
|
@ -1944,7 +1932,7 @@ upstream submission.
|
|||
if (err) {
|
||||
--- a/drivers/scsi/bfa/bfad.c
|
||||
+++ b/drivers/scsi/bfa/bfad.c
|
||||
@@ -1778,7 +1778,6 @@ bfad_read_firmware(struct pci_dev *pdev,
|
||||
@@ -1766,7 +1766,6 @@ bfad_read_firmware(struct pci_dev *pdev,
|
||||
const struct firmware *fw;
|
||||
|
||||
if (request_firmware(&fw, fw_name, &pdev->dev)) {
|
||||
|
@ -1968,15 +1956,16 @@ upstream submission.
|
|||
|
||||
--- a/drivers/scsi/pm8001/pm8001_ctl.c
|
||||
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
|
||||
@@ -676,9 +676,6 @@ static ssize_t pm8001_store_update_fw(st
|
||||
@@ -687,10 +687,6 @@ static ssize_t pm8001_store_update_fw(st
|
||||
pm8001_ha->dev);
|
||||
|
||||
if (err) {
|
||||
if (ret) {
|
||||
- PM8001_FAIL_DBG(pm8001_ha,
|
||||
- pm8001_printk("Failed to load firmware image file %s,"
|
||||
- " error %d\n", filename_ptr, err));
|
||||
err = FAIL_OPEN_BIOS_FILE;
|
||||
goto out1;
|
||||
- pm8001_printk(
|
||||
- "Failed to load firmware image file %s, error %d\n",
|
||||
- filename_ptr, ret));
|
||||
pm8001_ha->fw_status = FAIL_OPEN_BIOS_FILE;
|
||||
goto out;
|
||||
}
|
||||
--- a/drivers/scsi/qla1280.c
|
||||
+++ b/drivers/scsi/qla1280.c
|
||||
|
@ -1991,7 +1980,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/scsi/qla2xxx/qla_init.c
|
||||
+++ b/drivers/scsi/qla2xxx/qla_init.c
|
||||
@@ -5358,8 +5358,6 @@ qla2x00_load_risc(scsi_qla_host_t *vha,
|
||||
@@ -5350,8 +5350,6 @@ qla2x00_load_risc(scsi_qla_host_t *vha,
|
||||
/* Load firmware blob. */
|
||||
blob = qla2x00_request_firmware(vha);
|
||||
if (!blob) {
|
||||
|
@ -2000,7 +1989,7 @@ upstream submission.
|
|||
ql_log(ql_log_info, vha, 0x0084,
|
||||
"Firmware images can be retrieved from: "QLA_FW_URL ".\n");
|
||||
return QLA_FUNCTION_FAILED;
|
||||
@@ -5461,8 +5459,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t *
|
||||
@@ -5453,8 +5451,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t *
|
||||
/* Load firmware blob. */
|
||||
blob = qla2x00_request_firmware(vha);
|
||||
if (!blob) {
|
||||
|
@ -2011,7 +2000,7 @@ upstream submission.
|
|||
QLA_FW_URL ".\n");
|
||||
--- a/drivers/scsi/qla2xxx/qla_nx.c
|
||||
+++ b/drivers/scsi/qla2xxx/qla_nx.c
|
||||
@@ -2449,11 +2449,8 @@ try_blob_fw:
|
||||
@@ -2459,11 +2459,8 @@ try_blob_fw:
|
||||
|
||||
/* Load firmware blob. */
|
||||
blob = ha->hablob = qla2x00_request_firmware(vha);
|
||||
|
@ -2026,7 +2015,7 @@ upstream submission.
|
|||
if (qla82xx_validate_firmware_blob(vha,
|
||||
--- a/drivers/scsi/qla2xxx/qla_os.c
|
||||
+++ b/drivers/scsi/qla2xxx/qla_os.c
|
||||
@@ -5393,8 +5393,6 @@ qla2x00_request_firmware(scsi_qla_host_t
|
||||
@@ -5413,8 +5413,6 @@ qla2x00_request_firmware(scsi_qla_host_t
|
||||
goto out;
|
||||
|
||||
if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
|
||||
|
@ -2052,7 +2041,7 @@ upstream submission.
|
|||
fw->size, fwname);
|
||||
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
|
||||
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
|
||||
@@ -2233,16 +2233,12 @@ struct net_device *init_ft1000_card(stru
|
||||
@@ -2230,16 +2230,12 @@ struct net_device *init_ft1000_card(stru
|
||||
info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
|
||||
if (info->AsicID == ELECTRABUZZ_ID) {
|
||||
DEBUG(0, "ft1000_hw: ELECTRABUZZ ASIC\n");
|
||||
|
@ -2113,9 +2102,9 @@ upstream submission.
|
|||
|
||||
/* initiate firmware upload */
|
||||
errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
|
||||
--- a/drivers/staging/media/go7007/go7007-driver.c
|
||||
+++ b/drivers/staging/media/go7007/go7007-driver.c
|
||||
@@ -95,10 +95,8 @@ static int go7007_load_encoder(struct go
|
||||
--- a/drivers/media/usb/go7007/go7007-driver.c
|
||||
+++ b/drivers/media/usb/go7007/go7007-driver.c
|
||||
@@ -92,10 +92,8 @@ static int go7007_load_encoder(struct go
|
||||
u16 intr_val, intr_data;
|
||||
|
||||
if (go->boot_fw == NULL) {
|
||||
|
@ -2127,8 +2116,8 @@ upstream submission.
|
|||
if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
|
||||
v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name);
|
||||
release_firmware(fw_entry);
|
||||
--- a/drivers/staging/media/go7007/go7007-fw.c
|
||||
+++ b/drivers/staging/media/go7007/go7007-fw.c
|
||||
--- a/drivers/media/usb/go7007/go7007-fw.c
|
||||
+++ b/drivers/media/usb/go7007/go7007-fw.c
|
||||
@@ -1570,12 +1570,8 @@ int go7007_construct_fw_image(struct go7
|
||||
default:
|
||||
return -1;
|
||||
|
@ -2143,9 +2132,9 @@ upstream submission.
|
|||
code = kzalloc(codespace * 2, GFP_KERNEL);
|
||||
if (code == NULL)
|
||||
goto fw_failed;
|
||||
--- a/drivers/staging/media/go7007/go7007-loader.c
|
||||
+++ b/drivers/staging/media/go7007/go7007-loader.c
|
||||
@@ -79,11 +79,8 @@ static int go7007_loader_probe(struct us
|
||||
--- a/drivers/media/usb/go7007/go7007-loader.c
|
||||
+++ b/drivers/media/usb/go7007/go7007-loader.c
|
||||
@@ -75,11 +75,8 @@ static int go7007_loader_probe(struct us
|
||||
|
||||
dev_info(&interface->dev, "loading firmware %s\n", fw1);
|
||||
|
||||
|
@ -2158,7 +2147,7 @@ upstream submission.
|
|||
ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
|
||||
release_firmware(fw);
|
||||
if (0 != ret) {
|
||||
@@ -94,11 +91,8 @@ static int go7007_loader_probe(struct us
|
||||
@@ -90,11 +87,8 @@ static int go7007_loader_probe(struct us
|
||||
if (fw2 == NULL)
|
||||
return 0;
|
||||
|
||||
|
@ -2203,12 +2192,12 @@ upstream submission.
|
|||
struct usb_device *udev = padapter->dvobjpriv.pusbdev;
|
||||
struct usb_interface *pusb_intf = padapter->pusb_intf;
|
||||
- dev_err(&udev->dev, "r8712u: Firmware request failed\n");
|
||||
padapter->fw_found = false;
|
||||
usb_put_dev(udev);
|
||||
usb_set_intfdata(pusb_intf, NULL);
|
||||
return;
|
||||
--- a/drivers/staging/slicoss/slicoss.c
|
||||
+++ b/drivers/staging/slicoss/slicoss.c
|
||||
@@ -402,11 +402,8 @@ static int slic_card_download_gbrcv(stru
|
||||
@@ -393,11 +393,8 @@ static int slic_card_download_gbrcv(stru
|
||||
}
|
||||
|
||||
ret = request_firmware(&fw, file, &adapter->pcidev->dev);
|
||||
|
@ -2221,7 +2210,7 @@ upstream submission.
|
|||
|
||||
rcvucodelen = *(u32 *)(fw->data + index);
|
||||
index += 4;
|
||||
@@ -480,11 +477,8 @@ static int slic_card_download(struct ada
|
||||
@@ -471,11 +468,8 @@ static int slic_card_download(struct ada
|
||||
return -ENOENT;
|
||||
}
|
||||
ret = request_firmware(&fw, file, &adapter->pcidev->dev);
|
||||
|
@ -2236,8 +2225,8 @@ upstream submission.
|
|||
for (i = 0; i < numsects; i++) {
|
||||
--- a/drivers/staging/vt6656/firmware.c
|
||||
+++ b/drivers/staging/vt6656/firmware.c
|
||||
@@ -57,11 +57,8 @@ int FIRMWAREbDownload(struct vnt_private
|
||||
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Download firmware\n");
|
||||
@@ -53,11 +53,8 @@ int vnt_download_firmware(struct vnt_pri
|
||||
dev_dbg(dev, "---->Download firmware\n");
|
||||
|
||||
rc = request_firmware(&fw, FIRMWARE_NAME, dev);
|
||||
- if (rc) {
|
||||
|
@ -2248,8 +2237,8 @@ upstream submission.
|
|||
+ if (rc)
|
||||
+ goto out;
|
||||
|
||||
pBuffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
|
||||
if (!pBuffer)
|
||||
buffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
|
||||
if (!buffer)
|
||||
--- a/drivers/tty/cyclades.c
|
||||
+++ b/drivers/tty/cyclades.c
|
||||
@@ -3522,10 +3522,8 @@ static int cyz_load_fw(struct pci_dev *p
|
||||
|
@ -2309,7 +2298,7 @@ upstream submission.
|
|||
}
|
||||
--- a/drivers/tty/serial/ucc_uart.c
|
||||
+++ b/drivers/tty/serial/ucc_uart.c
|
||||
@@ -1178,10 +1178,8 @@ static void uart_firmware_cont(const str
|
||||
@@ -1167,10 +1167,8 @@ static void uart_firmware_cont(const str
|
||||
struct device *dev = context;
|
||||
int ret;
|
||||
|
||||
|
@ -2657,7 +2646,7 @@ upstream submission.
|
|||
filename, emu->firmware->size);
|
||||
--- a/sound/pci/hda/hda_intel.c
|
||||
+++ b/sound/pci/hda/hda_intel.c
|
||||
@@ -1407,10 +1407,8 @@ static void azx_firmware_cb(const struct
|
||||
@@ -1644,10 +1644,8 @@ static void azx_firmware_cb(const struct
|
||||
struct azx *chip = card->private_data;
|
||||
struct pci_dev *pci = chip->pci;
|
||||
|
||||
|
@ -2742,7 +2731,7 @@ upstream submission.
|
|||
"too short firmware size %d (expected %d)\n",
|
||||
--- a/sound/soc/codecs/wm2000.c
|
||||
+++ b/sound/soc/codecs/wm2000.c
|
||||
@@ -891,10 +891,8 @@ static int wm2000_i2c_probe(struct i2c_c
|
||||
@@ -889,10 +889,8 @@ static int wm2000_i2c_probe(struct i2c_c
|
||||
}
|
||||
|
||||
ret = request_firmware(&fw, filename, &i2c->dev);
|
||||
|
|
|
@ -20,7 +20,7 @@ This does not cover the case where we fall back to a user-mode helper
|
|||
---
|
||||
--- a/drivers/base/firmware_class.c
|
||||
+++ b/drivers/base/firmware_class.c
|
||||
@@ -344,17 +344,20 @@ static int fw_get_filesystem_firmware(st
|
||||
@@ -340,17 +340,20 @@ static int fw_get_filesystem_firmware(st
|
||||
}
|
||||
rc = fw_read_file_contents(file, buf);
|
||||
fput(file);
|
||||
|
@ -46,7 +46,7 @@ This does not cover the case where we fall back to a user-mode helper
|
|||
mutex_lock(&fw_lock);
|
||||
set_bit(FW_STATUS_DONE, &buf->status);
|
||||
complete_all(&buf->completion);
|
||||
@@ -1007,7 +1010,8 @@ _request_firmware_prepare(struct firmwar
|
||||
@@ -1026,7 +1029,8 @@ _request_firmware_prepare(struct firmwar
|
||||
}
|
||||
|
||||
if (fw_get_builtin_firmware(firmware, name)) {
|
||||
|
@ -56,7 +56,7 @@ This does not cover the case where we fall back to a user-mode helper
|
|||
return 0; /* assigned */
|
||||
}
|
||||
|
||||
@@ -1090,7 +1094,7 @@ _request_firmware(const struct firmware
|
||||
@@ -1109,7 +1113,7 @@ _request_firmware(const struct firmware
|
||||
if (opt_flags & FW_OPT_NOWAIT) {
|
||||
timeout = usermodehelper_read_lock_wait(timeout);
|
||||
if (!timeout) {
|
||||
|
|
|
@ -17,46 +17,25 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
---
|
||||
--- a/drivers/base/firmware_class.c
|
||||
+++ b/drivers/base/firmware_class.c
|
||||
@@ -283,12 +283,15 @@ MODULE_PARM_DESC(path, "customized firmw
|
||||
static noinline_for_stack int fw_file_size(struct file *file)
|
||||
{
|
||||
struct kstat st;
|
||||
- if (vfs_getattr(&file->f_path, &st))
|
||||
- return -1;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = vfs_getattr(&file->f_path, &st);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
if (!S_ISREG(st.mode))
|
||||
- return -1;
|
||||
+ return -ENOTTY;
|
||||
if (st.size != (int)st.size)
|
||||
- return -1;
|
||||
+ return -EFBIG;
|
||||
return st.size;
|
||||
}
|
||||
|
||||
@@ -299,14 +302,16 @@ static int fw_read_file_contents(struct
|
||||
@@ -293,7 +293,7 @@ static int fw_read_file_contents(struct
|
||||
int rc;
|
||||
|
||||
size = fw_file_size(file);
|
||||
- if (size <= 0)
|
||||
+ if (size < 0)
|
||||
+ return size;
|
||||
+ if (size == 0)
|
||||
if (!S_ISREG(file_inode(file)->i_mode))
|
||||
- return -EINVAL;
|
||||
+ return -ENOTTY;
|
||||
size = i_size_read(file_inode(file));
|
||||
if (size <= 0)
|
||||
return -EINVAL;
|
||||
buf = vmalloc(size);
|
||||
if (!buf)
|
||||
@@ -302,7 +302,7 @@ static int fw_read_file_contents(struct
|
||||
return -ENOMEM;
|
||||
rc = kernel_read(file, 0, buf, size);
|
||||
if (rc != size) {
|
||||
- if (rc > 0)
|
||||
+ if (rc >= 0)
|
||||
rc = -EIO;
|
||||
vfree(buf);
|
||||
return rc;
|
||||
@@ -333,8 +338,10 @@ static int fw_get_filesystem_firmware(st
|
||||
goto fail;
|
||||
}
|
||||
@@ -334,8 +334,10 @@ static int fw_get_filesystem_firmware(st
|
||||
snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);
|
||||
|
||||
file = filp_open(path, O_RDONLY, 0);
|
||||
|
@ -68,7 +47,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
rc = fw_read_file_contents(file, buf);
|
||||
fput(file);
|
||||
if (rc)
|
||||
@@ -950,13 +957,6 @@ static void kill_requests_without_uevent
|
||||
@@ -974,13 +976,6 @@ static void kill_requests_without_uevent
|
||||
#endif
|
||||
|
||||
#else /* CONFIG_FW_LOADER_USER_HELPER */
|
||||
|
@ -82,15 +61,15 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
|
||||
/* No abort during direct loading */
|
||||
#define is_fw_load_aborted(buf) false
|
||||
@@ -1105,6 +1105,7 @@ _request_firmware(const struct firmware
|
||||
@@ -1129,6 +1124,7 @@ _request_firmware(const struct firmware
|
||||
}
|
||||
|
||||
ret = fw_get_filesystem_firmware(device, fw->priv);
|
||||
+#ifdef CONFIG_FW_LOADER_USER_HELPER
|
||||
if (ret) {
|
||||
if (opt_flags & FW_OPT_FALLBACK) {
|
||||
if (!(opt_flags & FW_OPT_NO_WARN))
|
||||
dev_warn(device,
|
||||
@@ -1115,6 +1116,7 @@ _request_firmware(const struct firmware
|
||||
@@ -1140,6 +1136,7 @@ _request_firmware(const struct firmware
|
||||
opt_flags, timeout);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ the kernel.
|
|||
|
||||
--- a/scripts/Kbuild.include
|
||||
+++ b/scripts/Kbuild.include
|
||||
@@ -110,12 +110,12 @@ as-instr = $(call try-run,\
|
||||
@@ -111,12 +111,12 @@ as-instr = $(call try-run,\
|
||||
# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
|
||||
|
||||
cc-option = $(call try-run,\
|
||||
|
@ -30,7 +30,7 @@ the kernel.
|
|||
|
||||
# cc-option-align
|
||||
# Prefix align with either -falign or -malign
|
||||
@@ -125,16 +125,17 @@ cc-option-align = $(subst -functions=0,,
|
||||
@@ -126,16 +126,17 @@ cc-option-align = $(subst -functions=0,,
|
||||
# cc-disable-warning
|
||||
# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
|
||||
cc-disable-warning = $(call try-run,\
|
||||
|
@ -51,7 +51,7 @@ the kernel.
|
|||
|
||||
# cc-ifversion
|
||||
# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
|
||||
@@ -148,7 +149,7 @@ cc-ldoption = $(call try-run,\
|
||||
@@ -149,7 +150,7 @@ cc-ldoption = $(call try-run,\
|
||||
# ld-option
|
||||
# Usage: LDFLAGS += $(call ld-option, -X)
|
||||
ld-option = $(call try-run,\
|
||||
|
@ -62,16 +62,16 @@ the kernel.
|
|||
# Usage: KBUILD_ARFLAGS := $(call ar-option,D)
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -578,6 +578,8 @@ else
|
||||
@@ -624,6 +624,8 @@ else
|
||||
KBUILD_CFLAGS += -O2
|
||||
endif
|
||||
|
||||
+NOSTDINC_FLAGS += -nostdinc
|
||||
+
|
||||
ifdef CONFIG_READABLE_ASM
|
||||
# Disable optimizations that make assembler listings hard to read.
|
||||
# reorder blocks reorders the control in the function
|
||||
@@ -646,7 +648,7 @@ KBUILD_CFLAGS += $(call cc-option, -fno-
|
||||
# Tell gcc to never replace conditional load with a non-conditional one
|
||||
KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0)
|
||||
|
||||
@@ -750,7 +752,7 @@ KBUILD_CFLAGS += $(call cc-option, -fno-
|
||||
endif
|
||||
|
||||
# arch Makefile may override CC so keep this after arch Makefile is included
|
||||
|
|
|
@ -1,275 +0,0 @@
|
|||
From: Ilya Dryomov <ilya.dryomov@inktank.com>
|
||||
Date: Mon, 8 Sep 2014 17:25:34 +0400
|
||||
Subject: libceph: add process_one_ticket() helper
|
||||
Origin: https://git.kernel.org/linus/597cda357716a3cf8d994cb11927af917c8d71fa
|
||||
|
||||
Add a helper for processing individual cephx auth tickets. Needed for
|
||||
the next commit, which deals with allocating ticket buffers. (Most of
|
||||
the diff here is whitespace - view with git diff -b).
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
|
||||
Reviewed-by: Sage Weil <sage@redhat.com>
|
||||
---
|
||||
net/ceph/auth_x.c | 228 +++++++++++++++++++++++++++++-------------------------
|
||||
1 file changed, 124 insertions(+), 104 deletions(-)
|
||||
|
||||
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c
|
||||
index 96238ba..0eb146d 100644
|
||||
--- a/net/ceph/auth_x.c
|
||||
+++ b/net/ceph/auth_x.c
|
||||
@@ -129,17 +129,131 @@ static void remove_ticket_handler(struct ceph_auth_client *ac,
|
||||
kfree(th);
|
||||
}
|
||||
|
||||
+static int process_one_ticket(struct ceph_auth_client *ac,
|
||||
+ struct ceph_crypto_key *secret,
|
||||
+ void **p, void *end,
|
||||
+ void *dbuf, void *ticket_buf)
|
||||
+{
|
||||
+ struct ceph_x_info *xi = ac->private;
|
||||
+ int type;
|
||||
+ u8 tkt_struct_v, blob_struct_v;
|
||||
+ struct ceph_x_ticket_handler *th;
|
||||
+ void *dp, *dend;
|
||||
+ int dlen;
|
||||
+ char is_enc;
|
||||
+ struct timespec validity;
|
||||
+ struct ceph_crypto_key old_key;
|
||||
+ void *tp, *tpend;
|
||||
+ struct ceph_timespec new_validity;
|
||||
+ struct ceph_crypto_key new_session_key;
|
||||
+ struct ceph_buffer *new_ticket_blob;
|
||||
+ unsigned long new_expires, new_renew_after;
|
||||
+ u64 new_secret_id;
|
||||
+ int ret;
|
||||
+
|
||||
+ ceph_decode_need(p, end, sizeof(u32) + 1, bad);
|
||||
+
|
||||
+ type = ceph_decode_32(p);
|
||||
+ dout(" ticket type %d %s\n", type, ceph_entity_type_name(type));
|
||||
+
|
||||
+ tkt_struct_v = ceph_decode_8(p);
|
||||
+ if (tkt_struct_v != 1)
|
||||
+ goto bad;
|
||||
+
|
||||
+ th = get_ticket_handler(ac, type);
|
||||
+ if (IS_ERR(th)) {
|
||||
+ ret = PTR_ERR(th);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* blob for me */
|
||||
+ dlen = ceph_x_decrypt(secret, p, end, dbuf,
|
||||
+ TEMP_TICKET_BUF_LEN);
|
||||
+ if (dlen <= 0) {
|
||||
+ ret = dlen;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ dout(" decrypted %d bytes\n", dlen);
|
||||
+ dp = dbuf;
|
||||
+ dend = dp + dlen;
|
||||
+
|
||||
+ tkt_struct_v = ceph_decode_8(&dp);
|
||||
+ if (tkt_struct_v != 1)
|
||||
+ goto bad;
|
||||
+
|
||||
+ memcpy(&old_key, &th->session_key, sizeof(old_key));
|
||||
+ ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+
|
||||
+ ceph_decode_copy(&dp, &new_validity, sizeof(new_validity));
|
||||
+ ceph_decode_timespec(&validity, &new_validity);
|
||||
+ new_expires = get_seconds() + validity.tv_sec;
|
||||
+ new_renew_after = new_expires - (validity.tv_sec / 4);
|
||||
+ dout(" expires=%lu renew_after=%lu\n", new_expires,
|
||||
+ new_renew_after);
|
||||
+
|
||||
+ /* ticket blob for service */
|
||||
+ ceph_decode_8_safe(p, end, is_enc, bad);
|
||||
+ tp = ticket_buf;
|
||||
+ if (is_enc) {
|
||||
+ /* encrypted */
|
||||
+ dout(" encrypted ticket\n");
|
||||
+ dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf,
|
||||
+ TEMP_TICKET_BUF_LEN);
|
||||
+ if (dlen < 0) {
|
||||
+ ret = dlen;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ dlen = ceph_decode_32(&tp);
|
||||
+ } else {
|
||||
+ /* unencrypted */
|
||||
+ ceph_decode_32_safe(p, end, dlen, bad);
|
||||
+ ceph_decode_need(p, end, dlen, bad);
|
||||
+ ceph_decode_copy(p, ticket_buf, dlen);
|
||||
+ }
|
||||
+ tpend = tp + dlen;
|
||||
+ dout(" ticket blob is %d bytes\n", dlen);
|
||||
+ ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
|
||||
+ blob_struct_v = ceph_decode_8(&tp);
|
||||
+ new_secret_id = ceph_decode_64(&tp);
|
||||
+ ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+
|
||||
+ /* all is well, update our ticket */
|
||||
+ ceph_crypto_key_destroy(&th->session_key);
|
||||
+ if (th->ticket_blob)
|
||||
+ ceph_buffer_put(th->ticket_blob);
|
||||
+ th->session_key = new_session_key;
|
||||
+ th->ticket_blob = new_ticket_blob;
|
||||
+ th->validity = new_validity;
|
||||
+ th->secret_id = new_secret_id;
|
||||
+ th->expires = new_expires;
|
||||
+ th->renew_after = new_renew_after;
|
||||
+ dout(" got ticket service %d (%s) secret_id %lld len %d\n",
|
||||
+ type, ceph_entity_type_name(type), th->secret_id,
|
||||
+ (int)th->ticket_blob->vec.iov_len);
|
||||
+ xi->have_keys |= th->service;
|
||||
+
|
||||
+out:
|
||||
+ return ret;
|
||||
+
|
||||
+bad:
|
||||
+ ret = -EINVAL;
|
||||
+ goto out;
|
||||
+}
|
||||
+
|
||||
static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
|
||||
struct ceph_crypto_key *secret,
|
||||
void *buf, void *end)
|
||||
{
|
||||
- struct ceph_x_info *xi = ac->private;
|
||||
- int num;
|
||||
void *p = buf;
|
||||
- int ret;
|
||||
char *dbuf;
|
||||
char *ticket_buf;
|
||||
u8 reply_struct_v;
|
||||
+ u32 num;
|
||||
+ int ret;
|
||||
|
||||
dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
|
||||
if (!dbuf)
|
||||
@@ -150,112 +264,18 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
|
||||
if (!ticket_buf)
|
||||
goto out_dbuf;
|
||||
|
||||
- ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
|
||||
- reply_struct_v = ceph_decode_8(&p);
|
||||
+ ceph_decode_8_safe(&p, end, reply_struct_v, bad);
|
||||
if (reply_struct_v != 1)
|
||||
- goto bad;
|
||||
- num = ceph_decode_32(&p);
|
||||
- dout("%d tickets\n", num);
|
||||
- while (num--) {
|
||||
- int type;
|
||||
- u8 tkt_struct_v, blob_struct_v;
|
||||
- struct ceph_x_ticket_handler *th;
|
||||
- void *dp, *dend;
|
||||
- int dlen;
|
||||
- char is_enc;
|
||||
- struct timespec validity;
|
||||
- struct ceph_crypto_key old_key;
|
||||
- void *tp, *tpend;
|
||||
- struct ceph_timespec new_validity;
|
||||
- struct ceph_crypto_key new_session_key;
|
||||
- struct ceph_buffer *new_ticket_blob;
|
||||
- unsigned long new_expires, new_renew_after;
|
||||
- u64 new_secret_id;
|
||||
-
|
||||
- ceph_decode_need(&p, end, sizeof(u32) + 1, bad);
|
||||
-
|
||||
- type = ceph_decode_32(&p);
|
||||
- dout(" ticket type %d %s\n", type, ceph_entity_type_name(type));
|
||||
-
|
||||
- tkt_struct_v = ceph_decode_8(&p);
|
||||
- if (tkt_struct_v != 1)
|
||||
- goto bad;
|
||||
-
|
||||
- th = get_ticket_handler(ac, type);
|
||||
- if (IS_ERR(th)) {
|
||||
- ret = PTR_ERR(th);
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- /* blob for me */
|
||||
- dlen = ceph_x_decrypt(secret, &p, end, dbuf,
|
||||
- TEMP_TICKET_BUF_LEN);
|
||||
- if (dlen <= 0) {
|
||||
- ret = dlen;
|
||||
- goto out;
|
||||
- }
|
||||
- dout(" decrypted %d bytes\n", dlen);
|
||||
- dend = dbuf + dlen;
|
||||
- dp = dbuf;
|
||||
-
|
||||
- tkt_struct_v = ceph_decode_8(&dp);
|
||||
- if (tkt_struct_v != 1)
|
||||
- goto bad;
|
||||
+ return -EINVAL;
|
||||
|
||||
- memcpy(&old_key, &th->session_key, sizeof(old_key));
|
||||
- ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
|
||||
- if (ret)
|
||||
- goto out;
|
||||
+ ceph_decode_32_safe(&p, end, num, bad);
|
||||
+ dout("%d tickets\n", num);
|
||||
|
||||
- ceph_decode_copy(&dp, &new_validity, sizeof(new_validity));
|
||||
- ceph_decode_timespec(&validity, &new_validity);
|
||||
- new_expires = get_seconds() + validity.tv_sec;
|
||||
- new_renew_after = new_expires - (validity.tv_sec / 4);
|
||||
- dout(" expires=%lu renew_after=%lu\n", new_expires,
|
||||
- new_renew_after);
|
||||
-
|
||||
- /* ticket blob for service */
|
||||
- ceph_decode_8_safe(&p, end, is_enc, bad);
|
||||
- tp = ticket_buf;
|
||||
- if (is_enc) {
|
||||
- /* encrypted */
|
||||
- dout(" encrypted ticket\n");
|
||||
- dlen = ceph_x_decrypt(&old_key, &p, end, ticket_buf,
|
||||
- TEMP_TICKET_BUF_LEN);
|
||||
- if (dlen < 0) {
|
||||
- ret = dlen;
|
||||
- goto out;
|
||||
- }
|
||||
- dlen = ceph_decode_32(&tp);
|
||||
- } else {
|
||||
- /* unencrypted */
|
||||
- ceph_decode_32_safe(&p, end, dlen, bad);
|
||||
- ceph_decode_need(&p, end, dlen, bad);
|
||||
- ceph_decode_copy(&p, ticket_buf, dlen);
|
||||
- }
|
||||
- tpend = tp + dlen;
|
||||
- dout(" ticket blob is %d bytes\n", dlen);
|
||||
- ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
|
||||
- blob_struct_v = ceph_decode_8(&tp);
|
||||
- new_secret_id = ceph_decode_64(&tp);
|
||||
- ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
|
||||
+ while (num--) {
|
||||
+ ret = process_one_ticket(ac, secret, &p, end,
|
||||
+ dbuf, ticket_buf);
|
||||
if (ret)
|
||||
goto out;
|
||||
-
|
||||
- /* all is well, update our ticket */
|
||||
- ceph_crypto_key_destroy(&th->session_key);
|
||||
- if (th->ticket_blob)
|
||||
- ceph_buffer_put(th->ticket_blob);
|
||||
- th->session_key = new_session_key;
|
||||
- th->ticket_blob = new_ticket_blob;
|
||||
- th->validity = new_validity;
|
||||
- th->secret_id = new_secret_id;
|
||||
- th->expires = new_expires;
|
||||
- th->renew_after = new_renew_after;
|
||||
- dout(" got ticket service %d (%s) secret_id %lld len %d\n",
|
||||
- type, ceph_entity_type_name(type), th->secret_id,
|
||||
- (int)th->ticket_blob->vec.iov_len);
|
||||
- xi->have_keys |= th->service;
|
||||
}
|
||||
|
||||
ret = 0;
|
|
@ -1,195 +0,0 @@
|
|||
From: Ilya Dryomov <ilya.dryomov@inktank.com>
|
||||
Date: Tue, 9 Sep 2014 19:39:15 +0400
|
||||
Subject: libceph: do not hard code max auth ticket len
|
||||
Origin: https://git.kernel.org/linus/c27a3e4d667fdcad3db7b104f75659478e0c68d8
|
||||
|
||||
We hard code cephx auth ticket buffer size to 256 bytes. This isn't
|
||||
enough for any moderate setups and, in case tickets themselves are not
|
||||
encrypted, leads to buffer overflows (ceph_x_decrypt() errors out, but
|
||||
ceph_decode_copy() doesn't - it's just a memcpy() wrapper). Since the
|
||||
buffer is allocated dynamically anyway, allocated it a bit later, at
|
||||
the point where we know how much is going to be needed.
|
||||
|
||||
Fixes: http://tracker.ceph.com/issues/8979
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
|
||||
Reviewed-by: Sage Weil <sage@redhat.com>
|
||||
---
|
||||
net/ceph/auth_x.c | 64 +++++++++++++++++++++++++------------------------------
|
||||
1 file changed, 29 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c
|
||||
index 0eb146d..de6662b 100644
|
||||
--- a/net/ceph/auth_x.c
|
||||
+++ b/net/ceph/auth_x.c
|
||||
@@ -13,8 +13,6 @@
|
||||
#include "auth_x.h"
|
||||
#include "auth_x_protocol.h"
|
||||
|
||||
-#define TEMP_TICKET_BUF_LEN 256
|
||||
-
|
||||
static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);
|
||||
|
||||
static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
|
||||
@@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret,
|
||||
}
|
||||
|
||||
static int ceph_x_decrypt(struct ceph_crypto_key *secret,
|
||||
- void **p, void *end, void *obuf, size_t olen)
|
||||
+ void **p, void *end, void **obuf, size_t olen)
|
||||
{
|
||||
struct ceph_x_encrypt_header head;
|
||||
size_t head_len = sizeof(head);
|
||||
@@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_crypto_key *secret,
|
||||
return -EINVAL;
|
||||
|
||||
dout("ceph_x_decrypt len %d\n", len);
|
||||
- ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen,
|
||||
- *p, len);
|
||||
+ if (*obuf == NULL) {
|
||||
+ *obuf = kmalloc(len, GFP_NOFS);
|
||||
+ if (!*obuf)
|
||||
+ return -ENOMEM;
|
||||
+ olen = len;
|
||||
+ }
|
||||
+
|
||||
+ ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
|
||||
@@ -131,18 +135,19 @@ static void remove_ticket_handler(struct ceph_auth_client *ac,
|
||||
|
||||
static int process_one_ticket(struct ceph_auth_client *ac,
|
||||
struct ceph_crypto_key *secret,
|
||||
- void **p, void *end,
|
||||
- void *dbuf, void *ticket_buf)
|
||||
+ void **p, void *end)
|
||||
{
|
||||
struct ceph_x_info *xi = ac->private;
|
||||
int type;
|
||||
u8 tkt_struct_v, blob_struct_v;
|
||||
struct ceph_x_ticket_handler *th;
|
||||
+ void *dbuf = NULL;
|
||||
void *dp, *dend;
|
||||
int dlen;
|
||||
char is_enc;
|
||||
struct timespec validity;
|
||||
struct ceph_crypto_key old_key;
|
||||
+ void *ticket_buf = NULL;
|
||||
void *tp, *tpend;
|
||||
struct ceph_timespec new_validity;
|
||||
struct ceph_crypto_key new_session_key;
|
||||
@@ -167,8 +172,7 @@ static int process_one_ticket(struct ceph_auth_client *ac,
|
||||
}
|
||||
|
||||
/* blob for me */
|
||||
- dlen = ceph_x_decrypt(secret, p, end, dbuf,
|
||||
- TEMP_TICKET_BUF_LEN);
|
||||
+ dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0);
|
||||
if (dlen <= 0) {
|
||||
ret = dlen;
|
||||
goto out;
|
||||
@@ -195,20 +199,25 @@ static int process_one_ticket(struct ceph_auth_client *ac,
|
||||
|
||||
/* ticket blob for service */
|
||||
ceph_decode_8_safe(p, end, is_enc, bad);
|
||||
- tp = ticket_buf;
|
||||
if (is_enc) {
|
||||
/* encrypted */
|
||||
dout(" encrypted ticket\n");
|
||||
- dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf,
|
||||
- TEMP_TICKET_BUF_LEN);
|
||||
+ dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0);
|
||||
if (dlen < 0) {
|
||||
ret = dlen;
|
||||
goto out;
|
||||
}
|
||||
+ tp = ticket_buf;
|
||||
dlen = ceph_decode_32(&tp);
|
||||
} else {
|
||||
/* unencrypted */
|
||||
ceph_decode_32_safe(p, end, dlen, bad);
|
||||
+ ticket_buf = kmalloc(dlen, GFP_NOFS);
|
||||
+ if (!ticket_buf) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ tp = ticket_buf;
|
||||
ceph_decode_need(p, end, dlen, bad);
|
||||
ceph_decode_copy(p, ticket_buf, dlen);
|
||||
}
|
||||
@@ -237,6 +246,8 @@ static int process_one_ticket(struct ceph_auth_client *ac,
|
||||
xi->have_keys |= th->service;
|
||||
|
||||
out:
|
||||
+ kfree(ticket_buf);
|
||||
+ kfree(dbuf);
|
||||
return ret;
|
||||
|
||||
bad:
|
||||
@@ -249,21 +260,10 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
|
||||
void *buf, void *end)
|
||||
{
|
||||
void *p = buf;
|
||||
- char *dbuf;
|
||||
- char *ticket_buf;
|
||||
u8 reply_struct_v;
|
||||
u32 num;
|
||||
int ret;
|
||||
|
||||
- dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
|
||||
- if (!dbuf)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- ret = -ENOMEM;
|
||||
- ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
|
||||
- if (!ticket_buf)
|
||||
- goto out_dbuf;
|
||||
-
|
||||
ceph_decode_8_safe(&p, end, reply_struct_v, bad);
|
||||
if (reply_struct_v != 1)
|
||||
return -EINVAL;
|
||||
@@ -272,22 +272,15 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
|
||||
dout("%d tickets\n", num);
|
||||
|
||||
while (num--) {
|
||||
- ret = process_one_ticket(ac, secret, &p, end,
|
||||
- dbuf, ticket_buf);
|
||||
+ ret = process_one_ticket(ac, secret, &p, end);
|
||||
if (ret)
|
||||
- goto out;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
- ret = 0;
|
||||
-out:
|
||||
- kfree(ticket_buf);
|
||||
-out_dbuf:
|
||||
- kfree(dbuf);
|
||||
- return ret;
|
||||
+ return 0;
|
||||
|
||||
bad:
|
||||
- ret = -EINVAL;
|
||||
- goto out;
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
|
||||
@@ -603,13 +596,14 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
|
||||
struct ceph_x_ticket_handler *th;
|
||||
int ret = 0;
|
||||
struct ceph_x_authorize_reply reply;
|
||||
+ void *preply = &reply;
|
||||
void *p = au->reply_buf;
|
||||
void *end = p + sizeof(au->reply_buf);
|
||||
|
||||
th = get_ticket_handler(ac, au->service);
|
||||
if (IS_ERR(th))
|
||||
return PTR_ERR(th);
|
||||
- ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply));
|
||||
+ ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret != sizeof(reply))
|
|
@ -1,36 +0,0 @@
|
|||
From: Sage Weil <sage@redhat.com>
|
||||
Date: Mon, 4 Aug 2014 07:01:54 -0700
|
||||
Subject: libceph: gracefully handle large reply messages from the mon
|
||||
Origin: https://git.kernel.org/linus/73c3d4812b4c755efeca0140f606f83772a39ce4
|
||||
|
||||
We preallocate a few of the message types we get back from the mon. If we
|
||||
get a larger message than we are expecting, fall back to trying to allocate
|
||||
a new one instead of blindly using the one we have.
|
||||
|
||||
CC: stable@vger.kernel.org
|
||||
Signed-off-by: Sage Weil <sage@redhat.com>
|
||||
Reviewed-by: Ilya Dryomov <ilya.dryomov@inktank.com>
|
||||
---
|
||||
net/ceph/mon_client.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c
|
||||
index 067d3af..61fcfc3 100644
|
||||
--- a/net/ceph/mon_client.c
|
||||
+++ b/net/ceph/mon_client.c
|
||||
@@ -1181,7 +1181,15 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con,
|
||||
if (!m) {
|
||||
pr_info("alloc_msg unknown type %d\n", type);
|
||||
*skip = 1;
|
||||
+ } else if (front_len > m->front_alloc_len) {
|
||||
+ pr_warning("mon_alloc_msg front %d > prealloc %d (%u#%llu)\n",
|
||||
+ front_len, m->front_alloc_len,
|
||||
+ (unsigned int)con->peer_name.type,
|
||||
+ le64_to_cpu(con->peer_name.num));
|
||||
+ ceph_msg_put(m);
|
||||
+ m = ceph_msg_new(type, front_len, GFP_NOFS, false);
|
||||
}
|
||||
+
|
||||
return m;
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
From: Ilya Dryomov <ilya.dryomov@inktank.com>
|
||||
Date: Fri, 8 Aug 2014 12:43:39 +0400
|
||||
Subject: libceph: set last_piece in ceph_msg_data_pages_cursor_init()
|
||||
correctly
|
||||
Origin: https://git.kernel.org/linus/5f740d7e1531099b888410e6bab13f68da9b1a4d
|
||||
|
||||
Determining ->last_piece based on the value of ->page_offset + length
|
||||
is incorrect because length here is the length of the entire message.
|
||||
->last_piece set to false even if page array data item length is <=
|
||||
PAGE_SIZE, which results in invalid length passed to
|
||||
ceph_tcp_{send,recv}page() and causes various asserts to fire.
|
||||
|
||||
# cat pages-cursor-init.sh
|
||||
#!/bin/bash
|
||||
rbd create --size 10 --image-format 2 foo
|
||||
FOO_DEV=$(rbd map foo)
|
||||
dd if=/dev/urandom of=$FOO_DEV bs=1M &>/dev/null
|
||||
rbd snap create foo@snap
|
||||
rbd snap protect foo@snap
|
||||
rbd clone foo@snap bar
|
||||
# rbd_resize calls librbd rbd_resize(), size is in bytes
|
||||
./rbd_resize bar $(((4 << 20) + 512))
|
||||
rbd resize --size 10 bar
|
||||
BAR_DEV=$(rbd map bar)
|
||||
# trigger a 512-byte copyup -- 512-byte page array data item
|
||||
dd if=/dev/urandom of=$BAR_DEV bs=1M count=1 seek=5
|
||||
|
||||
The problem exists only in ceph_msg_data_pages_cursor_init(),
|
||||
ceph_msg_data_pages_advance() does the right thing. The size_t cast is
|
||||
unnecessary.
|
||||
|
||||
Cc: stable@vger.kernel.org # 3.10+
|
||||
Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
|
||||
Reviewed-by: Sage Weil <sage@redhat.com>
|
||||
Reviewed-by: Alex Elder <elder@linaro.org>
|
||||
---
|
||||
net/ceph/messenger.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/net/ceph/messenger.c
|
||||
+++ b/net/ceph/messenger.c
|
||||
@@ -900,7 +900,7 @@ static void ceph_msg_data_pages_cursor_i
|
||||
BUG_ON(page_count > (int)USHRT_MAX);
|
||||
cursor->page_count = (unsigned short)page_count;
|
||||
BUG_ON(length > SIZE_MAX - cursor->page_offset);
|
||||
- cursor->last_piece = (size_t)cursor->page_offset + length <= PAGE_SIZE;
|
||||
+ cursor->last_piece = cursor->page_offset + cursor->resid <= PAGE_SIZE;
|
||||
}
|
||||
|
||||
static struct page *
|
|
@ -1,315 +0,0 @@
|
|||
From: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||
Date: Tue, 29 Jul 2014 15:50:44 -0700
|
||||
Subject: [5/5] mnt: Add tests for unprivileged remount cases that have found
|
||||
to be faulty
|
||||
Origin: https://git.kernel.org/linus/db181ce011e3c033328608299cd6fac06ea50130
|
||||
|
||||
Kenton Varda <kenton@sandstorm.io> discovered that by remounting a
|
||||
read-only bind mount read-only in a user namespace the
|
||||
MNT_LOCK_READONLY bit would be cleared, allowing an unprivileged user
|
||||
to the remount a read-only mount read-write.
|
||||
|
||||
Upon review of the code in remount it was discovered that the code allowed
|
||||
nosuid, noexec, and nodev to be cleared. It was also discovered that
|
||||
the code was allowing the per mount atime flags to be changed.
|
||||
|
||||
The first naive patch to fix these issues contained the flaw that using
|
||||
default atime settings when remounting a filesystem could be disallowed.
|
||||
|
||||
To avoid this problems in the future add tests to ensure unprivileged
|
||||
remounts are succeeding and failing at the appropriate times.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
|
||||
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||
---
|
||||
tools/testing/selftests/Makefile | 1 +
|
||||
tools/testing/selftests/mount/Makefile | 17 ++
|
||||
.../selftests/mount/unprivileged-remount-test.c | 242 +++++++++++++++++++++
|
||||
3 files changed, 260 insertions(+)
|
||||
create mode 100644 tools/testing/selftests/mount/Makefile
|
||||
create mode 100644 tools/testing/selftests/mount/unprivileged-remount-test.c
|
||||
|
||||
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
|
||||
index e66e710..0a8a9db 100644
|
||||
--- a/tools/testing/selftests/Makefile
|
||||
+++ b/tools/testing/selftests/Makefile
|
||||
@@ -4,6 +4,7 @@ TARGETS += efivarfs
|
||||
TARGETS += kcmp
|
||||
TARGETS += memory-hotplug
|
||||
TARGETS += mqueue
|
||||
+TARGETS += mount
|
||||
TARGETS += net
|
||||
TARGETS += ptrace
|
||||
TARGETS += timers
|
||||
diff --git a/tools/testing/selftests/mount/Makefile b/tools/testing/selftests/mount/Makefile
|
||||
new file mode 100644
|
||||
index 0000000..337d853
|
||||
--- /dev/null
|
||||
+++ b/tools/testing/selftests/mount/Makefile
|
||||
@@ -0,0 +1,17 @@
|
||||
+# Makefile for mount selftests.
|
||||
+
|
||||
+all: unprivileged-remount-test
|
||||
+
|
||||
+unprivileged-remount-test: unprivileged-remount-test.c
|
||||
+ gcc -Wall -O2 unprivileged-remount-test.c -o unprivileged-remount-test
|
||||
+
|
||||
+# Allow specific tests to be selected.
|
||||
+test_unprivileged_remount: unprivileged-remount-test
|
||||
+ @if [ -f /proc/self/uid_map ] ; then ./unprivileged-remount-test ; fi
|
||||
+
|
||||
+run_tests: all test_unprivileged_remount
|
||||
+
|
||||
+clean:
|
||||
+ rm -f unprivileged-remount-test
|
||||
+
|
||||
+.PHONY: all test_unprivileged_remount
|
||||
diff --git a/tools/testing/selftests/mount/unprivileged-remount-test.c b/tools/testing/selftests/mount/unprivileged-remount-test.c
|
||||
new file mode 100644
|
||||
index 0000000..1b3ff2f
|
||||
--- /dev/null
|
||||
+++ b/tools/testing/selftests/mount/unprivileged-remount-test.c
|
||||
@@ -0,0 +1,242 @@
|
||||
+#define _GNU_SOURCE
|
||||
+#include <sched.h>
|
||||
+#include <stdio.h>
|
||||
+#include <errno.h>
|
||||
+#include <string.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/mount.h>
|
||||
+#include <sys/wait.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <unistd.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <grp.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdarg.h>
|
||||
+
|
||||
+#ifndef CLONE_NEWNS
|
||||
+# define CLONE_NEWNS 0x00020000
|
||||
+#endif
|
||||
+#ifndef CLONE_NEWUTS
|
||||
+# define CLONE_NEWUTS 0x04000000
|
||||
+#endif
|
||||
+#ifndef CLONE_NEWIPC
|
||||
+# define CLONE_NEWIPC 0x08000000
|
||||
+#endif
|
||||
+#ifndef CLONE_NEWNET
|
||||
+# define CLONE_NEWNET 0x40000000
|
||||
+#endif
|
||||
+#ifndef CLONE_NEWUSER
|
||||
+# define CLONE_NEWUSER 0x10000000
|
||||
+#endif
|
||||
+#ifndef CLONE_NEWPID
|
||||
+# define CLONE_NEWPID 0x20000000
|
||||
+#endif
|
||||
+
|
||||
+#ifndef MS_RELATIME
|
||||
+#define MS_RELATIME (1 << 21)
|
||||
+#endif
|
||||
+#ifndef MS_STRICTATIME
|
||||
+#define MS_STRICTATIME (1 << 24)
|
||||
+#endif
|
||||
+
|
||||
+static void die(char *fmt, ...)
|
||||
+{
|
||||
+ va_list ap;
|
||||
+ va_start(ap, fmt);
|
||||
+ vfprintf(stderr, fmt, ap);
|
||||
+ va_end(ap);
|
||||
+ exit(EXIT_FAILURE);
|
||||
+}
|
||||
+
|
||||
+static void write_file(char *filename, char *fmt, ...)
|
||||
+{
|
||||
+ char buf[4096];
|
||||
+ int fd;
|
||||
+ ssize_t written;
|
||||
+ int buf_len;
|
||||
+ va_list ap;
|
||||
+
|
||||
+ va_start(ap, fmt);
|
||||
+ buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
+ va_end(ap);
|
||||
+ if (buf_len < 0) {
|
||||
+ die("vsnprintf failed: %s\n",
|
||||
+ strerror(errno));
|
||||
+ }
|
||||
+ if (buf_len >= sizeof(buf)) {
|
||||
+ die("vsnprintf output truncated\n");
|
||||
+ }
|
||||
+
|
||||
+ fd = open(filename, O_WRONLY);
|
||||
+ if (fd < 0) {
|
||||
+ die("open of %s failed: %s\n",
|
||||
+ filename, strerror(errno));
|
||||
+ }
|
||||
+ written = write(fd, buf, buf_len);
|
||||
+ if (written != buf_len) {
|
||||
+ if (written >= 0) {
|
||||
+ die("short write to %s\n", filename);
|
||||
+ } else {
|
||||
+ die("write to %s failed: %s\n",
|
||||
+ filename, strerror(errno));
|
||||
+ }
|
||||
+ }
|
||||
+ if (close(fd) != 0) {
|
||||
+ die("close of %s failed: %s\n",
|
||||
+ filename, strerror(errno));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void create_and_enter_userns(void)
|
||||
+{
|
||||
+ uid_t uid;
|
||||
+ gid_t gid;
|
||||
+
|
||||
+ uid = getuid();
|
||||
+ gid = getgid();
|
||||
+
|
||||
+ if (unshare(CLONE_NEWUSER) !=0) {
|
||||
+ die("unshare(CLONE_NEWUSER) failed: %s\n",
|
||||
+ strerror(errno));
|
||||
+ }
|
||||
+
|
||||
+ write_file("/proc/self/uid_map", "0 %d 1", uid);
|
||||
+ write_file("/proc/self/gid_map", "0 %d 1", gid);
|
||||
+
|
||||
+ if (setgroups(0, NULL) != 0) {
|
||||
+ die("setgroups failed: %s\n",
|
||||
+ strerror(errno));
|
||||
+ }
|
||||
+ if (setgid(0) != 0) {
|
||||
+ die ("setgid(0) failed %s\n",
|
||||
+ strerror(errno));
|
||||
+ }
|
||||
+ if (setuid(0) != 0) {
|
||||
+ die("setuid(0) failed %s\n",
|
||||
+ strerror(errno));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static
|
||||
+bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags)
|
||||
+{
|
||||
+ pid_t child;
|
||||
+
|
||||
+ child = fork();
|
||||
+ if (child == -1) {
|
||||
+ die("fork failed: %s\n",
|
||||
+ strerror(errno));
|
||||
+ }
|
||||
+ if (child != 0) { /* parent */
|
||||
+ pid_t pid;
|
||||
+ int status;
|
||||
+ pid = waitpid(child, &status, 0);
|
||||
+ if (pid == -1) {
|
||||
+ die("waitpid failed: %s\n",
|
||||
+ strerror(errno));
|
||||
+ }
|
||||
+ if (pid != child) {
|
||||
+ die("waited for %d got %d\n",
|
||||
+ child, pid);
|
||||
+ }
|
||||
+ if (!WIFEXITED(status)) {
|
||||
+ die("child did not terminate cleanly\n");
|
||||
+ }
|
||||
+ return WEXITSTATUS(status) == EXIT_SUCCESS ? true : false;
|
||||
+ }
|
||||
+
|
||||
+ create_and_enter_userns();
|
||||
+ if (unshare(CLONE_NEWNS) != 0) {
|
||||
+ die("unshare(CLONE_NEWNS) failed: %s\n",
|
||||
+ strerror(errno));
|
||||
+ }
|
||||
+
|
||||
+ if (mount("testing", "/tmp", "ramfs", mount_flags, NULL) != 0) {
|
||||
+ die("mount of /tmp failed: %s\n",
|
||||
+ strerror(errno));
|
||||
+ }
|
||||
+
|
||||
+ create_and_enter_userns();
|
||||
+
|
||||
+ if (unshare(CLONE_NEWNS) != 0) {
|
||||
+ die("unshare(CLONE_NEWNS) failed: %s\n",
|
||||
+ strerror(errno));
|
||||
+ }
|
||||
+
|
||||
+ if (mount("/tmp", "/tmp", "none",
|
||||
+ MS_REMOUNT | MS_BIND | remount_flags, NULL) != 0) {
|
||||
+ /* system("cat /proc/self/mounts"); */
|
||||
+ die("remount of /tmp failed: %s\n",
|
||||
+ strerror(errno));
|
||||
+ }
|
||||
+
|
||||
+ if (mount("/tmp", "/tmp", "none",
|
||||
+ MS_REMOUNT | MS_BIND | invalid_flags, NULL) == 0) {
|
||||
+ /* system("cat /proc/self/mounts"); */
|
||||
+ die("remount of /tmp with invalid flags "
|
||||
+ "succeeded unexpectedly\n");
|
||||
+ }
|
||||
+ exit(EXIT_SUCCESS);
|
||||
+}
|
||||
+
|
||||
+static bool test_unpriv_remount_simple(int mount_flags)
|
||||
+{
|
||||
+ return test_unpriv_remount(mount_flags, mount_flags, 0);
|
||||
+}
|
||||
+
|
||||
+static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags)
|
||||
+{
|
||||
+ return test_unpriv_remount(mount_flags, mount_flags, invalid_flags);
|
||||
+}
|
||||
+
|
||||
+int main(int argc, char **argv)
|
||||
+{
|
||||
+ if (!test_unpriv_remount_simple(MS_RDONLY|MS_NODEV)) {
|
||||
+ die("MS_RDONLY malfunctions\n");
|
||||
+ }
|
||||
+ if (!test_unpriv_remount_simple(MS_NODEV)) {
|
||||
+ die("MS_NODEV malfunctions\n");
|
||||
+ }
|
||||
+ if (!test_unpriv_remount_simple(MS_NOSUID|MS_NODEV)) {
|
||||
+ die("MS_NOSUID malfunctions\n");
|
||||
+ }
|
||||
+ if (!test_unpriv_remount_simple(MS_NOEXEC|MS_NODEV)) {
|
||||
+ die("MS_NOEXEC malfunctions\n");
|
||||
+ }
|
||||
+ if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODEV,
|
||||
+ MS_NOATIME|MS_NODEV))
|
||||
+ {
|
||||
+ die("MS_RELATIME malfunctions\n");
|
||||
+ }
|
||||
+ if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODEV,
|
||||
+ MS_NOATIME|MS_NODEV))
|
||||
+ {
|
||||
+ die("MS_STRICTATIME malfunctions\n");
|
||||
+ }
|
||||
+ if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODEV,
|
||||
+ MS_STRICTATIME|MS_NODEV))
|
||||
+ {
|
||||
+ die("MS_RELATIME malfunctions\n");
|
||||
+ }
|
||||
+ if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME|MS_NODEV,
|
||||
+ MS_NOATIME|MS_NODEV))
|
||||
+ {
|
||||
+ die("MS_RELATIME malfunctions\n");
|
||||
+ }
|
||||
+ if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME|MS_NODEV,
|
||||
+ MS_NOATIME|MS_NODEV))
|
||||
+ {
|
||||
+ die("MS_RELATIME malfunctions\n");
|
||||
+ }
|
||||
+ if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME|MS_NODEV,
|
||||
+ MS_STRICTATIME|MS_NODEV))
|
||||
+ {
|
||||
+ die("MS_RELATIME malfunctions\n");
|
||||
+ }
|
||||
+ if (!test_unpriv_remount(MS_STRICTATIME|MS_NODEV, MS_NODEV,
|
||||
+ MS_NOATIME|MS_NODEV))
|
||||
+ {
|
||||
+ die("Default atime malfunctions\n");
|
||||
+ }
|
||||
+ return EXIT_SUCCESS;
|
||||
+}
|
|
@ -1,53 +0,0 @@
|
|||
From: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||
Date: Mon, 28 Jul 2014 17:36:04 -0700
|
||||
Subject: [4/5] mnt: Change the default remount atime from relatime to the
|
||||
existing value
|
||||
Origin: https://git.kernel.org/linus/ffbc6f0ead47fa5a1dc9642b0331cb75c20a640e
|
||||
|
||||
Since March 2009 the kernel has treated the state that if no
|
||||
MS_..ATIME flags are passed then the kernel defaults to relatime.
|
||||
|
||||
Defaulting to relatime instead of the existing atime state during a
|
||||
remount is silly, and causes problems in practice for people who don't
|
||||
specify any MS_...ATIME flags and to get the default filesystem atime
|
||||
setting. Those users may encounter a permission error because the
|
||||
default atime setting does not work.
|
||||
|
||||
A default that does not work and causes permission problems is
|
||||
ridiculous, so preserve the existing value to have a default
|
||||
atime setting that is always guaranteed to work.
|
||||
|
||||
Using the default atime setting in this way is particularly
|
||||
interesting for applications built to run in restricted userspace
|
||||
environments without /proc mounted, as the existing atime mount
|
||||
options of a filesystem can not be read from /proc/mounts.
|
||||
|
||||
In practice this fixes user space that uses the default atime
|
||||
setting on remount that are broken by the permission checks
|
||||
keeping less privileged users from changing more privileged users
|
||||
atime settings.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
|
||||
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||
---
|
||||
fs/namespace.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/fs/namespace.c
|
||||
+++ b/fs/namespace.c
|
||||
@@ -2475,6 +2475,14 @@ long do_mount(const char *dev_name, cons
|
||||
if (flags & MS_RDONLY)
|
||||
mnt_flags |= MNT_READONLY;
|
||||
|
||||
+ /* The default atime for remount is preservation */
|
||||
+ if ((flags & MS_REMOUNT) &&
|
||||
+ ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME |
|
||||
+ MS_STRICTATIME)) == 0)) {
|
||||
+ mnt_flags &= ~MNT_ATIME_MASK;
|
||||
+ mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK;
|
||||
+ }
|
||||
+
|
||||
flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN |
|
||||
MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
|
||||
MS_STRICTATIME);
|
|
@ -1,125 +0,0 @@
|
|||
From: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||
Date: Mon, 28 Jul 2014 17:26:07 -0700
|
||||
Subject: [3/5] mnt: Correct permission checks in do_remount
|
||||
Origin: https://git.kernel.org/linus/9566d6742852c527bf5af38af5cbb878dad75705
|
||||
|
||||
While invesgiating the issue where in "mount --bind -oremount,ro ..."
|
||||
would result in later "mount --bind -oremount,rw" succeeding even if
|
||||
the mount started off locked I realized that there are several
|
||||
additional mount flags that should be locked and are not.
|
||||
|
||||
In particular MNT_NOSUID, MNT_NODEV, MNT_NOEXEC, and the atime
|
||||
flags in addition to MNT_READONLY should all be locked. These
|
||||
flags are all per superblock, can all be changed with MS_BIND,
|
||||
and should not be changable if set by a more privileged user.
|
||||
|
||||
The following additions to the current logic are added in this patch.
|
||||
- nosuid may not be clearable by a less privileged user.
|
||||
- nodev may not be clearable by a less privielged user.
|
||||
- noexec may not be clearable by a less privileged user.
|
||||
- atime flags may not be changeable by a less privileged user.
|
||||
|
||||
The logic with atime is that always setting atime on access is a
|
||||
global policy and backup software and auditing software could break if
|
||||
atime bits are not updated (when they are configured to be updated),
|
||||
and serious performance degradation could result (DOS attack) if atime
|
||||
updates happen when they have been explicitly disabled. Therefore an
|
||||
unprivileged user should not be able to mess with the atime bits set
|
||||
by a more privileged user.
|
||||
|
||||
The additional restrictions are implemented with the addition of
|
||||
MNT_LOCK_NOSUID, MNT_LOCK_NODEV, MNT_LOCK_NOEXEC, and MNT_LOCK_ATIME
|
||||
mnt flags.
|
||||
|
||||
Taken together these changes and the fixes for MNT_LOCK_READONLY
|
||||
should make it safe for an unprivileged user to create a user
|
||||
namespace and to call "mount --bind -o remount,... ..." without
|
||||
the danger of mount flags being changed maliciously.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
|
||||
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||
---
|
||||
fs/namespace.c | 36 +++++++++++++++++++++++++++++++++---
|
||||
include/linux/mount.h | 5 +++++
|
||||
2 files changed, 38 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/fs/namespace.c
|
||||
+++ b/fs/namespace.c
|
||||
@@ -891,8 +891,21 @@ static struct mount *clone_mnt(struct mo
|
||||
|
||||
mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED);
|
||||
/* Don't allow unprivileged users to change mount flags */
|
||||
- if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY))
|
||||
- mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;
|
||||
+ if (flag & CL_UNPRIVILEGED) {
|
||||
+ mnt->mnt.mnt_flags |= MNT_LOCK_ATIME;
|
||||
+
|
||||
+ if (mnt->mnt.mnt_flags & MNT_READONLY)
|
||||
+ mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;
|
||||
+
|
||||
+ if (mnt->mnt.mnt_flags & MNT_NODEV)
|
||||
+ mnt->mnt.mnt_flags |= MNT_LOCK_NODEV;
|
||||
+
|
||||
+ if (mnt->mnt.mnt_flags & MNT_NOSUID)
|
||||
+ mnt->mnt.mnt_flags |= MNT_LOCK_NOSUID;
|
||||
+
|
||||
+ if (mnt->mnt.mnt_flags & MNT_NOEXEC)
|
||||
+ mnt->mnt.mnt_flags |= MNT_LOCK_NOEXEC;
|
||||
+ }
|
||||
|
||||
/* Don't allow unprivileged users to reveal what is under a mount */
|
||||
if ((flag & CL_UNPRIVILEGED) && list_empty(&old->mnt_expire))
|
||||
@@ -1933,6 +1946,23 @@ static int do_remount(struct path *path,
|
||||
!(mnt_flags & MNT_READONLY)) {
|
||||
return -EPERM;
|
||||
}
|
||||
+ if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) &&
|
||||
+ !(mnt_flags & MNT_NODEV)) {
|
||||
+ return -EPERM;
|
||||
+ }
|
||||
+ if ((mnt->mnt.mnt_flags & MNT_LOCK_NOSUID) &&
|
||||
+ !(mnt_flags & MNT_NOSUID)) {
|
||||
+ return -EPERM;
|
||||
+ }
|
||||
+ if ((mnt->mnt.mnt_flags & MNT_LOCK_NOEXEC) &&
|
||||
+ !(mnt_flags & MNT_NOEXEC)) {
|
||||
+ return -EPERM;
|
||||
+ }
|
||||
+ if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) &&
|
||||
+ ((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (mnt_flags & MNT_ATIME_MASK))) {
|
||||
+ return -EPERM;
|
||||
+ }
|
||||
+
|
||||
err = security_sb_remount(sb, data);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -2131,7 +2161,7 @@ static int do_new_mount(struct path *pat
|
||||
*/
|
||||
if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) {
|
||||
flags |= MS_NODEV;
|
||||
- mnt_flags |= MNT_NODEV;
|
||||
+ mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV;
|
||||
}
|
||||
}
|
||||
|
||||
--- a/include/linux/mount.h
|
||||
+++ b/include/linux/mount.h
|
||||
@@ -45,12 +45,17 @@ struct mnt_namespace;
|
||||
#define MNT_USER_SETTABLE_MASK (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC \
|
||||
| MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME \
|
||||
| MNT_READONLY)
|
||||
+#define MNT_ATIME_MASK (MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME )
|
||||
|
||||
#define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \
|
||||
MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED)
|
||||
|
||||
#define MNT_INTERNAL 0x4000
|
||||
|
||||
+#define MNT_LOCK_ATIME 0x040000
|
||||
+#define MNT_LOCK_NOEXEC 0x080000
|
||||
+#define MNT_LOCK_NOSUID 0x100000
|
||||
+#define MNT_LOCK_NODEV 0x200000
|
||||
#define MNT_LOCK_READONLY 0x400000
|
||||
#define MNT_LOCKED 0x800000
|
||||
#define MNT_DOOMED 0x1000000
|
|
@ -1,50 +0,0 @@
|
|||
From: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||
Date: Mon, 28 Jul 2014 17:10:56 -0700
|
||||
Subject: [2/5] mnt: Move the test for MNT_LOCK_READONLY from
|
||||
change_mount_flags into do_remount
|
||||
Origin: https://git.kernel.org/linus/07b645589dcda8b7a5249e096fece2a67556f0f4
|
||||
|
||||
There are no races as locked mount flags are guaranteed to never change.
|
||||
|
||||
Moving the test into do_remount makes it more visible, and ensures all
|
||||
filesystem remounts pass the MNT_LOCK_READONLY permission check. This
|
||||
second case is not an issue today as filesystem remounts are guarded
|
||||
by capable(CAP_DAC_ADMIN) and thus will always fail in less privileged
|
||||
mount namespaces, but it could become an issue in the future.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
|
||||
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||
---
|
||||
fs/namespace.c | 13 ++++++++++---
|
||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/fs/namespace.c
|
||||
+++ b/fs/namespace.c
|
||||
@@ -1898,9 +1898,6 @@ static int change_mount_flags(struct vfs
|
||||
if (readonly_request == __mnt_is_readonly(mnt))
|
||||
return 0;
|
||||
|
||||
- if (mnt->mnt_flags & MNT_LOCK_READONLY)
|
||||
- return -EPERM;
|
||||
-
|
||||
if (readonly_request)
|
||||
error = mnt_make_readonly(real_mount(mnt));
|
||||
else
|
||||
@@ -1926,6 +1923,16 @@ static int do_remount(struct path *path,
|
||||
if (path->dentry != path->mnt->mnt_root)
|
||||
return -EINVAL;
|
||||
|
||||
+ /* Don't allow changing of locked mnt flags.
|
||||
+ *
|
||||
+ * No locks need to be held here while testing the various
|
||||
+ * MNT_LOCK flags because those flags can never be cleared
|
||||
+ * once they are set.
|
||||
+ */
|
||||
+ if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) &&
|
||||
+ !(mnt_flags & MNT_READONLY)) {
|
||||
+ return -EPERM;
|
||||
+ }
|
||||
err = security_sb_remount(sb, data);
|
||||
if (err)
|
||||
return err;
|
|
@ -1,48 +0,0 @@
|
|||
From: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||
Date: Mon, 28 Jul 2014 16:26:53 -0700
|
||||
Subject: [1/5] mnt: Only change user settable mount flags in remount
|
||||
Origin: https://git.kernel.org/linus/a6138db815df5ee542d848318e5dae681590fccd
|
||||
|
||||
Kenton Varda <kenton@sandstorm.io> discovered that by remounting a
|
||||
read-only bind mount read-only in a user namespace the
|
||||
MNT_LOCK_READONLY bit would be cleared, allowing an unprivileged user
|
||||
to the remount a read-only mount read-write.
|
||||
|
||||
Correct this by replacing the mask of mount flags to preserve
|
||||
with a mask of mount flags that may be changed, and preserve
|
||||
all others. This ensures that any future bugs with this mask and
|
||||
remount will fail in an easy to detect way where new mount flags
|
||||
simply won't change.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
|
||||
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||
---
|
||||
fs/namespace.c | 2 +-
|
||||
include/linux/mount.h | 4 +++-
|
||||
2 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/fs/namespace.c
|
||||
+++ b/fs/namespace.c
|
||||
@@ -1939,7 +1939,7 @@ static int do_remount(struct path *path,
|
||||
err = do_remount_sb(sb, flags, data, 0);
|
||||
if (!err) {
|
||||
lock_mount_hash();
|
||||
- mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK;
|
||||
+ mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK;
|
||||
mnt->mnt.mnt_flags = mnt_flags;
|
||||
touch_mnt_namespace(mnt->mnt_ns);
|
||||
unlock_mount_hash();
|
||||
--- a/include/linux/mount.h
|
||||
+++ b/include/linux/mount.h
|
||||
@@ -42,7 +42,9 @@ struct mnt_namespace;
|
||||
* flag, consider how it interacts with shared mounts.
|
||||
*/
|
||||
#define MNT_SHARED_MASK (MNT_UNBINDABLE)
|
||||
-#define MNT_PROPAGATION_MASK (MNT_SHARED | MNT_UNBINDABLE)
|
||||
+#define MNT_USER_SETTABLE_MASK (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC \
|
||||
+ | MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME \
|
||||
+ | MNT_READONLY)
|
||||
|
||||
#define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \
|
||||
MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED)
|
|
@ -1,61 +0,0 @@
|
|||
From: Alex Smith <alex.smith@imgtec.com>
|
||||
Date: Wed, 23 Jul 2014 14:40:11 +0100
|
||||
Subject: MIPS: O32/32-bit: Fix bug which can cause incorrect system
|
||||
call restarts
|
||||
Origin: https://git.kernel.org/linus/e90e6fddc57055c4c6b57f92787fea1c065d440b
|
||||
|
||||
On 32-bit/O32, pt_regs has a padding area at the beginning into which the
|
||||
syscall arguments passed via the user stack are copied. 4 arguments
|
||||
totalling 16 bytes are copied to offset 16 bytes into this area, however
|
||||
the area is only 24 bytes long. This means the last 2 arguments overwrite
|
||||
pt_regs->regs[{0,1}].
|
||||
|
||||
If a syscall function returns an error, handle_sys stores the original
|
||||
syscall number in pt_regs->regs[0] for syscall restart. signal.c checks
|
||||
whether regs[0] is non-zero, if it is it will check whether the syscall
|
||||
return value is one of the ERESTART* codes to see if it must be
|
||||
restarted.
|
||||
|
||||
Should a syscall be made that results in a non-zero value being copied
|
||||
off the user stack into regs[0], and then returns a positive (non-error)
|
||||
value that matches one of the ERESTART* error codes, this can be mistaken
|
||||
for requiring a syscall restart.
|
||||
|
||||
While the possibility for this to occur has always existed, it is made
|
||||
much more likely to occur by commit 46e12c07b3b9 ("MIPS: O32 / 32-bit:
|
||||
Always copy 4 stack arguments."), since now every syscall will copy 4
|
||||
arguments and overwrite regs[0], rather than just those with 7 or 8
|
||||
arguments.
|
||||
|
||||
Since that commit, booting Debian under a 32-bit MIPS kernel almost
|
||||
always results in a hang early in boot, due to a wait4 syscall returning
|
||||
a PID that matches one of the ERESTART* codes, which then causes an
|
||||
incorrect restart of the syscall.
|
||||
|
||||
The problem is fixed by increasing the size of the padding area so that
|
||||
arguments copied off the stack will not overwrite pt_regs->regs[{0,1}].
|
||||
|
||||
Signed-off-by: Alex Smith <alex.smith@imgtec.com>
|
||||
Cc: <stable@vger.kernel.org> # v3.13+
|
||||
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
|
||||
---
|
||||
arch/mips/include/asm/ptrace.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
|
||||
index 7e6e682..c301fa9 100644
|
||||
--- a/arch/mips/include/asm/ptrace.h
|
||||
+++ b/arch/mips/include/asm/ptrace.h
|
||||
@@ -23,7 +23,7 @@
|
||||
struct pt_regs {
|
||||
#ifdef CONFIG_32BIT
|
||||
/* Pad bytes for argument save space on the stack. */
|
||||
- unsigned long pad0[6];
|
||||
+ unsigned long pad0[8];
|
||||
#endif
|
||||
|
||||
/* Saved main processor registers. */
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
From: Aaro Koskinen <aaro.koskinen@nsn.com>
|
||||
Date: Tue, 22 Jul 2014 14:51:08 +0300
|
||||
Subject: MIPS: OCTEON: make get_system_type() thread-safe
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/?id=726d129dfdc9622197a8c3f5947ce09c1a4c935e
|
||||
|
||||
get_system_type() is not thread-safe on OCTEON. It uses static data,
|
||||
also more dangerous issue is that it's calling cvmx_fuse_read_byte()
|
||||
every time without any synchronization. Currently it's possible to get
|
||||
processes stuck looping forever in kernel simply by launching multiple
|
||||
readers of /proc/cpuinfo:
|
||||
|
||||
(while true; do cat /proc/cpuinfo > /dev/null; done) &
|
||||
(while true; do cat /proc/cpuinfo > /dev/null; done) &
|
||||
...
|
||||
|
||||
Fix by initializing the system type string only once during the early
|
||||
boot.
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@nsn.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Reviewed-by: Markos Chandras <markos.chandras@imgtec.com>
|
||||
Patchwork: http://patchwork.linux-mips.org/patch/7437/
|
||||
Signed-off-by: James Hogan <james.hogan@imgtec.com>
|
||||
---
|
||||
arch/mips/cavium-octeon/setup.c | 18 +++++++++++++-----
|
||||
1 file changed, 13 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
|
||||
index 008e9c8..c9d9c62 100644
|
||||
--- a/arch/mips/cavium-octeon/setup.c
|
||||
+++ b/arch/mips/cavium-octeon/setup.c
|
||||
@@ -458,6 +458,18 @@ static void octeon_halt(void)
|
||||
octeon_kill_core(NULL);
|
||||
}
|
||||
|
||||
+static char __read_mostly octeon_system_type[80];
|
||||
+
|
||||
+static int __init init_octeon_system_type(void)
|
||||
+{
|
||||
+ snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)",
|
||||
+ cvmx_board_type_to_string(octeon_bootinfo->board_type),
|
||||
+ octeon_model_get_string(read_c0_prid()));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+early_initcall(init_octeon_system_type);
|
||||
+
|
||||
/**
|
||||
* Return a string representing the system type
|
||||
*
|
||||
@@ -465,11 +477,7 @@ static void octeon_halt(void)
|
||||
*/
|
||||
const char *octeon_board_type_string(void)
|
||||
{
|
||||
- static char name[80];
|
||||
- sprintf(name, "%s (%s)",
|
||||
- cvmx_board_type_to_string(octeon_bootinfo->board_type),
|
||||
- octeon_model_get_string(read_c0_prid()));
|
||||
- return name;
|
||||
+ return octeon_system_type;
|
||||
}
|
||||
|
||||
const char *get_system_type(void)
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
From: Huacai Chen <chenhc@lemote.com>
|
||||
Date: Wed, 16 Jul 2014 09:19:16 +0800
|
||||
Subject: MIPS: Remove BUG_ON(!is_fpu_owner()) in do_ade()
|
||||
Origin: https://git.kernel.org/linus/2e5767a27337812f6850b3fa362419e2f085e5c3
|
||||
|
||||
In do_ade(), is_fpu_owner() isn't preempt-safe. For example, when an
|
||||
unaligned ldc1 is executed, do_cpu() is called and then FPU will be
|
||||
enabled (and TIF_USEDFPU will be set for the current process). Then,
|
||||
do_ade() is called because the access is unaligned. If the current
|
||||
process is preempted at this time, TIF_USEDFPU will be cleard. So when
|
||||
the process is scheduled again, BUG_ON(!is_fpu_owner()) is triggered.
|
||||
|
||||
This small program can trigger this BUG in a preemptible kernel:
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
double u64[2];
|
||||
|
||||
while (1) {
|
||||
asm volatile (
|
||||
".set push \n\t"
|
||||
".set noreorder \n\t"
|
||||
"ldc1 $f3, 4(%0) \n\t"
|
||||
".set pop \n\t"
|
||||
::"r"(u64):
|
||||
);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
V2: Remove the BUG_ON() unconditionally due to Paul's suggestion.
|
||||
|
||||
Signed-off-by: Huacai Chen <chenhc@lemote.com>
|
||||
Signed-off-by: Jie Chen <chenj@lemote.com>
|
||||
Signed-off-by: Rui Wang <wangr@lemote.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Cc: John Crispin <john@phrozen.org>
|
||||
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Cc: Fuxin Zhang <zhangfx@lemote.com>
|
||||
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/kernel/unaligned.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
|
||||
index 2b35172..e11906d 100644
|
||||
--- a/arch/mips/kernel/unaligned.c
|
||||
+++ b/arch/mips/kernel/unaligned.c
|
||||
@@ -690,7 +690,6 @@ static void emulate_load_store_insn(struct pt_regs *regs,
|
||||
case sdc1_op:
|
||||
die_if_kernel("Unaligned FP access in kernel code", regs);
|
||||
BUG_ON(!used_math());
|
||||
- BUG_ON(!is_fpu_owner());
|
||||
|
||||
lose_fpu(1); /* Save FPU state for the emulator. */
|
||||
res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1,
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
From: Paul Burton <paul.burton@imgtec.com>
|
||||
Date: Tue, 22 Jul 2014 14:21:21 +0100
|
||||
Subject: MIPS: prevent user from setting FCSR cause bits
|
||||
Origin: https://git.kernel.org/linus/b1442d39fac2fcfbe6a4814979020e993ca59c9e
|
||||
|
||||
If one or more matching FCSR cause & enable bits are set in saved thread
|
||||
context then when that context is restored the kernel will take an FP
|
||||
exception. This is of course undesirable and considered an oops, leading
|
||||
to the kernel writing a backtrace to the console and potentially
|
||||
rebooting depending upon the configuration. Thus the kernel avoids this
|
||||
situation by clearing the cause bits of the FCSR register when handling
|
||||
FP exceptions and after emulating FP instructions.
|
||||
|
||||
However the kernel does not prevent userland from setting arbitrary FCSR
|
||||
cause & enable bits via ptrace, using either the PTRACE_POKEUSR or
|
||||
PTRACE_SETFPREGS requests. This means userland can trivially cause the
|
||||
kernel to oops on any system with an FPU. Prevent this from happening
|
||||
by clearing the cause bits when writing to the saved FCSR context via
|
||||
ptrace.
|
||||
|
||||
This problem appears to exist at least back to the beginning of the git
|
||||
era in the PTRACE_POKEUSR case.
|
||||
|
||||
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Patchwork: http://patchwork.linux-mips.org/patch/7438/
|
||||
Signed-off-by: James Hogan <james.hogan@imgtec.com>
|
||||
---
|
||||
arch/mips/kernel/ptrace.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/mips/kernel/ptrace.c
|
||||
+++ b/arch/mips/kernel/ptrace.c
|
||||
@@ -151,6 +151,7 @@ int ptrace_setfpregs(struct task_struct
|
||||
}
|
||||
|
||||
__get_user(child->thread.fpu.fcr31, data + 64);
|
||||
+ child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
|
||||
|
||||
/* FIR may not be written. */
|
||||
|
||||
@@ -565,7 +566,7 @@ long arch_ptrace(struct task_struct *chi
|
||||
break;
|
||||
#endif
|
||||
case FPC_CSR:
|
||||
- child->thread.fpu.fcr31 = data;
|
||||
+ child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X;
|
||||
break;
|
||||
case DSP_BASE ... DSP_BASE + 5: {
|
||||
dspreg_t *dregs;
|
|
@ -1,35 +0,0 @@
|
|||
From: Huacai Chen <chenhc@lemote.com>
|
||||
Date: Tue, 29 Jul 2014 14:54:40 +0800
|
||||
Subject: MIPS: tlbex: fix a missing statement for HUGETLB
|
||||
Origin: https://git.kernel.org/linus/8393c524a25609a30129e4a8975cf3b91f6c16a5
|
||||
|
||||
In commit 2c8c53e28f1 (MIPS: Optimize TLB handlers for Octeon CPUs)
|
||||
build_r4000_tlb_refill_handler() is modified. But it doesn't compatible
|
||||
with the original code in HUGETLB case. Because there is a copy & paste
|
||||
error and one line of code is missing. It is very easy to produce a bug
|
||||
with LTP's hugemmap05 test.
|
||||
|
||||
Signed-off-by: Huacai Chen <chenhc@lemote.com>
|
||||
Signed-off-by: Binbin Zhou <zhoubb@lemote.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
|
||||
---
|
||||
arch/mips/mm/tlbex.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
|
||||
index e80e10b..343fe0f 100644
|
||||
--- a/arch/mips/mm/tlbex.c
|
||||
+++ b/arch/mips/mm/tlbex.c
|
||||
@@ -1299,6 +1299,7 @@ static void build_r4000_tlb_refill_handler(void)
|
||||
}
|
||||
#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
|
||||
uasm_l_tlb_huge_update(&l, p);
|
||||
+ UASM_i_LW(&p, K0, 0, K1);
|
||||
build_huge_update_entries(&p, htlb_info.huge_pte, K1);
|
||||
build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
|
||||
htlb_info.restore_scratch);
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -12,13 +12,16 @@ make[5]: *** [__modpost] Error 1
|
|||
But report:
|
||||
http://www.mail-archive.com/linux-scsi@vger.kernel.org/msg12773.html
|
||||
|
||||
--- a/drivers/scsi/Kconfig 2007-12-27 19:16:18.000000000 +0000
|
||||
+++ b/drivers/scsi/Kconfig 2007-12-27 19:16:58.000000000 +0000
|
||||
@@ -523,6 +523,7 @@
|
||||
[bwh: Upstream finally accepted this was broken on ARM! But MIPS has
|
||||
the same problem still.]
|
||||
|
||||
--- a/drivers/scsi/Kconfig
|
||||
+++ b/drivers/scsi/Kconfig
|
||||
@@ -495,6 +495,7 @@ config SCSI_ADVANSYS
|
||||
tristate "AdvanSys SCSI support"
|
||||
depends on SCSI && VIRT_TO_BUS
|
||||
depends on SCSI && VIRT_TO_BUS && !ARM
|
||||
depends on ISA || EISA || PCI
|
||||
+ depends on (!MIPS && !ARM) || BROKEN
|
||||
+ depends on !MIPS || BROKEN
|
||||
help
|
||||
This is a driver for all SCSI host adapters manufactured by
|
||||
AdvanSys. It is documented in the kernel source in
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
From: Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
Date: Tue, 15 Jul 2014 17:53:12 +0200
|
||||
Subject: s390/3215: fix hanging console issue
|
||||
Origin: https://git.kernel.org/cgit/linux/kernel/git/s390/linux.git/commit?id=26d766c60f4ea08cd14f0f3435a6db3d6cc2ae96
|
||||
Bug-Debian: https://bugs.debian.org/747922
|
||||
|
||||
The ccw_device_start in raw3215_start_io can fail. raw3215_try_io
|
||||
does not check if the request could be started and removes any
|
||||
pending timer. This can leave the system in a hanging state.
|
||||
Check for pending request after raw3215_start_io and start a
|
||||
timer if necessary.
|
||||
|
||||
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
---
|
||||
drivers/s390/char/con3215.c | 32 +++++++++++++++++---------------
|
||||
1 file changed, 17 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
|
||||
index 5af7f0b..a6d47e5 100644
|
||||
--- a/drivers/s390/char/con3215.c
|
||||
+++ b/drivers/s390/char/con3215.c
|
||||
@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned long __data)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
|
||||
- if (raw->flags & RAW3215_TIMER_RUNS) {
|
||||
- del_timer(&raw->timer);
|
||||
- raw->flags &= ~RAW3215_TIMER_RUNS;
|
||||
- if (!(raw->port.flags & ASYNC_SUSPENDED)) {
|
||||
- raw3215_mk_write_req(raw);
|
||||
- raw3215_start_io(raw);
|
||||
+ raw->flags &= ~RAW3215_TIMER_RUNS;
|
||||
+ if (!(raw->port.flags & ASYNC_SUSPENDED)) {
|
||||
+ raw3215_mk_write_req(raw);
|
||||
+ raw3215_start_io(raw);
|
||||
+ if ((raw->queued_read || raw->queued_write) &&
|
||||
+ !(raw->flags & RAW3215_WORKING) &&
|
||||
+ !(raw->flags & RAW3215_TIMER_RUNS)) {
|
||||
+ raw->timer.expires = RAW3215_TIMEOUT + jiffies;
|
||||
+ add_timer(&raw->timer);
|
||||
+ raw->flags |= RAW3215_TIMER_RUNS;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
|
||||
@@ -317,17 +321,15 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
|
||||
(raw->flags & RAW3215_FLUSHING)) {
|
||||
/* execute write requests bigger than minimum size */
|
||||
raw3215_start_io(raw);
|
||||
- if (raw->flags & RAW3215_TIMER_RUNS) {
|
||||
- del_timer(&raw->timer);
|
||||
- raw->flags &= ~RAW3215_TIMER_RUNS;
|
||||
- }
|
||||
- } else if (!(raw->flags & RAW3215_TIMER_RUNS)) {
|
||||
- /* delay small writes */
|
||||
- raw->timer.expires = RAW3215_TIMEOUT + jiffies;
|
||||
- add_timer(&raw->timer);
|
||||
- raw->flags |= RAW3215_TIMER_RUNS;
|
||||
}
|
||||
}
|
||||
+ if ((raw->queued_read || raw->queued_write) &&
|
||||
+ !(raw->flags & RAW3215_WORKING) &&
|
||||
+ !(raw->flags & RAW3215_TIMER_RUNS)) {
|
||||
+ raw->timer.expires = RAW3215_TIMEOUT + jiffies;
|
||||
+ add_timer(&raw->timer);
|
||||
+ raw->flags |= RAW3215_TIMER_RUNS;
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
|
@ -18,11 +18,6 @@ rm drivers/net/appletalk/cops_ltdrv.h
|
|||
rm drivers/staging/ft1000/ft1000-pcmcia/boot.h
|
||||
rm drivers/staging/ft1000/ft1000-*/*.img
|
||||
|
||||
rm drivers/staging/keucr/init.h
|
||||
|
||||
rm drivers/staging/wlags49_h2/ap_*.c
|
||||
rm drivers/staging/wlags49_h2/sta_*.c
|
||||
|
||||
# These include apparently obfuscated code
|
||||
rm drivers/video/fbdev/nvidia/
|
||||
rm drivers/video/fbdev/riva/
|
||||
|
|
|
@ -21,11 +21,9 @@ Including the scripts in linux-kbuild will avoid this manual step
|
|||
altogether, and allow for the possibility of other archs to provide
|
||||
their own scripts in the future.
|
||||
|
||||
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
|
||||
index e7cbaa0..c8af869 100644
|
||||
--- a/arch/ia64/Makefile
|
||||
+++ b/arch/ia64/Makefile
|
||||
@@ -30,16 +30,7 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \
|
||||
@@ -30,16 +30,7 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 -
|
||||
-falign-functions=32 -frename-registers -fno-optimize-sibling-calls
|
||||
KBUILD_CFLAGS_KERNEL := -mconstant-gp
|
||||
|
||||
|
@ -43,7 +41,7 @@ index e7cbaa0..c8af869 100644
|
|||
|
||||
KBUILD_CFLAGS += $(cflags-y)
|
||||
head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
|
||||
@@ -69,7 +60,7 @@ boot := arch/ia64/hp/sim/boot
|
||||
@@ -66,7 +57,7 @@ boot := arch/ia64/hp/sim/boot
|
||||
|
||||
PHONY += boot compressed check
|
||||
|
||||
|
@ -52,17 +50,17 @@ index e7cbaa0..c8af869 100644
|
|||
|
||||
compressed: vmlinux.gz
|
||||
|
||||
@@ -78,9 +69,6 @@ vmlinuz: vmlinux.gz
|
||||
@@ -75,9 +66,6 @@ vmlinuz: vmlinux.gz
|
||||
vmlinux.gz: vmlinux
|
||||
$(Q)$(MAKE) $(build)=$(boot) $@
|
||||
|
||||
-unwcheck: vmlinux
|
||||
- -$(Q)READELF=$(READELF) python $(srctree)/arch/ia64/scripts/unwcheck.py $<
|
||||
- -$(Q)READELF=$(READELF) $(PYTHON) $(srctree)/arch/ia64/scripts/unwcheck.py $<
|
||||
-
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=$(boot)
|
||||
|
||||
@@ -96,7 +84,6 @@ define archhelp
|
||||
@@ -93,7 +81,6 @@ define archhelp
|
||||
echo '* compressed - Build compressed kernel image'
|
||||
echo ' install - Install compressed kernel image'
|
||||
echo ' boot - Build vmlinux and bootloader for Ski simulator'
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,7 +9,7 @@ are set.
|
|||
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -826,7 +826,7 @@ endif
|
||||
@@ -963,7 +963,7 @@ endif
|
||||
prepare2: prepare3 outputmakefile asm-generic
|
||||
|
||||
prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
|
||||
|
@ -18,7 +18,7 @@ are set.
|
|||
$(cmd_crmodverdir)
|
||||
|
||||
archprepare: archheaders archscripts prepare1 scripts_basic
|
||||
@@ -858,12 +858,25 @@ define filechk_version.h
|
||||
@@ -995,12 +995,25 @@ define filechk_version.h
|
||||
echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
|
||||
endef
|
||||
|
||||
|
@ -54,7 +54,7 @@ are set.
|
|||
#include <asm/current.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/sysrq.h>
|
||||
@@ -16,8 +17,9 @@ void __show_regs(struct pt_regs *regs)
|
||||
@@ -16,8 +17,9 @@ void show_regs(struct pt_regs *regs)
|
||||
{
|
||||
printk("\n");
|
||||
print_modules();
|
||||
|
@ -90,7 +90,7 @@ are set.
|
|||
regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
|
||||
--- a/arch/powerpc/kernel/process.c
|
||||
+++ b/arch/powerpc/kernel/process.c
|
||||
@@ -38,6 +38,7 @@
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <linux/personality.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/hw_breakpoint.h>
|
||||
|
@ -98,7 +98,7 @@ are set.
|
|||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/uaccess.h>
|
||||
@@ -843,8 +844,9 @@ void show_regs(struct pt_regs * regs)
|
||||
@@ -1004,8 +1005,9 @@ void show_regs(struct pt_regs * regs)
|
||||
|
||||
printk("NIP: "REG" LR: "REG" CTR: "REG"\n",
|
||||
regs->nip, regs->link, regs->ctr);
|
||||
|
@ -112,15 +112,15 @@ are set.
|
|||
printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer);
|
||||
--- a/kernel/printk/printk.c
|
||||
+++ b/kernel/printk/printk.c
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <linux/poll.h>
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <linux/irq_work.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/ctype.h>
|
||||
+#include <generated/package.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
@@ -2871,11 +2872,12 @@ void __init dump_stack_set_arch_desc(con
|
||||
@@ -3034,11 +3035,12 @@ void __init dump_stack_set_arch_desc(con
|
||||
*/
|
||||
void dump_stack_print_info(const char *log_lvl)
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
|
||||
--- a/Documentation/kernel-parameters.txt
|
||||
+++ b/Documentation/kernel-parameters.txt
|
||||
@@ -569,8 +569,8 @@ bytes respectively. Such letter suffixes
|
||||
@@ -580,8 +580,8 @@ bytes respectively. Such letter suffixes
|
||||
ccw_timeout_log [S390]
|
||||
See Documentation/s390/CommonIO for details.
|
||||
|
||||
|
@ -32,7 +32,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
a single hierarchy
|
||||
--- a/init/Kconfig
|
||||
+++ b/init/Kconfig
|
||||
@@ -960,6 +960,14 @@ config MEMCG
|
||||
@@ -1003,6 +1003,14 @@ config MEMCG
|
||||
disable memory resource controller and you can avoid overheads.
|
||||
(and lose benefits of memory resource controller)
|
||||
|
||||
|
@ -49,7 +49,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
depends on MEMCG && SWAP
|
||||
--- a/kernel/cgroup.c
|
||||
+++ b/kernel/cgroup.c
|
||||
@@ -5182,7 +5182,7 @@ static void cgroup_release_agent(struct
|
||||
@@ -5359,7 +5359,7 @@ static void cgroup_release_agent(struct
|
||||
mutex_unlock(&cgroup_mutex);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
{
|
||||
struct cgroup_subsys *ss;
|
||||
char *token;
|
||||
@@ -5194,17 +5194,29 @@ static int __init cgroup_disable(char *s
|
||||
@@ -5371,17 +5371,29 @@ static int __init cgroup_disable(char *s
|
||||
|
||||
for_each_subsys(ss, i) {
|
||||
if (!strcmp(token, ss->name)) {
|
||||
|
@ -88,12 +88,12 @@ Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|||
+}
|
||||
+__setup("cgroup_enable=", cgroup_enable);
|
||||
+
|
||||
/**
|
||||
* css_tryget_online_from_dir - get corresponding css from a cgroup dentry
|
||||
* @dentry: directory dentry of interest
|
||||
static int __init cgroup_set_legacy_files_on_dfl(char *str)
|
||||
{
|
||||
printk("cgroup: using legacy files on the default hierarchy\n");
|
||||
--- a/mm/memcontrol.c
|
||||
+++ b/mm/memcontrol.c
|
||||
@@ -7015,6 +7015,9 @@ static void mem_cgroup_bind(struct cgrou
|
||||
@@ -6297,6 +6297,9 @@ static void mem_cgroup_bind(struct cgrou
|
||||
}
|
||||
|
||||
struct cgroup_subsys memory_cgrp_subsys = {
|
||||
|
|
|
@ -14,48 +14,8 @@ Instead, give them module aliases as if they are platform drivers, and
|
|||
register a corresponding platform device whenever EFI runtime services
|
||||
are available. This should trigger udev to load them.
|
||||
|
||||
[bwh: Most of this went upstream in 3.17-rc4, just not the efi-pstore bit.]
|
||||
---
|
||||
--- a/arch/x86/platform/efi/efi.c
|
||||
+++ b/arch/x86/platform/efi/efi.c
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/bcd.h>
|
||||
+#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/efi.h>
|
||||
@@ -783,6 +784,20 @@ void __init efi_late_init(void)
|
||||
efi_bgrt_init();
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_EFI_VARS_MODULE
|
||||
+static int __init efi_load_efivars(void)
|
||||
+{
|
||||
+ struct platform_device *pdev;
|
||||
+
|
||||
+ if (!efi_enabled(EFI_RUNTIME_SERVICES))
|
||||
+ return 0;
|
||||
+
|
||||
+ pdev = platform_device_register_simple("efivars", 0, NULL, 0);
|
||||
+ return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
|
||||
+}
|
||||
+device_initcall(efi_load_efivars);
|
||||
+#endif
|
||||
+
|
||||
void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
|
||||
{
|
||||
u64 addr, npages;
|
||||
--- a/drivers/firmware/efi/efivars.c
|
||||
+++ b/drivers/firmware/efi/efivars.c
|
||||
@@ -77,6 +77,7 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@
|
||||
MODULE_DESCRIPTION("sysfs interface to EFI Variables");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(EFIVARS_VERSION);
|
||||
+MODULE_ALIAS("platform:efivars");
|
||||
|
||||
LIST_HEAD(efivar_sysfs_list);
|
||||
EXPORT_SYMBOL_GPL(efivar_sysfs_list);
|
||||
--- a/drivers/firmware/efi/efi-pstore.c
|
||||
+++ b/drivers/firmware/efi/efi-pstore.c
|
||||
@@ -250,3 +250,4 @@ module_exit(efivars_pstore_exit);
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
From: Venkatesh Srinivas <venkateshs@google.com>
|
||||
Date: Sun, 6 Jul 2014 16:39:27 +0200
|
||||
Subject: virtio-scsi: Implement change_queue_depth for virtscsi targets
|
||||
Origin: https://git.kernel.org/linus/761f1193f299873236dbc21277864d70cb7ba8a3
|
||||
|
||||
change_queue_depth allows changing per-target queue depth via sysfs.
|
||||
|
||||
It also allows the SCSI midlayer to ramp down the number of concurrent
|
||||
inflight requests in response to a SCSI BUSY status response and allows
|
||||
the midlayer to ramp the count back up to the device maximum when the
|
||||
BUSY condition has resolved.
|
||||
|
||||
Signed-off-by: Venkatesh Srinivas <venkateshs@google.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
||||
[bwh: Backported to 3.16: adjust context]
|
||||
---
|
||||
drivers/scsi/virtio_scsi.c | 33 +++++++++++++++++++++++++++++++++
|
||||
1 file changed, 33 insertions(+)
|
||||
|
||||
--- a/drivers/scsi/virtio_scsi.c
|
||||
+++ b/drivers/scsi/virtio_scsi.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
+#include <scsi/scsi_tcq.h>
|
||||
|
||||
#define VIRTIO_SCSI_MEMPOOL_SZ 64
|
||||
#define VIRTIO_SCSI_EVENT_LEN 8
|
||||
@@ -641,6 +642,36 @@ static int virtscsi_device_reset(struct
|
||||
return virtscsi_tmf(vscsi, cmd);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * virtscsi_change_queue_depth() - Change a virtscsi target's queue depth
|
||||
+ * @sdev: Virtscsi target whose queue depth to change
|
||||
+ * @qdepth: New queue depth
|
||||
+ * @reason: Reason for the queue depth change.
|
||||
+ */
|
||||
+static int virtscsi_change_queue_depth(struct scsi_device *sdev,
|
||||
+ int qdepth,
|
||||
+ int reason)
|
||||
+{
|
||||
+ struct Scsi_Host *shost = sdev->host;
|
||||
+ int max_depth = shost->cmd_per_lun;
|
||||
+
|
||||
+ switch (reason) {
|
||||
+ case SCSI_QDEPTH_QFULL: /* Drop qdepth in response to BUSY state */
|
||||
+ scsi_track_queue_full(sdev, qdepth);
|
||||
+ break;
|
||||
+ case SCSI_QDEPTH_RAMP_UP: /* Raise qdepth after BUSY state resolved */
|
||||
+ case SCSI_QDEPTH_DEFAULT: /* Manual change via sysfs */
|
||||
+ scsi_adjust_queue_depth(sdev,
|
||||
+ scsi_get_tag_type(sdev),
|
||||
+ min(max_depth, qdepth));
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+
|
||||
+ return sdev->queue_depth;
|
||||
+}
|
||||
+
|
||||
static int virtscsi_abort(struct scsi_cmnd *sc)
|
||||
{
|
||||
struct virtio_scsi *vscsi = shost_priv(sc->device->host);
|
||||
@@ -693,6 +724,7 @@ static struct scsi_host_template virtscs
|
||||
.this_id = -1,
|
||||
.cmd_size = sizeof(struct virtio_scsi_cmd),
|
||||
.queuecommand = virtscsi_queuecommand_single,
|
||||
+ .change_queue_depth = virtscsi_change_queue_depth,
|
||||
.eh_abort_handler = virtscsi_abort,
|
||||
.eh_device_reset_handler = virtscsi_device_reset,
|
||||
|
||||
@@ -710,6 +742,7 @@ static struct scsi_host_template virtscs
|
||||
.this_id = -1,
|
||||
.cmd_size = sizeof(struct virtio_scsi_cmd),
|
||||
.queuecommand = virtscsi_queuecommand_multi,
|
||||
+ .change_queue_depth = virtscsi_change_queue_depth,
|
||||
.eh_abort_handler = virtscsi_abort,
|
||||
.eh_device_reset_handler = virtscsi_device_reset,
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,83 +0,0 @@
|
|||
From ad56b94346519e510355624dc2f88a11ee0fe07a Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Thu, 7 Aug 2014 15:14:27 -0700
|
||||
Subject: [PATCH] dts: Add bindings for APM X-Gene SoC ethernet driver
|
||||
|
||||
This patch adds bindings for APM X-Gene SoC ethernet driver.
|
||||
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: Ravi Patel <rapatel@apm.com>
|
||||
Signed-off-by: Keyur Chudgar <kchudgar@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
arch/arm64/boot/dts/apm-mustang.dts | 4 ++++
|
||||
arch/arm64/boot/dts/apm-storm.dtsi | 30 +++++++++++++++++++++++++++---
|
||||
2 files changed, 31 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts
|
||||
index 6541962..b2f5622 100644
|
||||
--- a/arch/arm64/boot/dts/apm-mustang.dts
|
||||
+++ b/arch/arm64/boot/dts/apm-mustang.dts
|
||||
@@ -28,3 +28,7 @@
|
||||
&serial0 {
|
||||
status = "ok";
|
||||
};
|
||||
+
|
||||
+&menet {
|
||||
+ status = "ok";
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
index 40aa96c..c0aceef 100644
|
||||
--- a/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
+++ b/arch/arm64/boot/dts/apm-storm.dtsi
|
||||
@@ -167,14 +167,13 @@
|
||||
clock-output-names = "ethclk";
|
||||
};
|
||||
|
||||
- eth8clk: eth8clk {
|
||||
+ menetclk: menetclk {
|
||||
compatible = "apm,xgene-device-clock";
|
||||
#clock-cells = <1>;
|
||||
clocks = <ðclk 0>;
|
||||
- clock-names = "eth8clk";
|
||||
reg = <0x0 0x1702C000 0x0 0x1000>;
|
||||
reg-names = "csr-reg";
|
||||
- clock-output-names = "eth8clk";
|
||||
+ clock-output-names = "menetclk";
|
||||
};
|
||||
|
||||
sataphy1clk: sataphy1clk@1f21c000 {
|
||||
@@ -397,5 +396,30 @@
|
||||
#clock-cells = <1>;
|
||||
clocks = <&rtcclk 0>;
|
||||
};
|
||||
+
|
||||
+ menet: ethernet@17020000 {
|
||||
+ compatible = "apm,xgene-enet";
|
||||
+ status = "disabled";
|
||||
+ reg = <0x0 0x17020000 0x0 0xd100>,
|
||||
+ <0x0 0X17030000 0x0 0X400>,
|
||||
+ <0x0 0X10000000 0x0 0X200>;
|
||||
+ reg-names = "enet_csr", "ring_csr", "ring_cmd";
|
||||
+ interrupts = <0x0 0x3c 0x4>;
|
||||
+ dma-coherent;
|
||||
+ clocks = <&menetclk 0>;
|
||||
+ local-mac-address = [00 01 73 00 00 01];
|
||||
+ phy-connection-type = "rgmii";
|
||||
+ phy-handle = <&menetphy>;
|
||||
+ mdio {
|
||||
+ compatible = "apm,xgene-mdio";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ menetphy: menetphy@3 {
|
||||
+ compatible = "ethernet-phy-id001c.c915";
|
||||
+ reg = <0x3>;
|
||||
+ };
|
||||
+
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
};
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
From 42113901e335c5431e11e33711f5cdcc8e033955 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Klauser <tklauser@distanz.ch>
|
||||
Date: Thu, 14 Aug 2014 13:59:42 +0200
|
||||
Subject: [PATCH 2/4] net: xgene: Check negative return value of
|
||||
xgene_enet_get_ring_size()
|
||||
|
||||
xgene_enet_get_ring_size() returns a negative value in case of an error,
|
||||
but its only caller in xgene_enet_create_desc_ring() currently uses the
|
||||
return value directly as u32. Instead, check for a negative value first and
|
||||
error out in case. Also move the call to xgene_enet_get_ring_size() before
|
||||
devm_kzalloc() so we don't need to free anything in the error path.
|
||||
|
||||
This fixes the following issue reported by the Coverity Scanner:
|
||||
|
||||
** CID 1231336: Improper use of negative value (NEGATIVE_RETURNS)
|
||||
/drivers/net/ethernet/apm/xgene/xgene_enet_main.c: 596 in xgene_enet_create_desc_ring()
|
||||
|
||||
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
index af7c40a..e1a8f4e 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
@@ -581,7 +581,11 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
|
||||
struct xgene_enet_desc_ring *ring;
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||
struct device *dev = ndev_to_dev(ndev);
|
||||
- u32 size;
|
||||
+ int size;
|
||||
+
|
||||
+ size = xgene_enet_get_ring_size(dev, cfgsize);
|
||||
+ if (size < 0)
|
||||
+ return NULL;
|
||||
|
||||
ring = devm_kzalloc(dev, sizeof(struct xgene_enet_desc_ring),
|
||||
GFP_KERNEL);
|
||||
@@ -593,7 +597,6 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
|
||||
ring->cfgsize = cfgsize;
|
||||
ring->id = ring_id;
|
||||
|
||||
- size = xgene_enet_get_ring_size(dev, cfgsize);
|
||||
ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma,
|
||||
GFP_KERNEL);
|
||||
if (!ring->desc_addr) {
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
From c04bbc2b1df7034f463ef512c34010b71c12c257 Mon Sep 17 00:00:00 2001
|
||||
From: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Date: Thu, 21 Aug 2014 13:44:48 -0700
|
||||
Subject: [PATCH 3/4] net: xgene: fix possible NULL dereference in
|
||||
xgene_enet_free_desc_rings()
|
||||
|
||||
A NULL pointer dereference is possible for the argument ring->buf_pool
|
||||
which is passed to xgene_enet_free_desc_ring(), as ring could be NULL.
|
||||
|
||||
And now since NULL pointers are being checked for before the calls to
|
||||
xgene_enet_free_desc_ring(), might as well take advantage of them and
|
||||
not call the function if the argument would be NULL.
|
||||
|
||||
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 20 +++++++++++++-------
|
||||
1 file changed, 13 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
index e1a8f4e..e4222af 100644
|
||||
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
|
||||
@@ -563,15 +563,21 @@ static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
|
||||
struct xgene_enet_desc_ring *ring;
|
||||
|
||||
ring = pdata->tx_ring;
|
||||
- if (ring && ring->cp_ring && ring->cp_ring->cp_skb)
|
||||
- devm_kfree(dev, ring->cp_ring->cp_skb);
|
||||
- xgene_enet_free_desc_ring(ring);
|
||||
+ if (ring) {
|
||||
+ if (ring->cp_ring && ring->cp_ring->cp_skb)
|
||||
+ devm_kfree(dev, ring->cp_ring->cp_skb);
|
||||
+ xgene_enet_free_desc_ring(ring);
|
||||
+ }
|
||||
|
||||
ring = pdata->rx_ring;
|
||||
- if (ring && ring->buf_pool && ring->buf_pool->rx_skb)
|
||||
- devm_kfree(dev, ring->buf_pool->rx_skb);
|
||||
- xgene_enet_free_desc_ring(ring->buf_pool);
|
||||
- xgene_enet_free_desc_ring(ring);
|
||||
+ if (ring) {
|
||||
+ if (ring->buf_pool) {
|
||||
+ if (ring->buf_pool->rx_skb)
|
||||
+ devm_kfree(dev, ring->buf_pool->rx_skb);
|
||||
+ xgene_enet_free_desc_ring(ring->buf_pool);
|
||||
+ }
|
||||
+ xgene_enet_free_desc_ring(ring);
|
||||
+ }
|
||||
}
|
||||
|
||||
static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,725 +0,0 @@
|
|||
From: Huacai Chen <chenhc@lemote.com>
|
||||
Date: Thu, 26 Jun 2014 11:41:30 +0800
|
||||
Subject: [6/8] MIPS: Add Loongson-3B support
|
||||
Origin: https://git.kernel.org/linus/e7841be50fe2b8751a51a068b8cdcdcb6611e354
|
||||
|
||||
Loongson-3B is a 8-cores processor. In general it looks like there are
|
||||
two Loongson-3A integrated in one chip: 8 cores are separated into two
|
||||
groups (two NUMA node), each node has its own local memory.
|
||||
|
||||
Of course there are some differences between one Loongson-3B and two
|
||||
Loongson-3A. E.g., the base addresses of IPI registers of each node are
|
||||
not the same; Loongson-3A use ChipConfig register to enable/disable
|
||||
clock, but Loongson-3B use FreqControl register instead.
|
||||
|
||||
There are two revision of Loongson-3B, the first revision is called as
|
||||
Loongson-3B1000, whose frequency is 1GHz and has a PRid 0x6306, the
|
||||
second revision is called as Loongson-3B1500, whose frequency is 1.5GHz
|
||||
and has a PRid 0x6307. Both revisions has a bug that clock cannot be
|
||||
disabled at runtime, but this will be fixed in future.
|
||||
|
||||
Signed-off-by: Huacai Chen <chenhc@lemote.com>
|
||||
Cc: John Crispin <john@phrozen.org>
|
||||
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
|
||||
Cc: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Cc: Fuxin Zhang <zhangfx@lemote.com>
|
||||
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/7188/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/include/asm/cpu.h | 2 +
|
||||
arch/mips/include/asm/mach-loongson/boot_param.h | 1 +
|
||||
arch/mips/include/asm/mach-loongson/loongson.h | 4 +
|
||||
arch/mips/kernel/cpu-probe.c | 6 +
|
||||
arch/mips/loongson/common/env.c | 31 +-
|
||||
arch/mips/loongson/loongson-3/irq.c | 26 +-
|
||||
arch/mips/loongson/loongson-3/smp.c | 387 ++++++++++++++++------
|
||||
arch/mips/loongson/loongson-3/smp.h | 37 ++-
|
||||
8 files changed, 372 insertions(+), 122 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
|
||||
index 129d087..abf7e00 100644
|
||||
--- a/arch/mips/include/asm/cpu.h
|
||||
+++ b/arch/mips/include/asm/cpu.h
|
||||
@@ -233,6 +233,8 @@
|
||||
#define PRID_REV_LOONGSON2E 0x0002
|
||||
#define PRID_REV_LOONGSON2F 0x0003
|
||||
#define PRID_REV_LOONGSON3A 0x0005
|
||||
+#define PRID_REV_LOONGSON3B_R1 0x0006
|
||||
+#define PRID_REV_LOONGSON3B_R2 0x0007
|
||||
|
||||
/*
|
||||
* Older processors used to encode processor version and revision in two
|
||||
diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
|
||||
index 8b06c96..3388fc5 100644
|
||||
--- a/arch/mips/include/asm/mach-loongson/boot_param.h
|
||||
+++ b/arch/mips/include/asm/mach-loongson/boot_param.h
|
||||
@@ -163,4 +163,5 @@ struct loongson_system_configuration {
|
||||
|
||||
extern struct efi_memory_map_loongson *loongson_memmap;
|
||||
extern struct loongson_system_configuration loongson_sysconf;
|
||||
+extern int cpuhotplug_workaround;
|
||||
#endif
|
||||
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
|
||||
index a1c76ca..92bf76c 100644
|
||||
--- a/arch/mips/include/asm/mach-loongson/loongson.h
|
||||
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
|
||||
@@ -255,6 +255,10 @@ static inline void do_perfcnt_IRQ(void)
|
||||
extern u64 loongson_chipcfg[MAX_PACKAGES];
|
||||
#define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id]))
|
||||
|
||||
+/* Freq Control register of each physical cpu package, PRid >= Loongson-3B */
|
||||
+extern u64 loongson_freqctrl[MAX_PACKAGES];
|
||||
+#define LOONGSON_FREQCTRL(id) (*(volatile u32 *)(loongson_freqctrl[id]))
|
||||
+
|
||||
/* pcimap */
|
||||
|
||||
#define LOONGSON_PCIMAP_PCIMAP_LO0 0x0000003f
|
||||
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
|
||||
index d74f957..2d2e287 100644
|
||||
--- a/arch/mips/kernel/cpu-probe.c
|
||||
+++ b/arch/mips/kernel/cpu-probe.c
|
||||
@@ -740,6 +740,12 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
|
||||
__cpu_name[cpu] = "ICT Loongson-3";
|
||||
set_elf_platform(cpu, "loongson3a");
|
||||
break;
|
||||
+ case PRID_REV_LOONGSON3B_R1:
|
||||
+ case PRID_REV_LOONGSON3B_R2:
|
||||
+ c->cputype = CPU_LOONGSON3;
|
||||
+ __cpu_name[cpu] = "ICT Loongson-3";
|
||||
+ set_elf_platform(cpu, "loongson3b");
|
||||
+ break;
|
||||
}
|
||||
|
||||
set_isa(c, MIPS_CPU_ISA_III);
|
||||
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
|
||||
index 33a13b9..f152285 100644
|
||||
--- a/arch/mips/loongson/common/env.c
|
||||
+++ b/arch/mips/loongson/common/env.c
|
||||
@@ -28,6 +28,10 @@ struct efi_memory_map_loongson *loongson_memmap;
|
||||
struct loongson_system_configuration loongson_sysconf;
|
||||
|
||||
u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
|
||||
+u64 loongson_freqctrl[MAX_PACKAGES];
|
||||
+
|
||||
+unsigned long long smp_group[4];
|
||||
+int cpuhotplug_workaround = 0;
|
||||
|
||||
#define parse_even_earlier(res, option, p) \
|
||||
do { \
|
||||
@@ -82,10 +86,32 @@ void __init prom_init_env(void)
|
||||
if (ecpu->cputype == Loongson_3A) {
|
||||
loongson_sysconf.cores_per_node = 4;
|
||||
loongson_sysconf.cores_per_package = 4;
|
||||
+ smp_group[0] = 0x900000003ff01000;
|
||||
+ smp_group[1] = 0x900010003ff01000;
|
||||
+ smp_group[2] = 0x900020003ff01000;
|
||||
+ smp_group[3] = 0x900030003ff01000;
|
||||
loongson_chipcfg[0] = 0x900000001fe00180;
|
||||
loongson_chipcfg[1] = 0x900010001fe00180;
|
||||
loongson_chipcfg[2] = 0x900020001fe00180;
|
||||
loongson_chipcfg[3] = 0x900030001fe00180;
|
||||
+ loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
|
||||
+ } else if (ecpu->cputype == Loongson_3B) {
|
||||
+ loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */
|
||||
+ loongson_sysconf.cores_per_package = 8;
|
||||
+ smp_group[0] = 0x900000003ff01000;
|
||||
+ smp_group[1] = 0x900010003ff05000;
|
||||
+ smp_group[2] = 0x900020003ff09000;
|
||||
+ smp_group[3] = 0x900030003ff0d000;
|
||||
+ loongson_chipcfg[0] = 0x900000001fe00180;
|
||||
+ loongson_chipcfg[1] = 0x900020001fe00180;
|
||||
+ loongson_chipcfg[2] = 0x900040001fe00180;
|
||||
+ loongson_chipcfg[3] = 0x900060001fe00180;
|
||||
+ loongson_freqctrl[0] = 0x900000001fe001d0;
|
||||
+ loongson_freqctrl[1] = 0x900020001fe001d0;
|
||||
+ loongson_freqctrl[2] = 0x900040001fe001d0;
|
||||
+ loongson_freqctrl[3] = 0x900060001fe001d0;
|
||||
+ loongson_sysconf.ht_control_base = 0x90001EFDFB000000;
|
||||
+ cpuhotplug_workaround = 1;
|
||||
} else {
|
||||
loongson_sysconf.cores_per_node = 1;
|
||||
loongson_sysconf.cores_per_package = 1;
|
||||
@@ -111,7 +137,6 @@ void __init prom_init_env(void)
|
||||
loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
|
||||
loongson_sysconf.suspend_addr = boot_p->reset_system.DoSuspend;
|
||||
|
||||
- loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
|
||||
loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
|
||||
pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
|
||||
loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
|
||||
@@ -129,6 +154,10 @@ void __init prom_init_env(void)
|
||||
case PRID_REV_LOONGSON3A:
|
||||
cpu_clock_freq = 900000000;
|
||||
break;
|
||||
+ case PRID_REV_LOONGSON3B_R1:
|
||||
+ case PRID_REV_LOONGSON3B_R2:
|
||||
+ cpu_clock_freq = 1000000000;
|
||||
+ break;
|
||||
default:
|
||||
cpu_clock_freq = 100000000;
|
||||
break;
|
||||
diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
|
||||
index f240828..ca1c62a 100644
|
||||
--- a/arch/mips/loongson/loongson-3/irq.c
|
||||
+++ b/arch/mips/loongson/loongson-3/irq.c
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <asm/i8259.h>
|
||||
#include <asm/mipsregs.h>
|
||||
|
||||
+#include "smp.h"
|
||||
+
|
||||
unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
|
||||
|
||||
static void ht_irqdispatch(void)
|
||||
@@ -53,9 +55,15 @@ static inline void mask_loongson_irq(struct irq_data *d)
|
||||
/* Workaround: UART IRQ may deliver to any core */
|
||||
if (d->irq == LOONGSON_UART_IRQ) {
|
||||
int cpu = smp_processor_id();
|
||||
-
|
||||
- LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
|
||||
- LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
|
||||
+ int node_id = cpu / loongson_sysconf.cores_per_node;
|
||||
+ int core_id = cpu % loongson_sysconf.cores_per_node;
|
||||
+ u64 intenclr_addr = smp_group[node_id] |
|
||||
+ (u64)(&LOONGSON_INT_ROUTER_INTENCLR);
|
||||
+ u64 introuter_lpc_addr = smp_group[node_id] |
|
||||
+ (u64)(&LOONGSON_INT_ROUTER_LPC);
|
||||
+
|
||||
+ *(volatile u32 *)intenclr_addr = 1 << 10;
|
||||
+ *(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,9 +72,15 @@ static inline void unmask_loongson_irq(struct irq_data *d)
|
||||
/* Workaround: UART IRQ may deliver to any core */
|
||||
if (d->irq == LOONGSON_UART_IRQ) {
|
||||
int cpu = smp_processor_id();
|
||||
-
|
||||
- LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
|
||||
- LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
|
||||
+ int node_id = cpu / loongson_sysconf.cores_per_node;
|
||||
+ int core_id = cpu % loongson_sysconf.cores_per_node;
|
||||
+ u64 intenset_addr = smp_group[node_id] |
|
||||
+ (u64)(&LOONGSON_INT_ROUTER_INTENSET);
|
||||
+ u64 introuter_lpc_addr = smp_group[node_id] |
|
||||
+ (u64)(&LOONGSON_INT_ROUTER_LPC);
|
||||
+
|
||||
+ *(volatile u32 *)intenset_addr = 1 << 10;
|
||||
+ *(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
|
||||
}
|
||||
|
||||
set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
|
||||
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
|
||||
index ed0e2d0..74e827b 100644
|
||||
--- a/arch/mips/loongson/loongson-3/smp.c
|
||||
+++ b/arch/mips/loongson/loongson-3/smp.c
|
||||
@@ -31,6 +31,12 @@
|
||||
DEFINE_PER_CPU(int, cpu_state);
|
||||
DEFINE_PER_CPU(uint32_t, core0_c0count);
|
||||
|
||||
+static void *ipi_set0_regs[16];
|
||||
+static void *ipi_clear0_regs[16];
|
||||
+static void *ipi_status0_regs[16];
|
||||
+static void *ipi_en0_regs[16];
|
||||
+static void *ipi_mailbox_buf[16];
|
||||
+
|
||||
/* read a 32bit value from ipi register */
|
||||
#define loongson3_ipi_read32(addr) readl(addr)
|
||||
/* read a 64bit value from ipi register */
|
||||
@@ -48,100 +54,185 @@ DEFINE_PER_CPU(uint32_t, core0_c0count);
|
||||
__wbflush(); \
|
||||
} while (0)
|
||||
|
||||
-static void *ipi_set0_regs[] = {
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0),
|
||||
-};
|
||||
+static void ipi_set0_regs_init(void)
|
||||
+{
|
||||
+ ipi_set0_regs[0] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0);
|
||||
+ ipi_set0_regs[1] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0);
|
||||
+ ipi_set0_regs[2] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0);
|
||||
+ ipi_set0_regs[3] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0);
|
||||
+ ipi_set0_regs[4] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0);
|
||||
+ ipi_set0_regs[5] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0);
|
||||
+ ipi_set0_regs[6] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0);
|
||||
+ ipi_set0_regs[7] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0);
|
||||
+ ipi_set0_regs[8] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0);
|
||||
+ ipi_set0_regs[9] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0);
|
||||
+ ipi_set0_regs[10] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0);
|
||||
+ ipi_set0_regs[11] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0);
|
||||
+ ipi_set0_regs[12] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0);
|
||||
+ ipi_set0_regs[13] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0);
|
||||
+ ipi_set0_regs[14] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0);
|
||||
+ ipi_set0_regs[15] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0);
|
||||
+}
|
||||
|
||||
-static void *ipi_clear0_regs[] = {
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0),
|
||||
-};
|
||||
+static void ipi_clear0_regs_init(void)
|
||||
+{
|
||||
+ ipi_clear0_regs[0] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[1] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[2] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[3] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[4] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[5] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[6] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[7] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[8] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[9] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[10] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[11] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[12] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[13] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[14] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0);
|
||||
+ ipi_clear0_regs[15] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0);
|
||||
+}
|
||||
|
||||
-static void *ipi_status0_regs[] = {
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0),
|
||||
-};
|
||||
+static void ipi_status0_regs_init(void)
|
||||
+{
|
||||
+ ipi_status0_regs[0] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[1] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[2] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[3] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[4] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[5] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[6] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[7] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[8] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[9] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[10] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[11] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[12] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[13] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[14] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0);
|
||||
+ ipi_status0_regs[15] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0);
|
||||
+}
|
||||
|
||||
-static void *ipi_en0_regs[] = {
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0),
|
||||
-};
|
||||
+static void ipi_en0_regs_init(void)
|
||||
+{
|
||||
+ ipi_en0_regs[0] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0);
|
||||
+ ipi_en0_regs[1] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0);
|
||||
+ ipi_en0_regs[2] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0);
|
||||
+ ipi_en0_regs[3] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0);
|
||||
+ ipi_en0_regs[4] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0);
|
||||
+ ipi_en0_regs[5] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0);
|
||||
+ ipi_en0_regs[6] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0);
|
||||
+ ipi_en0_regs[7] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0);
|
||||
+ ipi_en0_regs[8] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0);
|
||||
+ ipi_en0_regs[9] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0);
|
||||
+ ipi_en0_regs[10] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0);
|
||||
+ ipi_en0_regs[11] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0);
|
||||
+ ipi_en0_regs[12] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0);
|
||||
+ ipi_en0_regs[13] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0);
|
||||
+ ipi_en0_regs[14] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0);
|
||||
+ ipi_en0_regs[15] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0);
|
||||
+}
|
||||
|
||||
-static void *ipi_mailbox_buf[] = {
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF),
|
||||
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF),
|
||||
-};
|
||||
+static void ipi_mailbox_buf_init(void)
|
||||
+{
|
||||
+ ipi_mailbox_buf[0] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[1] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[2] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[3] = (void *)
|
||||
+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[4] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[5] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[6] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[7] = (void *)
|
||||
+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[8] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[9] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[10] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[11] = (void *)
|
||||
+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[12] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[13] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[14] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF);
|
||||
+ ipi_mailbox_buf[15] = (void *)
|
||||
+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF);
|
||||
+}
|
||||
|
||||
/*
|
||||
* Simple enough, just poke the appropriate ipi register
|
||||
@@ -248,6 +339,11 @@ static void __init loongson3_smp_setup(void)
|
||||
__cpu_number_map[i] = ++num;
|
||||
__cpu_logical_map[num] = i;
|
||||
}
|
||||
+ ipi_set0_regs_init();
|
||||
+ ipi_clear0_regs_init();
|
||||
+ ipi_status0_regs_init();
|
||||
+ ipi_en0_regs_init();
|
||||
+ ipi_mailbox_buf_init();
|
||||
pr_info("Detected %i available secondary CPU(s)\n", num);
|
||||
}
|
||||
|
||||
@@ -315,7 +411,7 @@ static void loongson3_cpu_die(unsigned int cpu)
|
||||
* flush all L1 entries at first. Then, another core (usually Core 0) can
|
||||
* safely disable the clock of the target core. loongson3_play_dead() is
|
||||
* called via CKSEG1 (uncached and unmmaped) */
|
||||
-static void loongson3_play_dead(int *state_addr)
|
||||
+static void loongson3a_play_dead(int *state_addr)
|
||||
{
|
||||
register int val;
|
||||
register long cpuid, core, node, count;
|
||||
@@ -377,6 +473,70 @@ static void loongson3_play_dead(int *state_addr)
|
||||
: "a1");
|
||||
}
|
||||
|
||||
+static void loongson3b_play_dead(int *state_addr)
|
||||
+{
|
||||
+ register int val;
|
||||
+ register long cpuid, core, node, count;
|
||||
+ register void *addr, *base, *initfunc;
|
||||
+
|
||||
+ __asm__ __volatile__(
|
||||
+ " .set push \n"
|
||||
+ " .set noreorder \n"
|
||||
+ " li %[addr], 0x80000000 \n" /* KSEG0 */
|
||||
+ "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */
|
||||
+ " cache 0, 1(%[addr]) \n"
|
||||
+ " cache 0, 2(%[addr]) \n"
|
||||
+ " cache 0, 3(%[addr]) \n"
|
||||
+ " cache 1, 0(%[addr]) \n" /* flush L1 DCache */
|
||||
+ " cache 1, 1(%[addr]) \n"
|
||||
+ " cache 1, 2(%[addr]) \n"
|
||||
+ " cache 1, 3(%[addr]) \n"
|
||||
+ " addiu %[sets], %[sets], -1 \n"
|
||||
+ " bnez %[sets], 1b \n"
|
||||
+ " addiu %[addr], %[addr], 0x20 \n"
|
||||
+ " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
|
||||
+ " sw %[val], (%[state_addr]) \n"
|
||||
+ " sync \n"
|
||||
+ " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */
|
||||
+ " .set pop \n"
|
||||
+ : [addr] "=&r" (addr), [val] "=&r" (val)
|
||||
+ : [state_addr] "r" (state_addr),
|
||||
+ [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
|
||||
+
|
||||
+ __asm__ __volatile__(
|
||||
+ " .set push \n"
|
||||
+ " .set noreorder \n"
|
||||
+ " .set mips64 \n"
|
||||
+ " mfc0 %[cpuid], $15, 1 \n"
|
||||
+ " andi %[cpuid], 0x3ff \n"
|
||||
+ " dli %[base], 0x900000003ff01000 \n"
|
||||
+ " andi %[core], %[cpuid], 0x3 \n"
|
||||
+ " sll %[core], 8 \n" /* get core id */
|
||||
+ " or %[base], %[base], %[core] \n"
|
||||
+ " andi %[node], %[cpuid], 0xc \n"
|
||||
+ " dsll %[node], 42 \n" /* get node id */
|
||||
+ " or %[base], %[base], %[node] \n"
|
||||
+ " dsrl %[node], 30 \n" /* 15:14 */
|
||||
+ " or %[base], %[base], %[node] \n"
|
||||
+ "1: li %[count], 0x100 \n" /* wait for init loop */
|
||||
+ "2: bnez %[count], 2b \n" /* limit mailbox access */
|
||||
+ " addiu %[count], -1 \n"
|
||||
+ " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */
|
||||
+ " beqz %[initfunc], 1b \n"
|
||||
+ " nop \n"
|
||||
+ " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */
|
||||
+ " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */
|
||||
+ " ld $a1, 0x38(%[base]) \n"
|
||||
+ " jr %[initfunc] \n" /* jump to initial PC */
|
||||
+ " nop \n"
|
||||
+ " .set pop \n"
|
||||
+ : [core] "=&r" (core), [node] "=&r" (node),
|
||||
+ [base] "=&r" (base), [cpuid] "=&r" (cpuid),
|
||||
+ [count] "=&r" (count), [initfunc] "=&r" (initfunc)
|
||||
+ : /* No Input */
|
||||
+ : "a1");
|
||||
+}
|
||||
+
|
||||
void play_dead(void)
|
||||
{
|
||||
int *state_addr;
|
||||
@@ -384,31 +544,64 @@ void play_dead(void)
|
||||
void (*play_dead_at_ckseg1)(int *);
|
||||
|
||||
idle_task_exit();
|
||||
- play_dead_at_ckseg1 =
|
||||
- (void *)CKSEG1ADDR((unsigned long)loongson3_play_dead);
|
||||
+ switch (loongson_sysconf.cputype) {
|
||||
+ case Loongson_3A:
|
||||
+ default:
|
||||
+ play_dead_at_ckseg1 =
|
||||
+ (void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead);
|
||||
+ break;
|
||||
+ case Loongson_3B:
|
||||
+ play_dead_at_ckseg1 =
|
||||
+ (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
|
||||
+ break;
|
||||
+ }
|
||||
state_addr = &per_cpu(cpu_state, cpu);
|
||||
mb();
|
||||
play_dead_at_ckseg1(state_addr);
|
||||
}
|
||||
|
||||
+void loongson3_disable_clock(int cpu)
|
||||
+{
|
||||
+ uint64_t core_id = cpu_data[cpu].core;
|
||||
+ uint64_t package_id = cpu_data[cpu].package;
|
||||
+
|
||||
+ if (loongson_sysconf.cputype == Loongson_3A) {
|
||||
+ LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
|
||||
+ } else if (loongson_sysconf.cputype == Loongson_3B) {
|
||||
+ if (!cpuhotplug_workaround)
|
||||
+ LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void loongson3_enable_clock(int cpu)
|
||||
+{
|
||||
+ uint64_t core_id = cpu_data[cpu].core;
|
||||
+ uint64_t package_id = cpu_data[cpu].package;
|
||||
+
|
||||
+ if (loongson_sysconf.cputype == Loongson_3A) {
|
||||
+ LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
|
||||
+ } else if (loongson_sysconf.cputype == Loongson_3B) {
|
||||
+ if (!cpuhotplug_workaround)
|
||||
+ LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#define CPU_POST_DEAD_FROZEN (CPU_POST_DEAD | CPU_TASKS_FROZEN)
|
||||
static int loongson3_cpu_callback(struct notifier_block *nfb,
|
||||
unsigned long action, void *hcpu)
|
||||
{
|
||||
unsigned int cpu = (unsigned long)hcpu;
|
||||
- uint64_t core_id = cpu_data[cpu].core;
|
||||
- uint64_t package_id = cpu_data[cpu].package;
|
||||
|
||||
switch (action) {
|
||||
case CPU_POST_DEAD:
|
||||
case CPU_POST_DEAD_FROZEN:
|
||||
pr_info("Disable clock for CPU#%d\n", cpu);
|
||||
- LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
|
||||
+ loongson3_disable_clock(cpu);
|
||||
break;
|
||||
case CPU_UP_PREPARE:
|
||||
case CPU_UP_PREPARE_FROZEN:
|
||||
pr_info("Enable clock for CPU#%d\n", cpu);
|
||||
- LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
|
||||
+ loongson3_enable_clock(cpu);
|
||||
break;
|
||||
}
|
||||
|
||||
diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson/loongson-3/smp.h
|
||||
index 3453e8c..d98ff65 100644
|
||||
--- a/arch/mips/loongson/loongson-3/smp.h
|
||||
+++ b/arch/mips/loongson/loongson-3/smp.h
|
||||
@@ -1,29 +1,30 @@
|
||||
#ifndef __LOONGSON_SMP_H_
|
||||
#define __LOONGSON_SMP_H_
|
||||
|
||||
-/* for Loongson-3A smp support */
|
||||
+/* for Loongson-3 smp support */
|
||||
+extern unsigned long long smp_group[4];
|
||||
|
||||
/* 4 groups(nodes) in maximum in numa case */
|
||||
-#define SMP_CORE_GROUP0_BASE 0x900000003ff01000
|
||||
-#define SMP_CORE_GROUP1_BASE 0x900010003ff01000
|
||||
-#define SMP_CORE_GROUP2_BASE 0x900020003ff01000
|
||||
-#define SMP_CORE_GROUP3_BASE 0x900030003ff01000
|
||||
+#define SMP_CORE_GROUP0_BASE (smp_group[0])
|
||||
+#define SMP_CORE_GROUP1_BASE (smp_group[1])
|
||||
+#define SMP_CORE_GROUP2_BASE (smp_group[2])
|
||||
+#define SMP_CORE_GROUP3_BASE (smp_group[3])
|
||||
|
||||
/* 4 cores in each group(node) */
|
||||
-#define SMP_CORE0_OFFSET 0x000
|
||||
-#define SMP_CORE1_OFFSET 0x100
|
||||
-#define SMP_CORE2_OFFSET 0x200
|
||||
-#define SMP_CORE3_OFFSET 0x300
|
||||
+#define SMP_CORE0_OFFSET 0x000
|
||||
+#define SMP_CORE1_OFFSET 0x100
|
||||
+#define SMP_CORE2_OFFSET 0x200
|
||||
+#define SMP_CORE3_OFFSET 0x300
|
||||
|
||||
/* ipi registers offsets */
|
||||
-#define STATUS0 0x00
|
||||
-#define EN0 0x04
|
||||
-#define SET0 0x08
|
||||
-#define CLEAR0 0x0c
|
||||
-#define STATUS1 0x10
|
||||
-#define MASK1 0x14
|
||||
-#define SET1 0x18
|
||||
-#define CLEAR1 0x1c
|
||||
-#define BUF 0x20
|
||||
+#define STATUS0 0x00
|
||||
+#define EN0 0x04
|
||||
+#define SET0 0x08
|
||||
+#define CLEAR0 0x0c
|
||||
+#define STATUS1 0x10
|
||||
+#define MASK1 0x14
|
||||
+#define SET1 0x18
|
||||
+#define CLEAR1 0x1c
|
||||
+#define BUF 0x20
|
||||
|
||||
#endif
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,651 +0,0 @@
|
|||
From: Huacai Chen <chenhc@lemote.com>
|
||||
Date: Thu, 26 Jun 2014 11:41:28 +0800
|
||||
Subject: [4/8] MIPS: Add NUMA support for Loongson-3
|
||||
Origin: https://git.kernel.org/linus/c46173183657bbdbe0d54a981c28807581648422
|
||||
|
||||
Multiple Loongson-3A chips can be interconnected with HT0-bus. This is
|
||||
a CC-NUMA system that every chip (node) has its own local memory and
|
||||
cache coherency is maintained by hardware. The 64-bit physical memory
|
||||
address format is as follows:
|
||||
|
||||
0x-0000-YZZZ-ZZZZ-ZZZZ
|
||||
|
||||
The high 16 bits should be 0, which means the real physical address
|
||||
supported by Loongson-3 is 48-bit. The "Y" bits is the base address of
|
||||
each node, which can be also considered as the node-id. The "Z" bits is
|
||||
the address offset within a node, which means every node has a 44 bits
|
||||
address space.
|
||||
|
||||
Macros XPHYSADDR and MAX_PHYSMEM_BITS are modified unconditionally,
|
||||
because many other MIPS CPUs have also extended their address spaces.
|
||||
|
||||
Signed-off-by: Huacai Chen <chenhc@lemote.com>
|
||||
Cc: John Crispin <john@phrozen.org>
|
||||
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
|
||||
Cc: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Cc: Fuxin Zhang <zhangfx@lemote.com>
|
||||
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/7187/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/include/asm/addrspace.h | 2 +-
|
||||
arch/mips/include/asm/mach-loongson/boot_param.h | 3 +
|
||||
.../include/asm/mach-loongson/kernel-entry-init.h | 52 ++++
|
||||
arch/mips/include/asm/mach-loongson/mmzone.h | 53 ++++
|
||||
arch/mips/include/asm/mach-loongson/topology.h | 23 ++
|
||||
arch/mips/include/asm/sparsemem.h | 2 +-
|
||||
arch/mips/kernel/setup.c | 2 +-
|
||||
arch/mips/loongson/Kconfig | 1 +
|
||||
arch/mips/loongson/common/env.c | 7 +
|
||||
arch/mips/loongson/common/init.c | 4 +
|
||||
arch/mips/loongson/loongson-3/Makefile | 2 +
|
||||
arch/mips/loongson/loongson-3/numa.c | 291 ++++++++++++++++++++
|
||||
arch/mips/loongson/loongson-3/smp.c | 8 +-
|
||||
13 files changed, 445 insertions(+), 5 deletions(-)
|
||||
create mode 100644 arch/mips/include/asm/mach-loongson/kernel-entry-init.h
|
||||
create mode 100644 arch/mips/include/asm/mach-loongson/mmzone.h
|
||||
create mode 100644 arch/mips/include/asm/mach-loongson/topology.h
|
||||
create mode 100644 arch/mips/loongson/loongson-3/numa.c
|
||||
|
||||
diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h
|
||||
index 3f74545..3b0e51d 100644
|
||||
--- a/arch/mips/include/asm/addrspace.h
|
||||
+++ b/arch/mips/include/asm/addrspace.h
|
||||
@@ -52,7 +52,7 @@
|
||||
*/
|
||||
#define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff)
|
||||
#define XPHYSADDR(a) ((_ACAST64_(a)) & \
|
||||
- _CONST64_(0x000000ffffffffff))
|
||||
+ _CONST64_(0x0000ffffffffffff))
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
|
||||
diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
|
||||
index 829a7ec..8b06c96 100644
|
||||
--- a/arch/mips/include/asm/mach-loongson/boot_param.h
|
||||
+++ b/arch/mips/include/asm/mach-loongson/boot_param.h
|
||||
@@ -146,6 +146,9 @@ struct boot_params {
|
||||
|
||||
struct loongson_system_configuration {
|
||||
u32 nr_cpus;
|
||||
+ u32 nr_nodes;
|
||||
+ int cores_per_node;
|
||||
+ int cores_per_package;
|
||||
enum loongson_cpu_type cputype;
|
||||
u64 ht_control_base;
|
||||
u64 pci_mem_start_addr;
|
||||
diff --git a/arch/mips/include/asm/mach-loongson/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson/kernel-entry-init.h
|
||||
new file mode 100644
|
||||
index 0000000..df5fca8
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/include/asm/mach-loongson/kernel-entry-init.h
|
||||
@@ -0,0 +1,52 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2005 Embedded Alley Solutions, Inc
|
||||
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
|
||||
+ * Copyright (C) 2009 Jiajie Chen (chenjiajie@cse.buaa.edu.cn)
|
||||
+ * Copyright (C) 2012 Huacai Chen (chenhc@lemote.com)
|
||||
+ */
|
||||
+#ifndef __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
|
||||
+#define __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
|
||||
+
|
||||
+/*
|
||||
+ * Override macros used in arch/mips/kernel/head.S.
|
||||
+ */
|
||||
+ .macro kernel_entry_setup
|
||||
+#ifdef CONFIG_CPU_LOONGSON3
|
||||
+ .set push
|
||||
+ .set mips64
|
||||
+ /* Set LPA on LOONGSON3 config3 */
|
||||
+ mfc0 t0, $16, 3
|
||||
+ or t0, (0x1 << 7)
|
||||
+ mtc0 t0, $16, 3
|
||||
+ /* Set ELPA on LOONGSON3 pagegrain */
|
||||
+ li t0, (0x1 << 29)
|
||||
+ mtc0 t0, $5, 1
|
||||
+ _ehb
|
||||
+ .set pop
|
||||
+#endif
|
||||
+ .endm
|
||||
+
|
||||
+/*
|
||||
+ * Do SMP slave processor setup.
|
||||
+ */
|
||||
+ .macro smp_slave_setup
|
||||
+#ifdef CONFIG_CPU_LOONGSON3
|
||||
+ .set push
|
||||
+ .set mips64
|
||||
+ /* Set LPA on LOONGSON3 config3 */
|
||||
+ mfc0 t0, $16, 3
|
||||
+ or t0, (0x1 << 7)
|
||||
+ mtc0 t0, $16, 3
|
||||
+ /* Set ELPA on LOONGSON3 pagegrain */
|
||||
+ li t0, (0x1 << 29)
|
||||
+ mtc0 t0, $5, 1
|
||||
+ _ehb
|
||||
+ .set pop
|
||||
+#endif
|
||||
+ .endm
|
||||
+
|
||||
+#endif /* __ASM_MACH_LOONGSON_KERNEL_ENTRY_H */
|
||||
diff --git a/arch/mips/include/asm/mach-loongson/mmzone.h b/arch/mips/include/asm/mach-loongson/mmzone.h
|
||||
new file mode 100644
|
||||
index 0000000..37c08a2
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/include/asm/mach-loongson/mmzone.h
|
||||
@@ -0,0 +1,53 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
|
||||
+ * Insititute of Computing Technology
|
||||
+ * Author: Xiang Gao, gaoxiang@ict.ac.cn
|
||||
+ * Huacai Chen, chenhc@lemote.com
|
||||
+ * Xiaofu Meng, Shuangshuang Zhang
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ */
|
||||
+#ifndef _ASM_MACH_MMZONE_H
|
||||
+#define _ASM_MACH_MMZONE_H
|
||||
+
|
||||
+#include <boot_param.h>
|
||||
+#define NODE_ADDRSPACE_SHIFT 44
|
||||
+#define NODE0_ADDRSPACE_OFFSET 0x000000000000UL
|
||||
+#define NODE1_ADDRSPACE_OFFSET 0x100000000000UL
|
||||
+#define NODE2_ADDRSPACE_OFFSET 0x200000000000UL
|
||||
+#define NODE3_ADDRSPACE_OFFSET 0x300000000000UL
|
||||
+
|
||||
+#define pa_to_nid(addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT)
|
||||
+
|
||||
+#define LEVELS_PER_SLICE 128
|
||||
+
|
||||
+struct slice_data {
|
||||
+ unsigned long irq_enable_mask[2];
|
||||
+ int level_to_irq[LEVELS_PER_SLICE];
|
||||
+};
|
||||
+
|
||||
+struct hub_data {
|
||||
+ cpumask_t h_cpus;
|
||||
+ unsigned long slice_map;
|
||||
+ unsigned long irq_alloc_mask[2];
|
||||
+ struct slice_data slice[2];
|
||||
+};
|
||||
+
|
||||
+struct node_data {
|
||||
+ struct pglist_data pglist;
|
||||
+ struct hub_data hub;
|
||||
+ cpumask_t cpumask;
|
||||
+};
|
||||
+
|
||||
+extern struct node_data *__node_data[];
|
||||
+
|
||||
+#define NODE_DATA(n) (&__node_data[(n)]->pglist)
|
||||
+#define hub_data(n) (&__node_data[(n)]->hub)
|
||||
+
|
||||
+extern void setup_zero_pages(void);
|
||||
+extern void __init prom_init_numa_memory(void);
|
||||
+
|
||||
+#endif /* _ASM_MACH_MMZONE_H */
|
||||
diff --git a/arch/mips/include/asm/mach-loongson/topology.h b/arch/mips/include/asm/mach-loongson/topology.h
|
||||
new file mode 100644
|
||||
index 0000000..5598ba7
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/include/asm/mach-loongson/topology.h
|
||||
@@ -0,0 +1,23 @@
|
||||
+#ifndef _ASM_MACH_TOPOLOGY_H
|
||||
+#define _ASM_MACH_TOPOLOGY_H
|
||||
+
|
||||
+#ifdef CONFIG_NUMA
|
||||
+
|
||||
+#define cpu_to_node(cpu) ((cpu) >> 2)
|
||||
+#define parent_node(node) (node)
|
||||
+#define cpumask_of_node(node) (&__node_data[(node)]->cpumask)
|
||||
+
|
||||
+struct pci_bus;
|
||||
+extern int pcibus_to_node(struct pci_bus *);
|
||||
+
|
||||
+#define cpumask_of_pcibus(bus) (cpu_online_mask)
|
||||
+
|
||||
+extern unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
|
||||
+
|
||||
+#define node_distance(from, to) (__node_distances[(from)][(to)])
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+#include <asm-generic/topology.h>
|
||||
+
|
||||
+#endif /* _ASM_MACH_TOPOLOGY_H */
|
||||
diff --git a/arch/mips/include/asm/sparsemem.h b/arch/mips/include/asm/sparsemem.h
|
||||
index d2da53c..b1071c1 100644
|
||||
--- a/arch/mips/include/asm/sparsemem.h
|
||||
+++ b/arch/mips/include/asm/sparsemem.h
|
||||
@@ -11,7 +11,7 @@
|
||||
#else
|
||||
# define SECTION_SIZE_BITS 28
|
||||
#endif
|
||||
-#define MAX_PHYSMEM_BITS 35
|
||||
+#define MAX_PHYSMEM_BITS 48
|
||||
|
||||
#endif /* CONFIG_SPARSEMEM */
|
||||
#endif /* _MIPS_SPARSEMEM_H */
|
||||
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
|
||||
index 2f01201..7c1fe2b 100644
|
||||
--- a/arch/mips/kernel/setup.c
|
||||
+++ b/arch/mips/kernel/setup.c
|
||||
@@ -282,7 +282,7 @@ static unsigned long __init init_initrd(void)
|
||||
* Initialize the bootmem allocator. It also setup initrd related data
|
||||
* if needed.
|
||||
*/
|
||||
-#ifdef CONFIG_SGI_IP27
|
||||
+#if defined(CONFIG_SGI_IP27) || (defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_NUMA))
|
||||
|
||||
static void __init bootmem_init(void)
|
||||
{
|
||||
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
|
||||
index e6a86cc..a14a50d 100644
|
||||
--- a/arch/mips/loongson/Kconfig
|
||||
+++ b/arch/mips/loongson/Kconfig
|
||||
@@ -79,6 +79,7 @@ config LEMOTE_MACH3A
|
||||
select SYS_HAS_EARLY_PRINTK
|
||||
select SYS_SUPPORTS_SMP
|
||||
select SYS_SUPPORTS_HOTPLUG_CPU
|
||||
+ select SYS_SUPPORTS_NUMA
|
||||
select SYS_SUPPORTS_64BIT_KERNEL
|
||||
select SYS_SUPPORTS_HIGHMEM
|
||||
select SYS_SUPPORTS_LITTLE_ENDIAN
|
||||
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
|
||||
index dc59241..33a13b9 100644
|
||||
--- a/arch/mips/loongson/common/env.c
|
||||
+++ b/arch/mips/loongson/common/env.c
|
||||
@@ -80,17 +80,24 @@ void __init prom_init_env(void)
|
||||
cpu_clock_freq = ecpu->cpu_clock_freq;
|
||||
loongson_sysconf.cputype = ecpu->cputype;
|
||||
if (ecpu->cputype == Loongson_3A) {
|
||||
+ loongson_sysconf.cores_per_node = 4;
|
||||
+ loongson_sysconf.cores_per_package = 4;
|
||||
loongson_chipcfg[0] = 0x900000001fe00180;
|
||||
loongson_chipcfg[1] = 0x900010001fe00180;
|
||||
loongson_chipcfg[2] = 0x900020001fe00180;
|
||||
loongson_chipcfg[3] = 0x900030001fe00180;
|
||||
} else {
|
||||
+ loongson_sysconf.cores_per_node = 1;
|
||||
+ loongson_sysconf.cores_per_package = 1;
|
||||
loongson_chipcfg[0] = 0x900000001fe00180;
|
||||
}
|
||||
|
||||
loongson_sysconf.nr_cpus = ecpu->nr_cpus;
|
||||
if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
|
||||
loongson_sysconf.nr_cpus = NR_CPUS;
|
||||
+ loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
|
||||
+ loongson_sysconf.cores_per_node - 1) /
|
||||
+ loongson_sysconf.cores_per_node;
|
||||
|
||||
loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
|
||||
loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
|
||||
diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
|
||||
index f37fe54..f6af3ab 100644
|
||||
--- a/arch/mips/loongson/common/init.c
|
||||
+++ b/arch/mips/loongson/common/init.c
|
||||
@@ -30,7 +30,11 @@ void __init prom_init(void)
|
||||
set_io_port_base((unsigned long)
|
||||
ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
|
||||
|
||||
+#ifdef CONFIG_NUMA
|
||||
+ prom_init_numa_memory();
|
||||
+#else
|
||||
prom_init_memory();
|
||||
+#endif
|
||||
|
||||
/*init the uart base address */
|
||||
prom_init_uart_base();
|
||||
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
|
||||
index 70152b2..471b0f2a 100644
|
||||
--- a/arch/mips/loongson/loongson-3/Makefile
|
||||
+++ b/arch/mips/loongson/loongson-3/Makefile
|
||||
@@ -4,3 +4,5 @@
|
||||
obj-y += irq.o
|
||||
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
+
|
||||
+obj-$(CONFIG_NUMA) += numa.o
|
||||
diff --git a/arch/mips/loongson/loongson-3/numa.c b/arch/mips/loongson/loongson-3/numa.c
|
||||
new file mode 100644
|
||||
index 0000000..ca025a6
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/loongson/loongson-3/numa.c
|
||||
@@ -0,0 +1,291 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
|
||||
+ * Insititute of Computing Technology
|
||||
+ * Author: Xiang Gao, gaoxiang@ict.ac.cn
|
||||
+ * Huacai Chen, chenhc@lemote.com
|
||||
+ * Xiaofu Meng, Shuangshuang Zhang
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ */
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/mm.h>
|
||||
+#include <linux/mmzone.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/nodemask.h>
|
||||
+#include <linux/swap.h>
|
||||
+#include <linux/memblock.h>
|
||||
+#include <linux/bootmem.h>
|
||||
+#include <linux/pfn.h>
|
||||
+#include <linux/highmem.h>
|
||||
+#include <asm/page.h>
|
||||
+#include <asm/pgalloc.h>
|
||||
+#include <asm/sections.h>
|
||||
+#include <linux/bootmem.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <asm/bootinfo.h>
|
||||
+#include <asm/mc146818-time.h>
|
||||
+#include <asm/time.h>
|
||||
+#include <asm/wbflush.h>
|
||||
+#include <boot_param.h>
|
||||
+
|
||||
+static struct node_data prealloc__node_data[MAX_NUMNODES];
|
||||
+unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
|
||||
+struct node_data *__node_data[MAX_NUMNODES];
|
||||
+EXPORT_SYMBOL(__node_data);
|
||||
+
|
||||
+static void enable_lpa(void)
|
||||
+{
|
||||
+ unsigned long value;
|
||||
+
|
||||
+ value = __read_32bit_c0_register($16, 3);
|
||||
+ value |= 0x00000080;
|
||||
+ __write_32bit_c0_register($16, 3, value);
|
||||
+ value = __read_32bit_c0_register($16, 3);
|
||||
+ pr_info("CP0_Config3: CP0 16.3 (0x%lx)\n", value);
|
||||
+
|
||||
+ value = __read_32bit_c0_register($5, 1);
|
||||
+ value |= 0x20000000;
|
||||
+ __write_32bit_c0_register($5, 1, value);
|
||||
+ value = __read_32bit_c0_register($5, 1);
|
||||
+ pr_info("CP0_PageGrain: CP0 5.1 (0x%lx)\n", value);
|
||||
+}
|
||||
+
|
||||
+static void cpu_node_probe(void)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ nodes_clear(node_possible_map);
|
||||
+ nodes_clear(node_online_map);
|
||||
+ for (i = 0; i < loongson_sysconf.nr_nodes; i++) {
|
||||
+ node_set_state(num_online_nodes(), N_POSSIBLE);
|
||||
+ node_set_online(num_online_nodes());
|
||||
+ }
|
||||
+
|
||||
+ pr_info("NUMA: Discovered %d cpus on %d nodes\n",
|
||||
+ loongson_sysconf.nr_cpus, num_online_nodes());
|
||||
+}
|
||||
+
|
||||
+static int __init compute_node_distance(int row, int col)
|
||||
+{
|
||||
+ int package_row = row * loongson_sysconf.cores_per_node /
|
||||
+ loongson_sysconf.cores_per_package;
|
||||
+ int package_col = col * loongson_sysconf.cores_per_node /
|
||||
+ loongson_sysconf.cores_per_package;
|
||||
+
|
||||
+ if (col == row)
|
||||
+ return 0;
|
||||
+ else if (package_row == package_col)
|
||||
+ return 40;
|
||||
+ else
|
||||
+ return 100;
|
||||
+}
|
||||
+
|
||||
+static void __init init_topology_matrix(void)
|
||||
+{
|
||||
+ int row, col;
|
||||
+
|
||||
+ for (row = 0; row < MAX_NUMNODES; row++)
|
||||
+ for (col = 0; col < MAX_NUMNODES; col++)
|
||||
+ __node_distances[row][col] = -1;
|
||||
+
|
||||
+ for_each_online_node(row) {
|
||||
+ for_each_online_node(col) {
|
||||
+ __node_distances[row][col] =
|
||||
+ compute_node_distance(row, col);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static unsigned long nid_to_addroffset(unsigned int nid)
|
||||
+{
|
||||
+ unsigned long result;
|
||||
+ switch (nid) {
|
||||
+ case 0:
|
||||
+ default:
|
||||
+ result = NODE0_ADDRSPACE_OFFSET;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ result = NODE1_ADDRSPACE_OFFSET;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ result = NODE2_ADDRSPACE_OFFSET;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ result = NODE3_ADDRSPACE_OFFSET;
|
||||
+ break;
|
||||
+ }
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+static void __init szmem(unsigned int node)
|
||||
+{
|
||||
+ u32 i, mem_type;
|
||||
+ static unsigned long num_physpages = 0;
|
||||
+ u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
|
||||
+
|
||||
+ /* Parse memory information and activate */
|
||||
+ for (i = 0; i < loongson_memmap->nr_map; i++) {
|
||||
+ node_id = loongson_memmap->map[i].node_id;
|
||||
+ if (node_id != node)
|
||||
+ continue;
|
||||
+
|
||||
+ mem_type = loongson_memmap->map[i].mem_type;
|
||||
+ mem_size = loongson_memmap->map[i].mem_size;
|
||||
+ mem_start = loongson_memmap->map[i].mem_start;
|
||||
+
|
||||
+ switch (mem_type) {
|
||||
+ case SYSTEM_RAM_LOW:
|
||||
+ start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
|
||||
+ node_psize = (mem_size << 20) >> PAGE_SHIFT;
|
||||
+ end_pfn = start_pfn + node_psize;
|
||||
+ num_physpages += node_psize;
|
||||
+ pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
|
||||
+ (u32)node_id, mem_type, mem_start, mem_size);
|
||||
+ pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
|
||||
+ start_pfn, end_pfn, num_physpages);
|
||||
+ add_memory_region((node_id << 44) + mem_start,
|
||||
+ (u64)mem_size << 20, BOOT_MEM_RAM);
|
||||
+ memblock_add_node(PFN_PHYS(start_pfn),
|
||||
+ PFN_PHYS(end_pfn - start_pfn), node);
|
||||
+ break;
|
||||
+ case SYSTEM_RAM_HIGH:
|
||||
+ start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
|
||||
+ node_psize = (mem_size << 20) >> PAGE_SHIFT;
|
||||
+ end_pfn = start_pfn + node_psize;
|
||||
+ num_physpages += node_psize;
|
||||
+ pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
|
||||
+ (u32)node_id, mem_type, mem_start, mem_size);
|
||||
+ pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
|
||||
+ start_pfn, end_pfn, num_physpages);
|
||||
+ add_memory_region((node_id << 44) + mem_start,
|
||||
+ (u64)mem_size << 20, BOOT_MEM_RAM);
|
||||
+ memblock_add_node(PFN_PHYS(start_pfn),
|
||||
+ PFN_PHYS(end_pfn - start_pfn), node);
|
||||
+ break;
|
||||
+ case MEM_RESERVED:
|
||||
+ pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
|
||||
+ (u32)node_id, mem_type, mem_start, mem_size);
|
||||
+ add_memory_region((node_id << 44) + mem_start,
|
||||
+ (u64)mem_size << 20, BOOT_MEM_RESERVED);
|
||||
+ memblock_reserve(((node_id << 44) + mem_start),
|
||||
+ mem_size << 20);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void __init node_mem_init(unsigned int node)
|
||||
+{
|
||||
+ unsigned long bootmap_size;
|
||||
+ unsigned long node_addrspace_offset;
|
||||
+ unsigned long start_pfn, end_pfn, freepfn;
|
||||
+
|
||||
+ node_addrspace_offset = nid_to_addroffset(node);
|
||||
+ pr_info("Node%d's addrspace_offset is 0x%lx\n",
|
||||
+ node, node_addrspace_offset);
|
||||
+
|
||||
+ get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
|
||||
+ freepfn = start_pfn;
|
||||
+ if (node == 0)
|
||||
+ freepfn = PFN_UP(__pa_symbol(&_end)); /* kernel end address */
|
||||
+ pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx, freepfn=0x%lx\n",
|
||||
+ node, start_pfn, end_pfn, freepfn);
|
||||
+
|
||||
+ __node_data[node] = prealloc__node_data + node;
|
||||
+
|
||||
+ NODE_DATA(node)->bdata = &bootmem_node_data[node];
|
||||
+ NODE_DATA(node)->node_start_pfn = start_pfn;
|
||||
+ NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
|
||||
+
|
||||
+ bootmap_size = init_bootmem_node(NODE_DATA(node), freepfn,
|
||||
+ start_pfn, end_pfn);
|
||||
+ free_bootmem_with_active_regions(node, end_pfn);
|
||||
+ if (node == 0) /* used by finalize_initrd() */
|
||||
+ max_low_pfn = end_pfn;
|
||||
+
|
||||
+ /* This is reserved for the kernel and bdata->node_bootmem_map */
|
||||
+ reserve_bootmem_node(NODE_DATA(node), start_pfn << PAGE_SHIFT,
|
||||
+ ((freepfn - start_pfn) << PAGE_SHIFT) + bootmap_size,
|
||||
+ BOOTMEM_DEFAULT);
|
||||
+
|
||||
+ if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) {
|
||||
+ /* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */
|
||||
+ reserve_bootmem_node(NODE_DATA(node),
|
||||
+ (node_addrspace_offset | 0xff800000),
|
||||
+ 8 << 20, BOOTMEM_DEFAULT);
|
||||
+ }
|
||||
+
|
||||
+ sparse_memory_present_with_active_regions(node);
|
||||
+}
|
||||
+
|
||||
+static __init void prom_meminit(void)
|
||||
+{
|
||||
+ unsigned int node, cpu;
|
||||
+
|
||||
+ cpu_node_probe();
|
||||
+ init_topology_matrix();
|
||||
+
|
||||
+ for (node = 0; node < loongson_sysconf.nr_nodes; node++) {
|
||||
+ if (node_online(node)) {
|
||||
+ szmem(node);
|
||||
+ node_mem_init(node);
|
||||
+ cpus_clear(__node_data[(node)]->cpumask);
|
||||
+ }
|
||||
+ }
|
||||
+ for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
|
||||
+ node = cpu / loongson_sysconf.cores_per_node;
|
||||
+ if (node >= num_online_nodes())
|
||||
+ node = 0;
|
||||
+ pr_info("NUMA: set cpumask cpu %d on node %d\n", cpu, node);
|
||||
+ cpu_set(cpu, __node_data[(node)]->cpumask);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void __init paging_init(void)
|
||||
+{
|
||||
+ unsigned node;
|
||||
+ unsigned long zones_size[MAX_NR_ZONES] = {0, };
|
||||
+
|
||||
+ pagetable_init();
|
||||
+
|
||||
+ for_each_online_node(node) {
|
||||
+ unsigned long start_pfn, end_pfn;
|
||||
+
|
||||
+ get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
|
||||
+
|
||||
+ if (end_pfn > max_low_pfn)
|
||||
+ max_low_pfn = end_pfn;
|
||||
+ }
|
||||
+#ifdef CONFIG_ZONE_DMA32
|
||||
+ zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
|
||||
+#endif
|
||||
+ zones_size[ZONE_NORMAL] = max_low_pfn;
|
||||
+ free_area_init_nodes(zones_size);
|
||||
+}
|
||||
+
|
||||
+void __init mem_init(void)
|
||||
+{
|
||||
+ high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT);
|
||||
+ free_all_bootmem();
|
||||
+ setup_zero_pages(); /* This comes from node 0 */
|
||||
+ mem_init_print_info(NULL);
|
||||
+}
|
||||
+
|
||||
+/* All PCI device belongs to logical Node-0 */
|
||||
+int pcibus_to_node(struct pci_bus *bus)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(pcibus_to_node);
|
||||
+
|
||||
+void __init prom_init_numa_memory(void)
|
||||
+{
|
||||
+ enable_lpa();
|
||||
+ prom_meminit();
|
||||
+}
|
||||
+EXPORT_SYMBOL(prom_init_numa_memory);
|
||||
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
|
||||
index 3c320e7..ed0e2d0 100644
|
||||
--- a/arch/mips/loongson/loongson-3/smp.c
|
||||
+++ b/arch/mips/loongson/loongson-3/smp.c
|
||||
@@ -203,6 +203,8 @@ static void loongson3_init_secondary(void)
|
||||
for (i = 0; i < loongson_sysconf.nr_cpus; i++)
|
||||
loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
|
||||
|
||||
+ cpu_data[cpu].package = cpu / loongson_sysconf.cores_per_package;
|
||||
+ cpu_data[cpu].core = cpu % loongson_sysconf.cores_per_package;
|
||||
per_cpu(cpu_state, cpu) = CPU_ONLINE;
|
||||
|
||||
i = 0;
|
||||
@@ -394,17 +396,19 @@ static int loongson3_cpu_callback(struct notifier_block *nfb,
|
||||
unsigned long action, void *hcpu)
|
||||
{
|
||||
unsigned int cpu = (unsigned long)hcpu;
|
||||
+ uint64_t core_id = cpu_data[cpu].core;
|
||||
+ uint64_t package_id = cpu_data[cpu].package;
|
||||
|
||||
switch (action) {
|
||||
case CPU_POST_DEAD:
|
||||
case CPU_POST_DEAD_FROZEN:
|
||||
pr_info("Disable clock for CPU#%d\n", cpu);
|
||||
- LOONGSON_CHIPCFG(0) &= ~(1 << (12 + cpu));
|
||||
+ LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
|
||||
break;
|
||||
case CPU_UP_PREPARE:
|
||||
case CPU_UP_PREPARE_FROZEN:
|
||||
pr_info("Enable clock for CPU#%d\n", cpu);
|
||||
- LOONGSON_CHIPCFG(0) |= 1 << (12 + cpu);
|
||||
+ LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
|
||||
break;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
From: Huacai Chen <chenhc@lemote.com>
|
||||
Date: Thu, 26 Jun 2014 11:41:29 +0800
|
||||
Subject: [5/8] MIPS: Add numa api support
|
||||
Origin: https://git.kernel.org/linus/1ff1ad6bc2c63f219cbc00dcdd35dcf36a7d6fe4
|
||||
|
||||
Enable sys_mbind()/sys_get_mempolicy()/sys_set_mempolicy() for O32, N32,
|
||||
and N64 ABIs. By the way, O32/N32 should use the compat version of
|
||||
sys_migrate_pages()/sys_move_pages(), so fix that.
|
||||
|
||||
Signed-off-by: Huacai Chen <chenhc@lemote.com>
|
||||
Cc: John Crispin <john@phrozen.org>
|
||||
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
|
||||
Cc: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Cc: Fuxin Zhang <zhangfx@lemote.com>
|
||||
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/7186/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/kernel/scall32-o32.S | 4 ++--
|
||||
arch/mips/kernel/scall64-64.S | 4 ++--
|
||||
arch/mips/kernel/scall64-n32.S | 10 +++++-----
|
||||
arch/mips/kernel/scall64-o32.S | 8 ++++----
|
||||
4 files changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
|
||||
index 3245474..6bfdc82 100644
|
||||
--- a/arch/mips/kernel/scall32-o32.S
|
||||
+++ b/arch/mips/kernel/scall32-o32.S
|
||||
@@ -495,8 +495,8 @@ EXPORT(sys_call_table)
|
||||
PTR sys_tgkill
|
||||
PTR sys_utimes
|
||||
PTR sys_mbind
|
||||
- PTR sys_ni_syscall /* sys_get_mempolicy */
|
||||
- PTR sys_ni_syscall /* 4270 sys_set_mempolicy */
|
||||
+ PTR sys_get_mempolicy
|
||||
+ PTR sys_set_mempolicy /* 4270 */
|
||||
PTR sys_mq_open
|
||||
PTR sys_mq_unlink
|
||||
PTR sys_mq_timedsend
|
||||
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
|
||||
index be2fedd..0952139 100644
|
||||
--- a/arch/mips/kernel/scall64-64.S
|
||||
+++ b/arch/mips/kernel/scall64-64.S
|
||||
@@ -347,8 +347,8 @@ EXPORT(sys_call_table)
|
||||
PTR sys_tgkill /* 5225 */
|
||||
PTR sys_utimes
|
||||
PTR sys_mbind
|
||||
- PTR sys_ni_syscall /* sys_get_mempolicy */
|
||||
- PTR sys_ni_syscall /* sys_set_mempolicy */
|
||||
+ PTR sys_get_mempolicy
|
||||
+ PTR sys_set_mempolicy
|
||||
PTR sys_mq_open /* 5230 */
|
||||
PTR sys_mq_unlink
|
||||
PTR sys_mq_timedsend
|
||||
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
|
||||
index c1dbcda..7641c87 100644
|
||||
--- a/arch/mips/kernel/scall64-n32.S
|
||||
+++ b/arch/mips/kernel/scall64-n32.S
|
||||
@@ -339,9 +339,9 @@ EXPORT(sysn32_call_table)
|
||||
PTR compat_sys_clock_nanosleep
|
||||
PTR sys_tgkill
|
||||
PTR compat_sys_utimes /* 6230 */
|
||||
- PTR sys_ni_syscall /* sys_mbind */
|
||||
- PTR sys_ni_syscall /* sys_get_mempolicy */
|
||||
- PTR sys_ni_syscall /* sys_set_mempolicy */
|
||||
+ PTR compat_sys_mbind
|
||||
+ PTR compat_sys_get_mempolicy
|
||||
+ PTR compat_sys_set_mempolicy
|
||||
PTR compat_sys_mq_open
|
||||
PTR sys_mq_unlink /* 6235 */
|
||||
PTR compat_sys_mq_timedsend
|
||||
@@ -358,7 +358,7 @@ EXPORT(sysn32_call_table)
|
||||
PTR sys_inotify_init
|
||||
PTR sys_inotify_add_watch
|
||||
PTR sys_inotify_rm_watch
|
||||
- PTR sys_migrate_pages /* 6250 */
|
||||
+ PTR compat_sys_migrate_pages /* 6250 */
|
||||
PTR sys_openat
|
||||
PTR sys_mkdirat
|
||||
PTR sys_mknodat
|
||||
@@ -379,7 +379,7 @@ EXPORT(sysn32_call_table)
|
||||
PTR sys_sync_file_range
|
||||
PTR sys_tee
|
||||
PTR compat_sys_vmsplice /* 6270 */
|
||||
- PTR sys_move_pages
|
||||
+ PTR compat_sys_move_pages
|
||||
PTR compat_sys_set_robust_list
|
||||
PTR compat_sys_get_robust_list
|
||||
PTR compat_sys_kexec_load
|
||||
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
|
||||
index f1343cc..18cfa11 100644
|
||||
--- a/arch/mips/kernel/scall64-o32.S
|
||||
+++ b/arch/mips/kernel/scall64-o32.S
|
||||
@@ -473,9 +473,9 @@ EXPORT(sys32_call_table)
|
||||
PTR compat_sys_clock_nanosleep /* 4265 */
|
||||
PTR sys_tgkill
|
||||
PTR compat_sys_utimes
|
||||
- PTR sys_ni_syscall /* sys_mbind */
|
||||
- PTR sys_ni_syscall /* sys_get_mempolicy */
|
||||
- PTR sys_ni_syscall /* 4270 sys_set_mempolicy */
|
||||
+ PTR compat_sys_mbind
|
||||
+ PTR compat_sys_get_mempolicy
|
||||
+ PTR compat_sys_set_mempolicy /* 4270 */
|
||||
PTR compat_sys_mq_open
|
||||
PTR sys_mq_unlink
|
||||
PTR compat_sys_mq_timedsend
|
||||
@@ -492,7 +492,7 @@ EXPORT(sys32_call_table)
|
||||
PTR sys_inotify_init
|
||||
PTR sys_inotify_add_watch /* 4285 */
|
||||
PTR sys_inotify_rm_watch
|
||||
- PTR sys_migrate_pages
|
||||
+ PTR compat_sys_migrate_pages
|
||||
PTR compat_sys_openat
|
||||
PTR sys_mkdirat
|
||||
PTR sys_mknodat /* 4290 */
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
From: Huacai Chen <chenhc@lemote.com>
|
||||
Date: Thu, 26 Jun 2014 11:41:31 +0800
|
||||
Subject: [7/8] MIPS: Loongson-3: Enable the COP2 usage
|
||||
Origin: https://git.kernel.org/linus/ef2f826c8f2ff1e4215968042139604633581a13
|
||||
|
||||
Loongson-3 has some specific instructions (MMI/SIMD) in coprocessor 2.
|
||||
COP2 isn't independent because it share COP1 (FPU)'s registers. This
|
||||
patch enable the COP2 usage so user-space programs can use the MMI/SIMD
|
||||
instructions. When COP2 exception happens, we enable both COP1 (FPU)
|
||||
and COP2, only in this way the fp context can be saved and restored
|
||||
correctly.
|
||||
|
||||
Signed-off-by: Huacai Chen <chenhc@lemote.com>
|
||||
Cc: John Crispin <john@phrozen.org>
|
||||
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
|
||||
Cc: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Cc: Fuxin Zhang <zhangfx@lemote.com>
|
||||
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/7189/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/include/asm/cop2.h | 8 ++++
|
||||
arch/mips/loongson/loongson-3/Makefile | 2 +-
|
||||
arch/mips/loongson/loongson-3/cop2-ex.c | 63 +++++++++++++++++++++++++++++++
|
||||
3 files changed, 72 insertions(+), 1 deletion(-)
|
||||
create mode 100644 arch/mips/loongson/loongson-3/cop2-ex.c
|
||||
|
||||
diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h
|
||||
index c1516cc..d035298 100644
|
||||
--- a/arch/mips/include/asm/cop2.h
|
||||
+++ b/arch/mips/include/asm/cop2.h
|
||||
@@ -32,6 +32,14 @@ extern void nlm_cop2_restore(struct nlm_cop2_state *);
|
||||
#define cop2_present 1
|
||||
#define cop2_lazy_restore 0
|
||||
|
||||
+#elif defined(CONFIG_CPU_LOONGSON3)
|
||||
+
|
||||
+#define cop2_save(r)
|
||||
+#define cop2_restore(r)
|
||||
+
|
||||
+#define cop2_present 1
|
||||
+#define cop2_lazy_restore 1
|
||||
+
|
||||
#else
|
||||
|
||||
#define cop2_present 0
|
||||
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
|
||||
index 471b0f2a..b4df775 100644
|
||||
--- a/arch/mips/loongson/loongson-3/Makefile
|
||||
+++ b/arch/mips/loongson/loongson-3/Makefile
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Makefile for Loongson-3 family machines
|
||||
#
|
||||
-obj-y += irq.o
|
||||
+obj-y += irq.o cop2-ex.o
|
||||
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
|
||||
diff --git a/arch/mips/loongson/loongson-3/cop2-ex.c b/arch/mips/loongson/loongson-3/cop2-ex.c
|
||||
new file mode 100644
|
||||
index 0000000..9182e8d
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/loongson/loongson-3/cop2-ex.c
|
||||
@@ -0,0 +1,63 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2014 Lemote Corporation.
|
||||
+ * written by Huacai Chen <chenhc@lemote.com>
|
||||
+ *
|
||||
+ * based on arch/mips/cavium-octeon/cpu.c
|
||||
+ * Copyright (C) 2009 Wind River Systems,
|
||||
+ * written by Ralf Baechle <ralf@linux-mips.org>
|
||||
+ */
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/notifier.h>
|
||||
+
|
||||
+#include <asm/fpu.h>
|
||||
+#include <asm/cop2.h>
|
||||
+#include <asm/current.h>
|
||||
+#include <asm/mipsregs.h>
|
||||
+
|
||||
+static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action,
|
||||
+ void *data)
|
||||
+{
|
||||
+ int fpu_enabled;
|
||||
+ int fr = !test_thread_flag(TIF_32BIT_FPREGS);
|
||||
+
|
||||
+ switch (action) {
|
||||
+ case CU2_EXCEPTION:
|
||||
+ preempt_disable();
|
||||
+ fpu_enabled = read_c0_status() & ST0_CU1;
|
||||
+ if (!fr)
|
||||
+ set_c0_status(ST0_CU1 | ST0_CU2);
|
||||
+ else
|
||||
+ set_c0_status(ST0_CU1 | ST0_CU2 | ST0_FR);
|
||||
+ enable_fpu_hazard();
|
||||
+ KSTK_STATUS(current) |= (ST0_CU1 | ST0_CU2);
|
||||
+ if (fr)
|
||||
+ KSTK_STATUS(current) |= ST0_FR;
|
||||
+ else
|
||||
+ KSTK_STATUS(current) &= ~ST0_FR;
|
||||
+ /* If FPU is enabled, we needn't init or restore fp */
|
||||
+ if(!fpu_enabled) {
|
||||
+ set_thread_flag(TIF_USEDFPU);
|
||||
+ if (!used_math()) {
|
||||
+ _init_fpu();
|
||||
+ set_used_math();
|
||||
+ } else
|
||||
+ _restore_fp(current);
|
||||
+ }
|
||||
+ preempt_enable();
|
||||
+
|
||||
+ return NOTIFY_STOP; /* Don't call default notifier */
|
||||
+ }
|
||||
+
|
||||
+ return NOTIFY_OK; /* Let default notifier send signals */
|
||||
+}
|
||||
+
|
||||
+static int __init loongson_cu2_setup(void)
|
||||
+{
|
||||
+ return cu2_notifier(loongson_cu2_call, 0);
|
||||
+}
|
||||
+early_initcall(loongson_cu2_setup);
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
From: Huacai Chen <chenhc@lemote.com>
|
||||
Date: Thu, 26 Jun 2014 11:41:27 +0800
|
||||
Subject: [3/8] MIPS: Loongson: Modify ChipConfig register definition
|
||||
Origin: https://git.kernel.org/linus/140e39c1e3d29f50e161f55cca60f60b80408c2a
|
||||
|
||||
This patch is prepared for Multi-chip interconnection. Since each chip
|
||||
has a ChipConfig register, LOONGSON_CHIPCFG should be an array.
|
||||
|
||||
Signed-off-by: Huacai Chen <chenhc@lemote.com>
|
||||
Cc: John Crispin <john@phrozen.org>
|
||||
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
|
||||
Cc: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Cc: Fuxin Zhang <zhangfx@lemote.com>
|
||||
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/7185/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/include/asm/mach-loongson/loongson.h | 7 +++++--
|
||||
arch/mips/loongson/common/env.c | 11 +++++++++++
|
||||
arch/mips/loongson/common/pm.c | 8 ++++----
|
||||
arch/mips/loongson/lemote-2f/clock.c | 4 ++--
|
||||
arch/mips/loongson/lemote-2f/reset.c | 2 +-
|
||||
arch/mips/loongson/loongson-3/smp.c | 4 ++--
|
||||
drivers/cpufreq/loongson2_cpufreq.c | 6 +++---
|
||||
7 files changed, 28 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
|
||||
index f3fd1eb..a1c76ca 100644
|
||||
--- a/arch/mips/include/asm/mach-loongson/loongson.h
|
||||
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
|
||||
@@ -249,8 +249,11 @@ static inline void do_perfcnt_IRQ(void)
|
||||
#define LOONGSON_PXARB_CFG LOONGSON_REG(LOONGSON_REGBASE + 0x68)
|
||||
#define LOONGSON_PXARB_STATUS LOONGSON_REG(LOONGSON_REGBASE + 0x6c)
|
||||
|
||||
-/* Chip Config */
|
||||
-#define LOONGSON_CHIPCFG0 LOONGSON_REG(LOONGSON_REGBASE + 0x80)
|
||||
+#define MAX_PACKAGES 4
|
||||
+
|
||||
+/* Chip Config registor of each physical cpu package, PRid >= Loongson-2F */
|
||||
+extern u64 loongson_chipcfg[MAX_PACKAGES];
|
||||
+#define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id]))
|
||||
|
||||
/* pcimap */
|
||||
|
||||
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
|
||||
index 0c543ea..dc59241 100644
|
||||
--- a/arch/mips/loongson/common/env.c
|
||||
+++ b/arch/mips/loongson/common/env.c
|
||||
@@ -27,6 +27,8 @@ EXPORT_SYMBOL(cpu_clock_freq);
|
||||
struct efi_memory_map_loongson *loongson_memmap;
|
||||
struct loongson_system_configuration loongson_sysconf;
|
||||
|
||||
+u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
|
||||
+
|
||||
#define parse_even_earlier(res, option, p) \
|
||||
do { \
|
||||
unsigned int tmp __maybe_unused; \
|
||||
@@ -77,6 +79,15 @@ void __init prom_init_env(void)
|
||||
|
||||
cpu_clock_freq = ecpu->cpu_clock_freq;
|
||||
loongson_sysconf.cputype = ecpu->cputype;
|
||||
+ if (ecpu->cputype == Loongson_3A) {
|
||||
+ loongson_chipcfg[0] = 0x900000001fe00180;
|
||||
+ loongson_chipcfg[1] = 0x900010001fe00180;
|
||||
+ loongson_chipcfg[2] = 0x900020001fe00180;
|
||||
+ loongson_chipcfg[3] = 0x900030001fe00180;
|
||||
+ } else {
|
||||
+ loongson_chipcfg[0] = 0x900000001fe00180;
|
||||
+ }
|
||||
+
|
||||
loongson_sysconf.nr_cpus = ecpu->nr_cpus;
|
||||
if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
|
||||
loongson_sysconf.nr_cpus = NR_CPUS;
|
||||
diff --git a/arch/mips/loongson/common/pm.c b/arch/mips/loongson/common/pm.c
|
||||
index f55e07a..a6b67cc 100644
|
||||
--- a/arch/mips/loongson/common/pm.c
|
||||
+++ b/arch/mips/loongson/common/pm.c
|
||||
@@ -79,7 +79,7 @@ int __weak wakeup_loongson(void)
|
||||
static void wait_for_wakeup_events(void)
|
||||
{
|
||||
while (!wakeup_loongson())
|
||||
- LOONGSON_CHIPCFG0 &= ~0x7;
|
||||
+ LOONGSON_CHIPCFG(0) &= ~0x7;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -102,15 +102,15 @@ static void loongson_suspend_enter(void)
|
||||
|
||||
stop_perf_counters();
|
||||
|
||||
- cached_cpu_freq = LOONGSON_CHIPCFG0;
|
||||
+ cached_cpu_freq = LOONGSON_CHIPCFG(0);
|
||||
|
||||
/* Put CPU into wait mode */
|
||||
- LOONGSON_CHIPCFG0 &= ~0x7;
|
||||
+ LOONGSON_CHIPCFG(0) &= ~0x7;
|
||||
|
||||
/* wait for the given events to wakeup cpu from wait mode */
|
||||
wait_for_wakeup_events();
|
||||
|
||||
- LOONGSON_CHIPCFG0 = cached_cpu_freq;
|
||||
+ LOONGSON_CHIPCFG(0) = cached_cpu_freq;
|
||||
mmiowb();
|
||||
}
|
||||
|
||||
diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson/lemote-2f/clock.c
|
||||
index 1eed38e..a217061 100644
|
||||
--- a/arch/mips/loongson/lemote-2f/clock.c
|
||||
+++ b/arch/mips/loongson/lemote-2f/clock.c
|
||||
@@ -114,9 +114,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
|
||||
clk->rate = rate;
|
||||
|
||||
- regval = LOONGSON_CHIPCFG0;
|
||||
+ regval = LOONGSON_CHIPCFG(0);
|
||||
regval = (regval & ~0x7) | (pos->driver_data - 1);
|
||||
- LOONGSON_CHIPCFG0 = regval;
|
||||
+ LOONGSON_CHIPCFG(0) = regval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson/lemote-2f/reset.c
|
||||
index 90962a3..79ac694 100644
|
||||
--- a/arch/mips/loongson/lemote-2f/reset.c
|
||||
+++ b/arch/mips/loongson/lemote-2f/reset.c
|
||||
@@ -28,7 +28,7 @@ static void reset_cpu(void)
|
||||
* reset cpu to full speed, this is needed when enabling cpu frequency
|
||||
* scalling
|
||||
*/
|
||||
- LOONGSON_CHIPCFG0 |= 0x7;
|
||||
+ LOONGSON_CHIPCFG(0) |= 0x7;
|
||||
}
|
||||
|
||||
/* reset support for fuloong2f */
|
||||
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
|
||||
index 1e88940..3c320e7 100644
|
||||
--- a/arch/mips/loongson/loongson-3/smp.c
|
||||
+++ b/arch/mips/loongson/loongson-3/smp.c
|
||||
@@ -399,12 +399,12 @@ static int loongson3_cpu_callback(struct notifier_block *nfb,
|
||||
case CPU_POST_DEAD:
|
||||
case CPU_POST_DEAD_FROZEN:
|
||||
pr_info("Disable clock for CPU#%d\n", cpu);
|
||||
- LOONGSON_CHIPCFG0 &= ~(1 << (12 + cpu));
|
||||
+ LOONGSON_CHIPCFG(0) &= ~(1 << (12 + cpu));
|
||||
break;
|
||||
case CPU_UP_PREPARE:
|
||||
case CPU_UP_PREPARE_FROZEN:
|
||||
pr_info("Enable clock for CPU#%d\n", cpu);
|
||||
- LOONGSON_CHIPCFG0 |= 1 << (12 + cpu);
|
||||
+ LOONGSON_CHIPCFG(0) |= 1 << (12 + cpu);
|
||||
break;
|
||||
}
|
||||
|
||||
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
|
||||
index d4add86..9fa1772 100644
|
||||
--- a/drivers/cpufreq/loongson2_cpufreq.c
|
||||
+++ b/drivers/cpufreq/loongson2_cpufreq.c
|
||||
@@ -148,9 +148,9 @@ static void loongson2_cpu_wait(void)
|
||||
u32 cpu_freq;
|
||||
|
||||
spin_lock_irqsave(&loongson2_wait_lock, flags);
|
||||
- cpu_freq = LOONGSON_CHIPCFG0;
|
||||
- LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */
|
||||
- LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */
|
||||
+ cpu_freq = LOONGSON_CHIPCFG(0);
|
||||
+ LOONGSON_CHIPCFG(0) &= ~0x7; /* Put CPU into wait mode */
|
||||
+ LOONGSON_CHIPCFG(0) = cpu_freq; /* Restore CPU state */
|
||||
spin_unlock_irqrestore(&loongson2_wait_lock, flags);
|
||||
local_irq_enable();
|
||||
}
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
From: Huacai Chen <chenhc@lemote.com>
|
||||
Date: Thu, 26 Jun 2014 11:41:32 +0800
|
||||
Subject: [8/8] MIPS: Loongson: Rename CONFIG_LEMOTE_MACH3A to
|
||||
CONFIG_LOONGSON_MACH3X
|
||||
Origin: https://git.kernel.org/linus/5a21e0ba3e8996353e6892ccc54b0aab541d9722
|
||||
|
||||
Since this CONFIG option will be used for both Loongson-3A/3B machines,
|
||||
and not all Loongson-3 machines are produced by Lemote, we rename
|
||||
CONFIG_LEMOTE_MACH3A to CONFIG_LOONGSON_MACH3X.
|
||||
|
||||
Signed-off-by: Huacai Chen <chenhc@lemote.com>
|
||||
Cc: John Crispin <john@phrozen.org>
|
||||
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
|
||||
Cc: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Cc: Fuxin Zhang <zhangfx@lemote.com>
|
||||
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/7190/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/configs/loongson3_defconfig | 2 +-
|
||||
arch/mips/include/asm/mach-loongson/machine.h | 4 ++--
|
||||
arch/mips/loongson/Kconfig | 8 ++++----
|
||||
arch/mips/loongson/Platform | 2 +-
|
||||
arch/mips/pci/Makefile | 2 +-
|
||||
5 files changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig
|
||||
index ea1761f..130e31b 100644
|
||||
--- a/arch/mips/configs/loongson3_defconfig
|
||||
+++ b/arch/mips/configs/loongson3_defconfig
|
||||
@@ -1,6 +1,6 @@
|
||||
CONFIG_MACH_LOONGSON=y
|
||||
CONFIG_SWIOTLB=y
|
||||
-CONFIG_LEMOTE_MACH3A=y
|
||||
+CONFIG_LOONGSON_MACH3X=y
|
||||
CONFIG_CPU_LOONGSON3=y
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_PAGE_SIZE_16KB=y
|
||||
diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
|
||||
index 1b1f592..228e3784 100644
|
||||
--- a/arch/mips/include/asm/mach-loongson/machine.h
|
||||
+++ b/arch/mips/include/asm/mach-loongson/machine.h
|
||||
@@ -24,10 +24,10 @@
|
||||
|
||||
#endif
|
||||
|
||||
-#ifdef CONFIG_LEMOTE_MACH3A
|
||||
+#ifdef CONFIG_LOONGSON_MACH3X
|
||||
|
||||
#define LOONGSON_MACHTYPE MACH_LEMOTE_A1101
|
||||
|
||||
-#endif /* CONFIG_LEMOTE_MACH3A */
|
||||
+#endif /* CONFIG_LOONGSON_MACH3X */
|
||||
|
||||
#endif /* __ASM_MACH_LOONGSON_MACHINE_H */
|
||||
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
|
||||
index a14a50d..1b91fc6 100644
|
||||
--- a/arch/mips/loongson/Kconfig
|
||||
+++ b/arch/mips/loongson/Kconfig
|
||||
@@ -60,8 +60,8 @@ config LEMOTE_MACH2F
|
||||
These family machines include fuloong2f mini PC, yeeloong2f notebook,
|
||||
LingLoong allinone PC and so forth.
|
||||
|
||||
-config LEMOTE_MACH3A
|
||||
- bool "Lemote Loongson 3A family machines"
|
||||
+config LOONGSON_MACH3X
|
||||
+ bool "Generic Loongson 3 family machines"
|
||||
select ARCH_SPARSEMEM_ENABLE
|
||||
select GENERIC_ISA_DMA_SUPPORT_BROKEN
|
||||
select BOOT_ELF32
|
||||
@@ -87,8 +87,8 @@ config LEMOTE_MACH3A
|
||||
select ZONE_DMA32
|
||||
select LEFI_FIRMWARE_INTERFACE
|
||||
help
|
||||
- Lemote Loongson 3A family machines utilize the 3A revision of
|
||||
- Loongson processor and RS780/SBX00 chipset.
|
||||
+ Generic Loongson 3 family machines utilize the 3A/3B revision
|
||||
+ of Loongson processor and RS780/SBX00 chipset.
|
||||
endchoice
|
||||
|
||||
config CS5536
|
||||
diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform
|
||||
index 6205372..0ac20eb 100644
|
||||
--- a/arch/mips/loongson/Platform
|
||||
+++ b/arch/mips/loongson/Platform
|
||||
@@ -30,4 +30,4 @@ platform-$(CONFIG_MACH_LOONGSON) += loongson/
|
||||
cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
|
||||
load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
|
||||
load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
|
||||
-load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000
|
||||
+load-$(CONFIG_LOONGSON_MACH3X) += 0xffffffff80200000
|
||||
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
|
||||
index ff8a553..6523d55 100644
|
||||
--- a/arch/mips/pci/Makefile
|
||||
+++ b/arch/mips/pci/Makefile
|
||||
@@ -29,7 +29,7 @@ obj-$(CONFIG_LASAT) += pci-lasat.o
|
||||
obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
|
||||
obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o
|
||||
obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o
|
||||
-obj-$(CONFIG_LEMOTE_MACH3A) += fixup-loongson3.o ops-loongson3.o
|
||||
+obj-$(CONFIG_LOONGSON_MACH3X) += fixup-loongson3.o ops-loongson3.o
|
||||
obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o pci-malta.o
|
||||
obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o
|
||||
obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
From: Huacai Chen <chenhc@lemote.com>
|
||||
Date: Thu, 26 Jun 2014 11:41:26 +0800
|
||||
Subject: [2/8] MIPS: Support CPU topology files in sysfs
|
||||
Origin: https://git.kernel.org/linus/bda4584cd943d7bb6cf677a8d694700c1984cf3e
|
||||
|
||||
This patch is prepared for Loongson's NUMA support, it offer meaningful
|
||||
sysfs files such as physical_package_id, core_id, core_siblings and
|
||||
thread_siblings in /sys/devices/system/cpu/cpu?/topology.
|
||||
|
||||
Signed-off-by: Huacai Chen <chenhc@lemote.com>
|
||||
Reviewed-by: Andreas Herrmann <andreas.herrmann@caviumnetworks.com>
|
||||
Cc: John Crispin <john@phrozen.org>
|
||||
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
|
||||
Cc: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Cc: Fuxin Zhang <zhangfx@lemote.com>
|
||||
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/7184/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/include/asm/cpu-info.h | 1 +
|
||||
arch/mips/include/asm/smp.h | 6 ++++++
|
||||
arch/mips/kernel/proc.c | 1 +
|
||||
arch/mips/kernel/smp.c | 26 +++++++++++++++++++++++++-
|
||||
4 files changed, 33 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
|
||||
index a28e3de..6690d7a 100644
|
||||
--- a/arch/mips/include/asm/cpu-info.h
|
||||
+++ b/arch/mips/include/asm/cpu-info.h
|
||||
@@ -61,6 +61,7 @@ struct cpuinfo_mips {
|
||||
struct cache_desc scache; /* Secondary cache */
|
||||
struct cache_desc tcache; /* Tertiary/split secondary cache */
|
||||
int srsets; /* Shadow register sets */
|
||||
+ int package;/* physical package number */
|
||||
int core; /* physical core number */
|
||||
#ifdef CONFIG_64BIT
|
||||
int vmbits; /* Virtual memory size in bits */
|
||||
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
|
||||
index b037334..1e0f20a 100644
|
||||
--- a/arch/mips/include/asm/smp.h
|
||||
+++ b/arch/mips/include/asm/smp.h
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
extern int smp_num_siblings;
|
||||
extern cpumask_t cpu_sibling_map[];
|
||||
+extern cpumask_t cpu_core_map[];
|
||||
|
||||
#define raw_smp_processor_id() (current_thread_info()->cpu)
|
||||
|
||||
@@ -36,6 +37,11 @@ extern int __cpu_logical_map[NR_CPUS];
|
||||
|
||||
#define NO_PROC_ID (-1)
|
||||
|
||||
+#define topology_physical_package_id(cpu) (cpu_data[cpu].package)
|
||||
+#define topology_core_id(cpu) (cpu_data[cpu].core)
|
||||
+#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
|
||||
+#define topology_thread_cpumask(cpu) (&cpu_sibling_map[cpu])
|
||||
+
|
||||
#define SMP_RESCHEDULE_YOURSELF 0x1 /* XXX braindead */
|
||||
#define SMP_CALL_FUNCTION 0x2
|
||||
/* Octeon - Tell another core to flush its icache */
|
||||
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
|
||||
index 037a44d..62c4439 100644
|
||||
--- a/arch/mips/kernel/proc.c
|
||||
+++ b/arch/mips/kernel/proc.c
|
||||
@@ -123,6 +123,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
cpu_data[n].srsets);
|
||||
seq_printf(m, "kscratch registers\t: %d\n",
|
||||
hweight8(cpu_data[n].kscratch_mask));
|
||||
+ seq_printf(m, "package\t\t\t: %d\n", cpu_data[n].package);
|
||||
seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
|
||||
|
||||
sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
|
||||
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
|
||||
index 9bad52e..c94c4e9 100644
|
||||
--- a/arch/mips/kernel/smp.c
|
||||
+++ b/arch/mips/kernel/smp.c
|
||||
@@ -59,9 +59,16 @@ EXPORT_SYMBOL(smp_num_siblings);
|
||||
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
|
||||
EXPORT_SYMBOL(cpu_sibling_map);
|
||||
|
||||
+/* representing the core map of multi-core chips of each logical CPU */
|
||||
+cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
|
||||
+EXPORT_SYMBOL(cpu_core_map);
|
||||
+
|
||||
/* representing cpus for which sibling maps can be computed */
|
||||
static cpumask_t cpu_sibling_setup_map;
|
||||
|
||||
+/* representing cpus for which core maps can be computed */
|
||||
+static cpumask_t cpu_core_setup_map;
|
||||
+
|
||||
cpumask_t cpu_coherent_mask;
|
||||
|
||||
static inline void set_cpu_sibling_map(int cpu)
|
||||
@@ -72,7 +79,8 @@ static inline void set_cpu_sibling_map(int cpu)
|
||||
|
||||
if (smp_num_siblings > 1) {
|
||||
for_each_cpu_mask(i, cpu_sibling_setup_map) {
|
||||
- if (cpu_data[cpu].core == cpu_data[i].core) {
|
||||
+ if (cpu_data[cpu].package == cpu_data[i].package &&
|
||||
+ cpu_data[cpu].core == cpu_data[i].core) {
|
||||
cpu_set(i, cpu_sibling_map[cpu]);
|
||||
cpu_set(cpu, cpu_sibling_map[i]);
|
||||
}
|
||||
@@ -81,6 +89,20 @@ static inline void set_cpu_sibling_map(int cpu)
|
||||
cpu_set(cpu, cpu_sibling_map[cpu]);
|
||||
}
|
||||
|
||||
+static inline void set_cpu_core_map(int cpu)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ cpu_set(cpu, cpu_core_setup_map);
|
||||
+
|
||||
+ for_each_cpu_mask(i, cpu_core_setup_map) {
|
||||
+ if (cpu_data[cpu].package == cpu_data[i].package) {
|
||||
+ cpu_set(i, cpu_core_map[cpu]);
|
||||
+ cpu_set(cpu, cpu_core_map[i]);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
struct plat_smp_ops *mp_ops;
|
||||
EXPORT_SYMBOL(mp_ops);
|
||||
|
||||
@@ -122,6 +144,7 @@ asmlinkage void start_secondary(void)
|
||||
set_cpu_online(cpu, true);
|
||||
|
||||
set_cpu_sibling_map(cpu);
|
||||
+ set_cpu_core_map(cpu);
|
||||
|
||||
cpu_set(cpu, cpu_callin_map);
|
||||
|
||||
@@ -175,6 +198,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
current_thread_info()->cpu = 0;
|
||||
mp_ops->prepare_cpus(max_cpus);
|
||||
set_cpu_sibling_map(0);
|
||||
+ set_cpu_core_map(0);
|
||||
#ifndef CONFIG_HOTPLUG_CPU
|
||||
init_cpu_present(cpu_possible_mask);
|
||||
#endif
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
From: Huacai Chen <chenhc@lemote.com>
|
||||
Date: Thu, 26 Jun 2014 11:41:25 +0800
|
||||
Subject: [1/8] MIPS: Support hard limit of cpu count (nr_cpu_ids)
|
||||
Origin: https://git.kernel.org/linus/0f3f506b275517250ee0169ec075d5382967f5f6
|
||||
|
||||
On MIPS currently, only the soft limit of cpu count (maxcpus) has its
|
||||
effect, this patch enable the hard limit (nr_cpus) as well. Processor
|
||||
cores which greater than maxcpus and less than nr_cpus can be taken up
|
||||
via cpu hotplug. The code is borrowed from X86.
|
||||
|
||||
Signed-off-by: Huacai Chen <chenhc@lemote.com>
|
||||
Reviewed-by: Andreas Herrmann <andreas.herrmann@caviumnetworks.com>
|
||||
Cc: John Crispin <john@phrozen.org>
|
||||
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
|
||||
Cc: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Cc: Fuxin Zhang <zhangfx@lemote.com>
|
||||
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/7183/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/kernel/setup.c | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
|
||||
index a842154..2f01201 100644
|
||||
--- a/arch/mips/kernel/setup.c
|
||||
+++ b/arch/mips/kernel/setup.c
|
||||
@@ -729,6 +729,25 @@ static void __init resource_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_SMP
|
||||
+static void __init prefill_possible_map(void)
|
||||
+{
|
||||
+ int i, possible = num_possible_cpus();
|
||||
+
|
||||
+ if (possible > nr_cpu_ids)
|
||||
+ possible = nr_cpu_ids;
|
||||
+
|
||||
+ for (i = 0; i < possible; i++)
|
||||
+ set_cpu_possible(i, true);
|
||||
+ for (; i < NR_CPUS; i++)
|
||||
+ set_cpu_possible(i, false);
|
||||
+
|
||||
+ nr_cpu_ids = possible;
|
||||
+}
|
||||
+#else
|
||||
+static inline void prefill_possible_map(void) {}
|
||||
+#endif
|
||||
+
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
cpu_probe();
|
||||
@@ -752,6 +771,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
|
||||
resource_init();
|
||||
plat_smp_setup();
|
||||
+ prefill_possible_map();
|
||||
|
||||
cpu_cache_init();
|
||||
}
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Mon, 14 Jul 2014 18:33:08 +0200
|
||||
Subject: KVM: Allow KVM_CHECK_EXTENSION on the vm fd
|
||||
Origin: https://git.kernel.org/linus/92b591a4c46b103ebd3fc0d03a084e1efd331253
|
||||
|
||||
The KVM_CHECK_EXTENSION is only available on the kvm fd today. Unfortunately
|
||||
on PPC some of the capabilities change depending on the way a VM was created.
|
||||
|
||||
So instead we need a way to expose capabilities as VM ioctl, so that we can
|
||||
see which VM type we're using (HV or PR). To enable this, add the
|
||||
KVM_CHECK_EXTENSION ioctl to our vm ioctl portfolio.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
Documentation/virtual/kvm/api.txt | 7 +++--
|
||||
include/uapi/linux/kvm.h | 1 +
|
||||
virt/kvm/kvm_main.c | 58 ++++++++++++++++++++-----------------
|
||||
3 files changed, 37 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
|
||||
index 884f819..8898caf 100644
|
||||
--- a/Documentation/virtual/kvm/api.txt
|
||||
+++ b/Documentation/virtual/kvm/api.txt
|
||||
@@ -148,9 +148,9 @@ of banks, as set via the KVM_X86_SETUP_MCE ioctl.
|
||||
|
||||
4.4 KVM_CHECK_EXTENSION
|
||||
|
||||
-Capability: basic
|
||||
+Capability: basic, KVM_CAP_CHECK_EXTENSION_VM for vm ioctl
|
||||
Architectures: all
|
||||
-Type: system ioctl
|
||||
+Type: system ioctl, vm ioctl
|
||||
Parameters: extension identifier (KVM_CAP_*)
|
||||
Returns: 0 if unsupported; 1 (or some other positive integer) if supported
|
||||
|
||||
@@ -160,6 +160,9 @@ receives an integer that describes the extension availability.
|
||||
Generally 0 means no and 1 means yes, but some extensions may report
|
||||
additional information in the integer return value.
|
||||
|
||||
+Based on their initialization different VMs may have different capabilities.
|
||||
+It is thus encouraged to use the vm ioctl to query for capabilities (available
|
||||
+with KVM_CAP_CHECK_EXTENSION_VM on the vm fd)
|
||||
|
||||
4.5 KVM_GET_VCPU_MMAP_SIZE
|
||||
|
||||
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
|
||||
index 0418b74..51776ca 100644
|
||||
--- a/include/uapi/linux/kvm.h
|
||||
+++ b/include/uapi/linux/kvm.h
|
||||
@@ -759,6 +759,7 @@ struct kvm_ppc_smmu_info {
|
||||
#define KVM_CAP_ARM_PSCI_0_2 102
|
||||
#define KVM_CAP_PPC_FIXUP_HCALL 103
|
||||
#define KVM_CAP_PPC_ENABLE_HCALL 104
|
||||
+#define KVM_CAP_CHECK_EXTENSION_VM 105
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
|
||||
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
|
||||
index e28f3ca..1b95cc9 100644
|
||||
--- a/virt/kvm/kvm_main.c
|
||||
+++ b/virt/kvm/kvm_main.c
|
||||
@@ -2324,6 +2324,34 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
|
||||
+{
|
||||
+ switch (arg) {
|
||||
+ case KVM_CAP_USER_MEMORY:
|
||||
+ case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
|
||||
+ case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS:
|
||||
+#ifdef CONFIG_KVM_APIC_ARCHITECTURE
|
||||
+ case KVM_CAP_SET_BOOT_CPU_ID:
|
||||
+#endif
|
||||
+ case KVM_CAP_INTERNAL_ERROR_DATA:
|
||||
+#ifdef CONFIG_HAVE_KVM_MSI
|
||||
+ case KVM_CAP_SIGNAL_MSI:
|
||||
+#endif
|
||||
+#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
|
||||
+ case KVM_CAP_IRQFD_RESAMPLE:
|
||||
+#endif
|
||||
+ case KVM_CAP_CHECK_EXTENSION_VM:
|
||||
+ return 1;
|
||||
+#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
|
||||
+ case KVM_CAP_IRQ_ROUTING:
|
||||
+ return KVM_MAX_IRQ_ROUTES;
|
||||
+#endif
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ return kvm_vm_ioctl_check_extension(kvm, arg);
|
||||
+}
|
||||
+
|
||||
static long kvm_vm_ioctl(struct file *filp,
|
||||
unsigned int ioctl, unsigned long arg)
|
||||
{
|
||||
@@ -2487,6 +2515,9 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
+ case KVM_CHECK_EXTENSION:
|
||||
+ r = kvm_vm_ioctl_check_extension_generic(kvm, arg);
|
||||
+ break;
|
||||
default:
|
||||
r = kvm_arch_vm_ioctl(filp, ioctl, arg);
|
||||
if (r == -ENOTTY)
|
||||
@@ -2571,33 +2602,6 @@ static int kvm_dev_ioctl_create_vm(unsigned long type)
|
||||
return r;
|
||||
}
|
||||
|
||||
-static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
|
||||
-{
|
||||
- switch (arg) {
|
||||
- case KVM_CAP_USER_MEMORY:
|
||||
- case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
|
||||
- case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS:
|
||||
-#ifdef CONFIG_KVM_APIC_ARCHITECTURE
|
||||
- case KVM_CAP_SET_BOOT_CPU_ID:
|
||||
-#endif
|
||||
- case KVM_CAP_INTERNAL_ERROR_DATA:
|
||||
-#ifdef CONFIG_HAVE_KVM_MSI
|
||||
- case KVM_CAP_SIGNAL_MSI:
|
||||
-#endif
|
||||
-#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
|
||||
- case KVM_CAP_IRQFD_RESAMPLE:
|
||||
-#endif
|
||||
- return 1;
|
||||
-#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
|
||||
- case KVM_CAP_IRQ_ROUTING:
|
||||
- return KVM_MAX_IRQ_ROUTES;
|
||||
-#endif
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
- return kvm_vm_ioctl_check_extension(kvm, arg);
|
||||
-}
|
||||
-
|
||||
static long kvm_dev_ioctl(struct file *filp,
|
||||
unsigned int ioctl, unsigned long arg)
|
||||
{
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
From: Paul Mackerras <paulus@samba.org>
|
||||
Date: Mon, 30 Jun 2014 20:51:09 +1000
|
||||
Subject: KVM: Don't keep reference to irq routing table in
|
||||
irqfd struct
|
||||
Origin: https://git.kernel.org/linus/56f89f3629ffd1a21d38c3d0bea23deac0e284ce
|
||||
|
||||
This makes the irqfd code keep a copy of the irq routing table entry
|
||||
for each irqfd, rather than a reference to the copy in the actual
|
||||
irq routing table maintained in kvm/virt/irqchip.c. This will enable
|
||||
us to change the routing table structure in future, or even not have a
|
||||
routing table at all on some platforms.
|
||||
|
||||
The synchronization that was previously achieved using srcu_dereference
|
||||
on the read side is now achieved using a seqcount_t structure. That
|
||||
ensures that we don't get a halfway-updated copy of the structure if
|
||||
we read it while another thread is updating it.
|
||||
|
||||
We still use srcu_read_lock/unlock around the read side so that when
|
||||
changing the routing table we can be sure that after calling
|
||||
synchronize_srcu, nothing will be using the old routing.
|
||||
|
||||
Signed-off-by: Paul Mackerras <paulus@samba.org>
|
||||
Tested-by: Eric Auger <eric.auger@linaro.org>
|
||||
Tested-by: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
virt/kvm/eventfd.c | 41 +++++++++++++++++++++++++----------------
|
||||
1 file changed, 25 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
|
||||
index 20c3af7..bae593a 100644
|
||||
--- a/virt/kvm/eventfd.c
|
||||
+++ b/virt/kvm/eventfd.c
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/srcu.h>
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/seqlock.h>
|
||||
|
||||
#include "iodev.h"
|
||||
|
||||
@@ -75,7 +76,8 @@ struct _irqfd {
|
||||
struct kvm *kvm;
|
||||
wait_queue_t wait;
|
||||
/* Update side is protected by irqfds.lock */
|
||||
- struct kvm_kernel_irq_routing_entry __rcu *irq_entry;
|
||||
+ struct kvm_kernel_irq_routing_entry irq_entry;
|
||||
+ seqcount_t irq_entry_sc;
|
||||
/* Used for level IRQ fast-path */
|
||||
int gsi;
|
||||
struct work_struct inject;
|
||||
@@ -223,16 +225,20 @@ irqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
|
||||
{
|
||||
struct _irqfd *irqfd = container_of(wait, struct _irqfd, wait);
|
||||
unsigned long flags = (unsigned long)key;
|
||||
- struct kvm_kernel_irq_routing_entry *irq;
|
||||
+ struct kvm_kernel_irq_routing_entry irq;
|
||||
struct kvm *kvm = irqfd->kvm;
|
||||
+ unsigned seq;
|
||||
int idx;
|
||||
|
||||
if (flags & POLLIN) {
|
||||
idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
- irq = srcu_dereference(irqfd->irq_entry, &kvm->irq_srcu);
|
||||
+ do {
|
||||
+ seq = read_seqcount_begin(&irqfd->irq_entry_sc);
|
||||
+ irq = irqfd->irq_entry;
|
||||
+ } while (read_seqcount_retry(&irqfd->irq_entry_sc, seq));
|
||||
/* An event has been signaled, inject an interrupt */
|
||||
- if (irq)
|
||||
- kvm_set_msi(irq, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1,
|
||||
+ if (irq.type == KVM_IRQ_ROUTING_MSI)
|
||||
+ kvm_set_msi(&irq, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1,
|
||||
false);
|
||||
else
|
||||
schedule_work(&irqfd->inject);
|
||||
@@ -277,18 +283,20 @@ static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd,
|
||||
{
|
||||
struct kvm_kernel_irq_routing_entry *e;
|
||||
|
||||
- if (irqfd->gsi >= irq_rt->nr_rt_entries) {
|
||||
- rcu_assign_pointer(irqfd->irq_entry, NULL);
|
||||
- return;
|
||||
- }
|
||||
+ write_seqcount_begin(&irqfd->irq_entry_sc);
|
||||
+
|
||||
+ irqfd->irq_entry.type = 0;
|
||||
+ if (irqfd->gsi >= irq_rt->nr_rt_entries)
|
||||
+ goto out;
|
||||
|
||||
hlist_for_each_entry(e, &irq_rt->map[irqfd->gsi], link) {
|
||||
/* Only fast-path MSI. */
|
||||
if (e->type == KVM_IRQ_ROUTING_MSI)
|
||||
- rcu_assign_pointer(irqfd->irq_entry, e);
|
||||
- else
|
||||
- rcu_assign_pointer(irqfd->irq_entry, NULL);
|
||||
+ irqfd->irq_entry = *e;
|
||||
}
|
||||
+
|
||||
+ out:
|
||||
+ write_seqcount_end(&irqfd->irq_entry_sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -310,6 +318,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
||||
INIT_LIST_HEAD(&irqfd->list);
|
||||
INIT_WORK(&irqfd->inject, irqfd_inject);
|
||||
INIT_WORK(&irqfd->shutdown, irqfd_shutdown);
|
||||
+ seqcount_init(&irqfd->irq_entry_sc);
|
||||
|
||||
f = fdget(args->fd);
|
||||
if (!f.file) {
|
||||
@@ -466,14 +475,14 @@ kvm_irqfd_deassign(struct kvm *kvm, struct kvm_irqfd *args)
|
||||
list_for_each_entry_safe(irqfd, tmp, &kvm->irqfds.items, list) {
|
||||
if (irqfd->eventfd == eventfd && irqfd->gsi == args->gsi) {
|
||||
/*
|
||||
- * This rcu_assign_pointer is needed for when
|
||||
+ * This clearing of irq_entry.type is needed for when
|
||||
* another thread calls kvm_irq_routing_update before
|
||||
* we flush workqueue below (we synchronize with
|
||||
* kvm_irq_routing_update using irqfds.lock).
|
||||
- * It is paired with synchronize_srcu done by caller
|
||||
- * of that function.
|
||||
*/
|
||||
- rcu_assign_pointer(irqfd->irq_entry, NULL);
|
||||
+ write_seqcount_begin(&irqfd->irq_entry_sc);
|
||||
+ irqfd->irq_entry.type = 0;
|
||||
+ write_seqcount_end(&irqfd->irq_entry_sc);
|
||||
irqfd_deactivate(irqfd);
|
||||
}
|
||||
}
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
From: Paul Mackerras <paulus@samba.org>
|
||||
Date: Mon, 30 Jun 2014 20:51:13 +1000
|
||||
Subject: KVM: Give IRQFD its own separate enabling Kconfig
|
||||
option
|
||||
Origin: https://git.kernel.org/linus/297e21053a52f060944e9f0de4c64fad9bcd72fc
|
||||
|
||||
Currently, the IRQFD code is conditional on CONFIG_HAVE_KVM_IRQ_ROUTING.
|
||||
So that we can have the IRQFD code compiled in without having the
|
||||
IRQ routing code, this creates a new CONFIG_HAVE_KVM_IRQFD, makes
|
||||
the IRQFD code conditional on it instead of CONFIG_HAVE_KVM_IRQ_ROUTING,
|
||||
and makes all the platforms that currently select HAVE_KVM_IRQ_ROUTING
|
||||
also select HAVE_KVM_IRQFD.
|
||||
|
||||
Signed-off-by: Paul Mackerras <paulus@samba.org>
|
||||
Tested-by: Eric Auger <eric.auger@linaro.org>
|
||||
Tested-by: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
arch/ia64/kvm/Kconfig | 1 +
|
||||
arch/powerpc/kvm/Kconfig | 1 +
|
||||
arch/s390/kvm/Kconfig | 1 +
|
||||
arch/x86/kvm/Kconfig | 1 +
|
||||
include/linux/kvm_host.h | 8 ++++----
|
||||
virt/kvm/Kconfig | 3 +++
|
||||
virt/kvm/eventfd.c | 6 +++---
|
||||
virt/kvm/kvm_main.c | 2 +-
|
||||
8 files changed, 15 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
|
||||
index 990b864..3d50ea9 100644
|
||||
--- a/arch/ia64/kvm/Kconfig
|
||||
+++ b/arch/ia64/kvm/Kconfig
|
||||
@@ -25,6 +25,7 @@ config KVM
|
||||
select PREEMPT_NOTIFIERS
|
||||
select ANON_INODES
|
||||
select HAVE_KVM_IRQCHIP
|
||||
+ select HAVE_KVM_IRQFD
|
||||
select HAVE_KVM_IRQ_ROUTING
|
||||
select KVM_APIC_ARCHITECTURE
|
||||
select KVM_MMIO
|
||||
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
|
||||
index 8f104a6..d4741db 100644
|
||||
--- a/arch/powerpc/kvm/Kconfig
|
||||
+++ b/arch/powerpc/kvm/Kconfig
|
||||
@@ -158,6 +158,7 @@ config KVM_MPIC
|
||||
bool "KVM in-kernel MPIC emulation"
|
||||
depends on KVM && E500
|
||||
select HAVE_KVM_IRQCHIP
|
||||
+ select HAVE_KVM_IRQFD
|
||||
select HAVE_KVM_IRQ_ROUTING
|
||||
select HAVE_KVM_MSI
|
||||
help
|
||||
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
|
||||
index 10d529a..646db9c 100644
|
||||
--- a/arch/s390/kvm/Kconfig
|
||||
+++ b/arch/s390/kvm/Kconfig
|
||||
@@ -26,6 +26,7 @@ config KVM
|
||||
select KVM_ASYNC_PF
|
||||
select KVM_ASYNC_PF_SYNC
|
||||
select HAVE_KVM_IRQCHIP
|
||||
+ select HAVE_KVM_IRQFD
|
||||
select HAVE_KVM_IRQ_ROUTING
|
||||
---help---
|
||||
Support hosting paravirtualized guest machines using the SIE
|
||||
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
|
||||
index 287e4c8..f9d16ff 100644
|
||||
--- a/arch/x86/kvm/Kconfig
|
||||
+++ b/arch/x86/kvm/Kconfig
|
||||
@@ -27,6 +27,7 @@ config KVM
|
||||
select MMU_NOTIFIER
|
||||
select ANON_INODES
|
||||
select HAVE_KVM_IRQCHIP
|
||||
+ select HAVE_KVM_IRQFD
|
||||
select HAVE_KVM_IRQ_ROUTING
|
||||
select HAVE_KVM_EVENTFD
|
||||
select KVM_APIC_ARCHITECTURE
|
||||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
|
||||
index ddd33e1..8593d2e 100644
|
||||
--- a/include/linux/kvm_host.h
|
||||
+++ b/include/linux/kvm_host.h
|
||||
@@ -437,7 +437,7 @@ void kvm_vcpu_uninit(struct kvm_vcpu *vcpu);
|
||||
int __must_check vcpu_load(struct kvm_vcpu *vcpu);
|
||||
void vcpu_put(struct kvm_vcpu *vcpu);
|
||||
|
||||
-#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
|
||||
+#ifdef CONFIG_HAVE_KVM_IRQFD
|
||||
int kvm_irqfd_init(void);
|
||||
void kvm_irqfd_exit(void);
|
||||
#else
|
||||
@@ -932,20 +932,20 @@ int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
|
||||
const struct kvm_irq_routing_entry *ue);
|
||||
void kvm_free_irq_routing(struct kvm *kvm);
|
||||
|
||||
-int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
|
||||
-
|
||||
#else
|
||||
|
||||
static inline void kvm_free_irq_routing(struct kvm *kvm) {}
|
||||
|
||||
#endif
|
||||
|
||||
+int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
|
||||
+
|
||||
#ifdef CONFIG_HAVE_KVM_EVENTFD
|
||||
|
||||
void kvm_eventfd_init(struct kvm *kvm);
|
||||
int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args);
|
||||
|
||||
-#ifdef CONFIG_HAVE_KVM_IRQCHIP
|
||||
+#ifdef CONFIG_HAVE_KVM_IRQFD
|
||||
int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args);
|
||||
void kvm_irqfd_release(struct kvm *kvm);
|
||||
void kvm_irq_routing_update(struct kvm *);
|
||||
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
|
||||
index 13f2d19..fc0c5e6 100644
|
||||
--- a/virt/kvm/Kconfig
|
||||
+++ b/virt/kvm/Kconfig
|
||||
@@ -6,6 +6,9 @@ config HAVE_KVM
|
||||
config HAVE_KVM_IRQCHIP
|
||||
bool
|
||||
|
||||
+config HAVE_KVM_IRQFD
|
||||
+ bool
|
||||
+
|
||||
config HAVE_KVM_IRQ_ROUTING
|
||||
bool
|
||||
|
||||
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
|
||||
index 99957df..f5f6154 100644
|
||||
--- a/virt/kvm/eventfd.c
|
||||
+++ b/virt/kvm/eventfd.c
|
||||
@@ -39,7 +39,7 @@
|
||||
#include "irq.h"
|
||||
#include "iodev.h"
|
||||
|
||||
-#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
|
||||
+#ifdef CONFIG_HAVE_KVM_IRQFD
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* irqfd: Allows an fd to be used to inject an interrupt to the guest
|
||||
@@ -450,7 +450,7 @@ out:
|
||||
void
|
||||
kvm_eventfd_init(struct kvm *kvm)
|
||||
{
|
||||
-#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
|
||||
+#ifdef CONFIG_HAVE_KVM_IRQFD
|
||||
spin_lock_init(&kvm->irqfds.lock);
|
||||
INIT_LIST_HEAD(&kvm->irqfds.items);
|
||||
INIT_LIST_HEAD(&kvm->irqfds.resampler_list);
|
||||
@@ -459,7 +459,7 @@ kvm_eventfd_init(struct kvm *kvm)
|
||||
INIT_LIST_HEAD(&kvm->ioeventfds);
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
|
||||
+#ifdef CONFIG_HAVE_KVM_IRQFD
|
||||
/*
|
||||
* shutdown any irqfd's that match fd+gsi
|
||||
*/
|
||||
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
|
||||
index 1b95cc9..a69a623 100644
|
||||
--- a/virt/kvm/kvm_main.c
|
||||
+++ b/virt/kvm/kvm_main.c
|
||||
@@ -2337,7 +2337,7 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
|
||||
#ifdef CONFIG_HAVE_KVM_MSI
|
||||
case KVM_CAP_SIGNAL_MSI:
|
||||
#endif
|
||||
-#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
|
||||
+#ifdef CONFIG_HAVE_KVM_IRQFD
|
||||
case KVM_CAP_IRQFD_RESAMPLE:
|
||||
#endif
|
||||
case KVM_CAP_CHECK_EXTENSION_VM:
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,317 +0,0 @@
|
|||
From: Paul Mackerras <paulus@samba.org>
|
||||
Date: Mon, 30 Jun 2014 20:51:11 +1000
|
||||
Subject: KVM: Move all accesses to kvm::irq_routing into
|
||||
irqchip.c
|
||||
Origin: https://git.kernel.org/linus/9957c86d659a4d5a2bed25ccbd3bfc9c3f25e658
|
||||
|
||||
Now that struct _irqfd does not keep a reference to storage pointed
|
||||
to by the irq_routing field of struct kvm, we can move the statement
|
||||
that updates it out from under the irqfds.lock and put it in
|
||||
kvm_set_irq_routing() instead. That means we then have to take a
|
||||
srcu_read_lock on kvm->irq_srcu around the irqfd_update call in
|
||||
kvm_irqfd_assign(), since holding the kvm->irqfds.lock no longer
|
||||
ensures that that the routing can't change.
|
||||
|
||||
Combined with changing kvm_irq_map_gsi() and kvm_irq_map_chip_pin()
|
||||
to take a struct kvm * argument instead of the pointer to the routing
|
||||
table, this allows us to to move all references to kvm->irq_routing
|
||||
into irqchip.c. That in turn allows us to move the definition of the
|
||||
kvm_irq_routing_table struct into irqchip.c as well.
|
||||
|
||||
Signed-off-by: Paul Mackerras <paulus@samba.org>
|
||||
Tested-by: Eric Auger <eric.auger@linaro.org>
|
||||
Tested-by: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
include/linux/kvm_host.h | 35 +++++++----------------------------
|
||||
virt/kvm/eventfd.c | 22 +++++++++-------------
|
||||
virt/kvm/irq_comm.c | 6 ++----
|
||||
virt/kvm/irqchip.c | 39 +++++++++++++++++++++++++--------------
|
||||
4 files changed, 43 insertions(+), 59 deletions(-)
|
||||
|
||||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
|
||||
index 4956149..ddd33e1 100644
|
||||
--- a/include/linux/kvm_host.h
|
||||
+++ b/include/linux/kvm_host.h
|
||||
@@ -325,24 +325,7 @@ struct kvm_kernel_irq_routing_entry {
|
||||
struct hlist_node link;
|
||||
};
|
||||
|
||||
-#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
|
||||
-
|
||||
-struct kvm_irq_routing_table {
|
||||
- int chip[KVM_NR_IRQCHIPS][KVM_IRQCHIP_NUM_PINS];
|
||||
- struct kvm_kernel_irq_routing_entry *rt_entries;
|
||||
- u32 nr_rt_entries;
|
||||
- /*
|
||||
- * Array indexed by gsi. Each entry contains list of irq chips
|
||||
- * the gsi is connected to.
|
||||
- */
|
||||
- struct hlist_head map[0];
|
||||
-};
|
||||
-
|
||||
-#else
|
||||
-
|
||||
-struct kvm_irq_routing_table {};
|
||||
-
|
||||
-#endif
|
||||
+struct kvm_irq_routing_table;
|
||||
|
||||
#ifndef KVM_PRIVATE_MEM_SLOTS
|
||||
#define KVM_PRIVATE_MEM_SLOTS 0
|
||||
@@ -401,8 +384,7 @@ struct kvm {
|
||||
struct mutex irq_lock;
|
||||
#ifdef CONFIG_HAVE_KVM_IRQCHIP
|
||||
/*
|
||||
- * Update side is protected by irq_lock and,
|
||||
- * if configured, irqfds.lock.
|
||||
+ * Update side is protected by irq_lock.
|
||||
*/
|
||||
struct kvm_irq_routing_table __rcu *irq_routing;
|
||||
struct hlist_head mask_notifier_list;
|
||||
@@ -752,10 +734,9 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
|
||||
void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
|
||||
bool mask);
|
||||
|
||||
-int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries,
|
||||
- struct kvm_irq_routing_table *irq_rt, int gsi);
|
||||
-int kvm_irq_map_chip_pin(struct kvm_irq_routing_table *irq_rt,
|
||||
- unsigned irqchip, unsigned pin);
|
||||
+int kvm_irq_map_gsi(struct kvm *kvm,
|
||||
+ struct kvm_kernel_irq_routing_entry *entries, int gsi);
|
||||
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin);
|
||||
|
||||
int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
|
||||
bool line_status);
|
||||
@@ -967,7 +948,7 @@ int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args);
|
||||
#ifdef CONFIG_HAVE_KVM_IRQCHIP
|
||||
int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args);
|
||||
void kvm_irqfd_release(struct kvm *kvm);
|
||||
-void kvm_irq_routing_update(struct kvm *, struct kvm_irq_routing_table *);
|
||||
+void kvm_irq_routing_update(struct kvm *);
|
||||
#else
|
||||
static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
|
||||
{
|
||||
@@ -989,10 +970,8 @@ static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
|
||||
static inline void kvm_irqfd_release(struct kvm *kvm) {}
|
||||
|
||||
#ifdef CONFIG_HAVE_KVM_IRQCHIP
|
||||
-static inline void kvm_irq_routing_update(struct kvm *kvm,
|
||||
- struct kvm_irq_routing_table *irq_rt)
|
||||
+static inline void kvm_irq_routing_update(struct kvm *kvm)
|
||||
{
|
||||
- rcu_assign_pointer(kvm->irq_routing, irq_rt);
|
||||
}
|
||||
#endif
|
||||
|
||||
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
|
||||
index 15fa948..f0075ff 100644
|
||||
--- a/virt/kvm/eventfd.c
|
||||
+++ b/virt/kvm/eventfd.c
|
||||
@@ -278,14 +278,13 @@ irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh,
|
||||
}
|
||||
|
||||
/* Must be called under irqfds.lock */
|
||||
-static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd,
|
||||
- struct kvm_irq_routing_table *irq_rt)
|
||||
+static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd)
|
||||
{
|
||||
struct kvm_kernel_irq_routing_entry *e;
|
||||
struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS];
|
||||
int i, n_entries;
|
||||
|
||||
- n_entries = kvm_irq_map_gsi(entries, irq_rt, irqfd->gsi);
|
||||
+ n_entries = kvm_irq_map_gsi(kvm, entries, irqfd->gsi);
|
||||
|
||||
write_seqcount_begin(&irqfd->irq_entry_sc);
|
||||
|
||||
@@ -304,12 +303,12 @@ static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd,
|
||||
static int
|
||||
kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
||||
{
|
||||
- struct kvm_irq_routing_table *irq_rt;
|
||||
struct _irqfd *irqfd, *tmp;
|
||||
struct fd f;
|
||||
struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL;
|
||||
int ret;
|
||||
unsigned int events;
|
||||
+ int idx;
|
||||
|
||||
irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL);
|
||||
if (!irqfd)
|
||||
@@ -403,9 +402,9 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- irq_rt = rcu_dereference_protected(kvm->irq_routing,
|
||||
- lockdep_is_held(&kvm->irqfds.lock));
|
||||
- irqfd_update(kvm, irqfd, irq_rt);
|
||||
+ idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
+ irqfd_update(kvm, irqfd);
|
||||
+ srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
|
||||
list_add_tail(&irqfd->list, &kvm->irqfds.items);
|
||||
|
||||
@@ -539,20 +538,17 @@ kvm_irqfd_release(struct kvm *kvm)
|
||||
}
|
||||
|
||||
/*
|
||||
- * Change irq_routing and irqfd.
|
||||
+ * Take note of a change in irq routing.
|
||||
* Caller must invoke synchronize_srcu(&kvm->irq_srcu) afterwards.
|
||||
*/
|
||||
-void kvm_irq_routing_update(struct kvm *kvm,
|
||||
- struct kvm_irq_routing_table *irq_rt)
|
||||
+void kvm_irq_routing_update(struct kvm *kvm)
|
||||
{
|
||||
struct _irqfd *irqfd;
|
||||
|
||||
spin_lock_irq(&kvm->irqfds.lock);
|
||||
|
||||
- rcu_assign_pointer(kvm->irq_routing, irq_rt);
|
||||
-
|
||||
list_for_each_entry(irqfd, &kvm->irqfds.items, list)
|
||||
- irqfd_update(kvm, irqfd, irq_rt);
|
||||
+ irqfd_update(kvm, irqfd);
|
||||
|
||||
spin_unlock_irq(&kvm->irqfds.lock);
|
||||
}
|
||||
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
|
||||
index 1758445..963b899 100644
|
||||
--- a/virt/kvm/irq_comm.c
|
||||
+++ b/virt/kvm/irq_comm.c
|
||||
@@ -163,7 +163,6 @@ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level)
|
||||
struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS];
|
||||
struct kvm_kernel_irq_routing_entry *e;
|
||||
int ret = -EINVAL;
|
||||
- struct kvm_irq_routing_table *irq_rt;
|
||||
int idx;
|
||||
|
||||
trace_kvm_set_irq(irq, level, irq_source_id);
|
||||
@@ -177,8 +176,7 @@ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level)
|
||||
* which is limited to 1:1 GSI mapping.
|
||||
*/
|
||||
idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
- irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
|
||||
- if (kvm_irq_map_gsi(entries, irq_rt, irq) > 0) {
|
||||
+ if (kvm_irq_map_gsi(kvm, entries, irq) > 0) {
|
||||
e = &entries[0];
|
||||
if (likely(e->type == KVM_IRQ_ROUTING_MSI))
|
||||
ret = kvm_set_msi_inatomic(e, kvm);
|
||||
@@ -264,7 +262,7 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
|
||||
int idx, gsi;
|
||||
|
||||
idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
- gsi = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu)->chip[irqchip][pin];
|
||||
+ gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
|
||||
if (gsi != -1)
|
||||
hlist_for_each_entry_rcu(kimn, &kvm->mask_notifier_list, link)
|
||||
if (kimn->irq == gsi)
|
||||
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
|
||||
index f4648dd..04faac5 100644
|
||||
--- a/virt/kvm/irqchip.c
|
||||
+++ b/virt/kvm/irqchip.c
|
||||
@@ -31,12 +31,26 @@
|
||||
#include <trace/events/kvm.h>
|
||||
#include "irq.h"
|
||||
|
||||
-int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries,
|
||||
- struct kvm_irq_routing_table *irq_rt, int gsi)
|
||||
+struct kvm_irq_routing_table {
|
||||
+ int chip[KVM_NR_IRQCHIPS][KVM_IRQCHIP_NUM_PINS];
|
||||
+ struct kvm_kernel_irq_routing_entry *rt_entries;
|
||||
+ u32 nr_rt_entries;
|
||||
+ /*
|
||||
+ * Array indexed by gsi. Each entry contains list of irq chips
|
||||
+ * the gsi is connected to.
|
||||
+ */
|
||||
+ struct hlist_head map[0];
|
||||
+};
|
||||
+
|
||||
+int kvm_irq_map_gsi(struct kvm *kvm,
|
||||
+ struct kvm_kernel_irq_routing_entry *entries, int gsi)
|
||||
{
|
||||
+ struct kvm_irq_routing_table *irq_rt;
|
||||
struct kvm_kernel_irq_routing_entry *e;
|
||||
int n = 0;
|
||||
|
||||
+ irq_rt = srcu_dereference_check(kvm->irq_routing, &kvm->irq_srcu,
|
||||
+ lockdep_is_held(&kvm->irq_lock));
|
||||
if (gsi < irq_rt->nr_rt_entries) {
|
||||
hlist_for_each_entry(e, &irq_rt->map[gsi], link) {
|
||||
entries[n] = *e;
|
||||
@@ -47,21 +61,21 @@ int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries,
|
||||
return n;
|
||||
}
|
||||
|
||||
-int kvm_irq_map_chip_pin(struct kvm_irq_routing_table *irq_rt,
|
||||
- unsigned irqchip, unsigned pin)
|
||||
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin)
|
||||
{
|
||||
+ struct kvm_irq_routing_table *irq_rt;
|
||||
+
|
||||
+ irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
|
||||
return irq_rt->chip[irqchip][pin];
|
||||
}
|
||||
|
||||
bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin)
|
||||
{
|
||||
- struct kvm_irq_routing_table *irq_rt;
|
||||
struct kvm_irq_ack_notifier *kian;
|
||||
int gsi, idx;
|
||||
|
||||
idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
- irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
|
||||
- gsi = kvm_irq_map_chip_pin(irq_rt, irqchip, pin);
|
||||
+ gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
|
||||
if (gsi != -1)
|
||||
hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
|
||||
link)
|
||||
@@ -78,15 +92,13 @@ EXPORT_SYMBOL_GPL(kvm_irq_has_notifier);
|
||||
|
||||
void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
|
||||
{
|
||||
- struct kvm_irq_routing_table *irq_rt;
|
||||
struct kvm_irq_ack_notifier *kian;
|
||||
int gsi, idx;
|
||||
|
||||
trace_kvm_ack_irq(irqchip, pin);
|
||||
|
||||
idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
- irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
|
||||
- gsi = kvm_irq_map_chip_pin(irq_rt, irqchip, pin);
|
||||
+ gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
|
||||
if (gsi != -1)
|
||||
hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
|
||||
link)
|
||||
@@ -143,7 +155,6 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
|
||||
{
|
||||
struct kvm_kernel_irq_routing_entry irq_set[KVM_NR_IRQCHIPS];
|
||||
int ret = -1, i, idx;
|
||||
- struct kvm_irq_routing_table *irq_rt;
|
||||
|
||||
trace_kvm_set_irq(irq, level, irq_source_id);
|
||||
|
||||
@@ -152,8 +163,7 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
|
||||
* writes to the unused one.
|
||||
*/
|
||||
idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
- irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
|
||||
- i = kvm_irq_map_gsi(irq_set, irq_rt, irq);
|
||||
+ i = kvm_irq_map_gsi(kvm, irq_set, irq);
|
||||
srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
|
||||
while(i--) {
|
||||
@@ -250,7 +260,8 @@ int kvm_set_irq_routing(struct kvm *kvm,
|
||||
|
||||
mutex_lock(&kvm->irq_lock);
|
||||
old = kvm->irq_routing;
|
||||
- kvm_irq_routing_update(kvm, new);
|
||||
+ rcu_assign_pointer(kvm->irq_routing, new);
|
||||
+ kvm_irq_routing_update(kvm);
|
||||
mutex_unlock(&kvm->irq_lock);
|
||||
|
||||
synchronize_srcu_expedited(&kvm->irq_srcu);
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
From: Paul Mackerras <paulus@samba.org>
|
||||
Date: Mon, 30 Jun 2014 20:51:12 +1000
|
||||
Subject: KVM: Move irq notifier implementation into eventfd.c
|
||||
Origin: https://git.kernel.org/linus/e4d57e1ee1ab59f0cef0272800ac6c52e0ec814a
|
||||
|
||||
This moves the functions kvm_irq_has_notifier(), kvm_notify_acked_irq(),
|
||||
kvm_register_irq_ack_notifier() and kvm_unregister_irq_ack_notifier()
|
||||
from irqchip.c to eventfd.c. The reason for doing this is that those
|
||||
functions are used in connection with IRQFDs, which are implemented in
|
||||
eventfd.c. In future we will want to use IRQFDs on platforms that
|
||||
don't implement the GSI routing implemented in irqchip.c, so we won't
|
||||
be compiling in irqchip.c, but we still need the irq notifiers. The
|
||||
implementation is unchanged.
|
||||
|
||||
Signed-off-by: Paul Mackerras <paulus@samba.org>
|
||||
Tested-by: Eric Auger <eric.auger@linaro.org>
|
||||
Tested-by: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
virt/kvm/eventfd.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
virt/kvm/irqchip.c | 61 --------------------------------------------------
|
||||
2 files changed, 63 insertions(+), 61 deletions(-)
|
||||
|
||||
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
|
||||
index f0075ff..99957df 100644
|
||||
--- a/virt/kvm/eventfd.c
|
||||
+++ b/virt/kvm/eventfd.c
|
||||
@@ -34,7 +34,9 @@
|
||||
#include <linux/srcu.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seqlock.h>
|
||||
+#include <trace/events/kvm.h>
|
||||
|
||||
+#include "irq.h"
|
||||
#include "iodev.h"
|
||||
|
||||
#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
|
||||
@@ -865,3 +867,64 @@ kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
|
||||
|
||||
return kvm_assign_ioeventfd(kvm, args);
|
||||
}
|
||||
+
|
||||
+bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin)
|
||||
+{
|
||||
+ struct kvm_irq_ack_notifier *kian;
|
||||
+ int gsi, idx;
|
||||
+
|
||||
+ idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
+ gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
|
||||
+ if (gsi != -1)
|
||||
+ hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
|
||||
+ link)
|
||||
+ if (kian->gsi == gsi) {
|
||||
+ srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(kvm_irq_has_notifier);
|
||||
+
|
||||
+void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
|
||||
+{
|
||||
+ struct kvm_irq_ack_notifier *kian;
|
||||
+ int gsi, idx;
|
||||
+
|
||||
+ trace_kvm_ack_irq(irqchip, pin);
|
||||
+
|
||||
+ idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
+ gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
|
||||
+ if (gsi != -1)
|
||||
+ hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
|
||||
+ link)
|
||||
+ if (kian->gsi == gsi)
|
||||
+ kian->irq_acked(kian);
|
||||
+ srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
+}
|
||||
+
|
||||
+void kvm_register_irq_ack_notifier(struct kvm *kvm,
|
||||
+ struct kvm_irq_ack_notifier *kian)
|
||||
+{
|
||||
+ mutex_lock(&kvm->irq_lock);
|
||||
+ hlist_add_head_rcu(&kian->link, &kvm->irq_ack_notifier_list);
|
||||
+ mutex_unlock(&kvm->irq_lock);
|
||||
+#ifdef __KVM_HAVE_IOAPIC
|
||||
+ kvm_vcpu_request_scan_ioapic(kvm);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
|
||||
+ struct kvm_irq_ack_notifier *kian)
|
||||
+{
|
||||
+ mutex_lock(&kvm->irq_lock);
|
||||
+ hlist_del_init_rcu(&kian->link);
|
||||
+ mutex_unlock(&kvm->irq_lock);
|
||||
+ synchronize_srcu(&kvm->irq_srcu);
|
||||
+#ifdef __KVM_HAVE_IOAPIC
|
||||
+ kvm_vcpu_request_scan_ioapic(kvm);
|
||||
+#endif
|
||||
+}
|
||||
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
|
||||
index 04faac5..7f256f3 100644
|
||||
--- a/virt/kvm/irqchip.c
|
||||
+++ b/virt/kvm/irqchip.c
|
||||
@@ -69,67 +69,6 @@ int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin)
|
||||
return irq_rt->chip[irqchip][pin];
|
||||
}
|
||||
|
||||
-bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin)
|
||||
-{
|
||||
- struct kvm_irq_ack_notifier *kian;
|
||||
- int gsi, idx;
|
||||
-
|
||||
- idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
- gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
|
||||
- if (gsi != -1)
|
||||
- hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
|
||||
- link)
|
||||
- if (kian->gsi == gsi) {
|
||||
- srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
-
|
||||
- return false;
|
||||
-}
|
||||
-EXPORT_SYMBOL_GPL(kvm_irq_has_notifier);
|
||||
-
|
||||
-void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
|
||||
-{
|
||||
- struct kvm_irq_ack_notifier *kian;
|
||||
- int gsi, idx;
|
||||
-
|
||||
- trace_kvm_ack_irq(irqchip, pin);
|
||||
-
|
||||
- idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
- gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
|
||||
- if (gsi != -1)
|
||||
- hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
|
||||
- link)
|
||||
- if (kian->gsi == gsi)
|
||||
- kian->irq_acked(kian);
|
||||
- srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
-}
|
||||
-
|
||||
-void kvm_register_irq_ack_notifier(struct kvm *kvm,
|
||||
- struct kvm_irq_ack_notifier *kian)
|
||||
-{
|
||||
- mutex_lock(&kvm->irq_lock);
|
||||
- hlist_add_head_rcu(&kian->link, &kvm->irq_ack_notifier_list);
|
||||
- mutex_unlock(&kvm->irq_lock);
|
||||
-#ifdef __KVM_HAVE_IOAPIC
|
||||
- kvm_vcpu_request_scan_ioapic(kvm);
|
||||
-#endif
|
||||
-}
|
||||
-
|
||||
-void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
|
||||
- struct kvm_irq_ack_notifier *kian)
|
||||
-{
|
||||
- mutex_lock(&kvm->irq_lock);
|
||||
- hlist_del_init_rcu(&kian->link);
|
||||
- mutex_unlock(&kvm->irq_lock);
|
||||
- synchronize_srcu(&kvm->irq_srcu);
|
||||
-#ifdef __KVM_HAVE_IOAPIC
|
||||
- kvm_vcpu_request_scan_ioapic(kvm);
|
||||
-#endif
|
||||
-}
|
||||
-
|
||||
int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
|
||||
{
|
||||
struct kvm_kernel_irq_routing_entry route;
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,422 +0,0 @@
|
|||
From: Paul Mackerras <paulus@samba.org>
|
||||
Date: Mon, 2 Jun 2014 11:02:59 +1000
|
||||
Subject: KVM: PPC: Book3S: Controls for in-kernel sPAPR
|
||||
hypercall handling
|
||||
Origin: https://git.kernel.org/linus/699a0ea0823d32030b0666b28ff8633960f7ffa7
|
||||
|
||||
This provides a way for userspace controls which sPAPR hcalls get
|
||||
handled in the kernel. Each hcall can be individually enabled or
|
||||
disabled for in-kernel handling, except for H_RTAS. The exception
|
||||
for H_RTAS is because userspace can already control whether
|
||||
individual RTAS functions are handled in-kernel or not via the
|
||||
KVM_PPC_RTAS_DEFINE_TOKEN ioctl, and because the numeric value for
|
||||
H_RTAS is out of the normal sequence of hcall numbers.
|
||||
|
||||
Hcalls are enabled or disabled using the KVM_ENABLE_CAP ioctl for the
|
||||
KVM_CAP_PPC_ENABLE_HCALL capability on the file descriptor for the VM.
|
||||
The args field of the struct kvm_enable_cap specifies the hcall number
|
||||
in args[0] and the enable/disable flag in args[1]; 0 means disable
|
||||
in-kernel handling (so that the hcall will always cause an exit to
|
||||
userspace) and 1 means enable. Enabling or disabling in-kernel
|
||||
handling of an hcall is effective across the whole VM.
|
||||
|
||||
The ability for KVM_ENABLE_CAP to be used on a VM file descriptor
|
||||
on PowerPC is new, added by this commit. The KVM_CAP_ENABLE_CAP_VM
|
||||
capability advertises that this ability exists.
|
||||
|
||||
When a VM is created, an initial set of hcalls are enabled for
|
||||
in-kernel handling. The set that is enabled is the set that have
|
||||
an in-kernel implementation at this point. Any new hcall
|
||||
implementations from this point onwards should not be added to the
|
||||
default set without a good reason.
|
||||
|
||||
No distinction is made between real-mode and virtual-mode hcall
|
||||
implementations; the one setting controls them both.
|
||||
|
||||
Signed-off-by: Paul Mackerras <paulus@samba.org>
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
Documentation/virtual/kvm/api.txt | 41 +++++++++++++++++++++++--
|
||||
arch/powerpc/include/asm/kvm_book3s.h | 1 +
|
||||
arch/powerpc/include/asm/kvm_host.h | 2 ++
|
||||
arch/powerpc/kernel/asm-offsets.c | 1 +
|
||||
arch/powerpc/kvm/book3s_hv.c | 51 +++++++++++++++++++++++++++++++
|
||||
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 11 +++++++
|
||||
arch/powerpc/kvm/book3s_pr.c | 5 +++
|
||||
arch/powerpc/kvm/book3s_pr_papr.c | 37 ++++++++++++++++++++++
|
||||
arch/powerpc/kvm/powerpc.c | 45 +++++++++++++++++++++++++++
|
||||
include/uapi/linux/kvm.h | 1 +
|
||||
10 files changed, 193 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
|
||||
index 0fe3649..5c54d19 100644
|
||||
--- a/Documentation/virtual/kvm/api.txt
|
||||
+++ b/Documentation/virtual/kvm/api.txt
|
||||
@@ -2863,8 +2863,8 @@ The fields in each entry are defined as follows:
|
||||
this function/index combination
|
||||
|
||||
|
||||
-6. Capabilities that can be enabled
|
||||
------------------------------------
|
||||
+6. Capabilities that can be enabled on vCPUs
|
||||
+--------------------------------------------
|
||||
|
||||
There are certain capabilities that change the behavior of the virtual CPU when
|
||||
enabled. To enable them, please see section 4.37. Below you can find a list of
|
||||
@@ -3002,3 +3002,40 @@ Parameters: args[0] is the XICS device fd
|
||||
args[1] is the XICS CPU number (server ID) for this vcpu
|
||||
|
||||
This capability connects the vcpu to an in-kernel XICS device.
|
||||
+
|
||||
+
|
||||
+7. Capabilities that can be enabled on VMs
|
||||
+------------------------------------------
|
||||
+
|
||||
+There are certain capabilities that change the behavior of the virtual
|
||||
+machine when enabled. To enable them, please see section 4.37. Below
|
||||
+you can find a list of capabilities and what their effect on the VM
|
||||
+is when enabling them.
|
||||
+
|
||||
+The following information is provided along with the description:
|
||||
+
|
||||
+ Architectures: which instruction set architectures provide this ioctl.
|
||||
+ x86 includes both i386 and x86_64.
|
||||
+
|
||||
+ Parameters: what parameters are accepted by the capability.
|
||||
+
|
||||
+ Returns: the return value. General error numbers (EBADF, ENOMEM, EINVAL)
|
||||
+ are not detailed, but errors with specific meanings are.
|
||||
+
|
||||
+
|
||||
+7.1 KVM_CAP_PPC_ENABLE_HCALL
|
||||
+
|
||||
+Architectures: ppc
|
||||
+Parameters: args[0] is the sPAPR hcall number
|
||||
+ args[1] is 0 to disable, 1 to enable in-kernel handling
|
||||
+
|
||||
+This capability controls whether individual sPAPR hypercalls (hcalls)
|
||||
+get handled by the kernel or not. Enabling or disabling in-kernel
|
||||
+handling of an hcall is effective across the VM. On creation, an
|
||||
+initial set of hcalls are enabled for in-kernel handling, which
|
||||
+consists of those hcalls for which in-kernel handlers were implemented
|
||||
+before this capability was implemented. If disabled, the kernel will
|
||||
+not to attempt to handle the hcall, but will always exit to userspace
|
||||
+to handle it. Note that it may not make sense to enable some and
|
||||
+disable others of a group of related hcalls, but KVM does not prevent
|
||||
+userspace from doing that.
|
||||
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
|
||||
index a20cc0b..052ab2a 100644
|
||||
--- a/arch/powerpc/include/asm/kvm_book3s.h
|
||||
+++ b/arch/powerpc/include/asm/kvm_book3s.h
|
||||
@@ -187,6 +187,7 @@ extern void kvmppc_hv_entry_trampoline(void);
|
||||
extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
|
||||
extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
|
||||
extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
|
||||
+extern void kvmppc_pr_init_default_hcalls(struct kvm *kvm);
|
||||
extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
|
||||
struct kvm_vcpu *vcpu);
|
||||
extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
|
||||
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
|
||||
index f9ae696..62b2cee 100644
|
||||
--- a/arch/powerpc/include/asm/kvm_host.h
|
||||
+++ b/arch/powerpc/include/asm/kvm_host.h
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/cacheflush.h>
|
||||
+#include <asm/hvcall.h>
|
||||
|
||||
#define KVM_MAX_VCPUS NR_CPUS
|
||||
#define KVM_MAX_VCORES NR_CPUS
|
||||
@@ -263,6 +264,7 @@ struct kvm_arch {
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
struct list_head spapr_tce_tables;
|
||||
struct list_head rtas_tokens;
|
||||
+ DECLARE_BITMAP(enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
|
||||
#endif
|
||||
#ifdef CONFIG_KVM_MPIC
|
||||
struct openpic *mpic;
|
||||
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
|
||||
index f5995a9..17ffcb4 100644
|
||||
--- a/arch/powerpc/kernel/asm-offsets.c
|
||||
+++ b/arch/powerpc/kernel/asm-offsets.c
|
||||
@@ -493,6 +493,7 @@ int main(void)
|
||||
DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1));
|
||||
DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock));
|
||||
DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits));
|
||||
+ DEFINE(KVM_ENABLED_HCALLS, offsetof(struct kvm, arch.enabled_hcalls));
|
||||
DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
|
||||
DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
|
||||
DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v));
|
||||
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
|
||||
index 1562acf..cf445d2 100644
|
||||
--- a/arch/powerpc/kvm/book3s_hv.c
|
||||
+++ b/arch/powerpc/kvm/book3s_hv.c
|
||||
@@ -67,6 +67,8 @@
|
||||
/* Used as a "null" value for timebase values */
|
||||
#define TB_NIL (~(u64)0)
|
||||
|
||||
+static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
|
||||
+
|
||||
static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
|
||||
static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
|
||||
|
||||
@@ -562,6 +564,10 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
|
||||
struct kvm_vcpu *tvcpu;
|
||||
int idx, rc;
|
||||
|
||||
+ if (req <= MAX_HCALL_OPCODE &&
|
||||
+ !test_bit(req/4, vcpu->kvm->arch.enabled_hcalls))
|
||||
+ return RESUME_HOST;
|
||||
+
|
||||
switch (req) {
|
||||
case H_ENTER:
|
||||
idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||
@@ -2269,6 +2275,10 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
|
||||
*/
|
||||
cpumask_setall(&kvm->arch.need_tlb_flush);
|
||||
|
||||
+ /* Start out with the default set of hcalls enabled */
|
||||
+ memcpy(kvm->arch.enabled_hcalls, default_enabled_hcalls,
|
||||
+ sizeof(kvm->arch.enabled_hcalls));
|
||||
+
|
||||
kvm->arch.rma = NULL;
|
||||
|
||||
kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
|
||||
@@ -2407,6 +2417,45 @@ static long kvm_arch_vm_ioctl_hv(struct file *filp,
|
||||
return r;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * List of hcall numbers to enable by default.
|
||||
+ * For compatibility with old userspace, we enable by default
|
||||
+ * all hcalls that were implemented before the hcall-enabling
|
||||
+ * facility was added. Note this list should not include H_RTAS.
|
||||
+ */
|
||||
+static unsigned int default_hcall_list[] = {
|
||||
+ H_REMOVE,
|
||||
+ H_ENTER,
|
||||
+ H_READ,
|
||||
+ H_PROTECT,
|
||||
+ H_BULK_REMOVE,
|
||||
+ H_GET_TCE,
|
||||
+ H_PUT_TCE,
|
||||
+ H_SET_DABR,
|
||||
+ H_SET_XDABR,
|
||||
+ H_CEDE,
|
||||
+ H_PROD,
|
||||
+ H_CONFER,
|
||||
+ H_REGISTER_VPA,
|
||||
+#ifdef CONFIG_KVM_XICS
|
||||
+ H_EOI,
|
||||
+ H_CPPR,
|
||||
+ H_IPI,
|
||||
+ H_IPOLL,
|
||||
+ H_XIRR,
|
||||
+ H_XIRR_X,
|
||||
+#endif
|
||||
+ 0
|
||||
+};
|
||||
+
|
||||
+static void init_default_hcalls(void)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; default_hcall_list[i]; ++i)
|
||||
+ __set_bit(default_hcall_list[i] / 4, default_enabled_hcalls);
|
||||
+}
|
||||
+
|
||||
static struct kvmppc_ops kvm_ops_hv = {
|
||||
.get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv,
|
||||
.set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv,
|
||||
@@ -2454,6 +2503,8 @@ static int kvmppc_book3s_init_hv(void)
|
||||
kvm_ops_hv.owner = THIS_MODULE;
|
||||
kvmppc_hv_ops = &kvm_ops_hv;
|
||||
|
||||
+ init_default_hcalls();
|
||||
+
|
||||
r = kvmppc_mmu_hv_init();
|
||||
return r;
|
||||
}
|
||||
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
index 64ac56f..33aaade 100644
|
||||
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
@@ -1909,6 +1909,17 @@ hcall_try_real_mode:
|
||||
clrrdi r3,r3,2
|
||||
cmpldi r3,hcall_real_table_end - hcall_real_table
|
||||
bge guest_exit_cont
|
||||
+ /* See if this hcall is enabled for in-kernel handling */
|
||||
+ ld r4, VCPU_KVM(r9)
|
||||
+ srdi r0, r3, 8 /* r0 = (r3 / 4) >> 6 */
|
||||
+ sldi r0, r0, 3 /* index into kvm->arch.enabled_hcalls[] */
|
||||
+ add r4, r4, r0
|
||||
+ ld r0, KVM_ENABLED_HCALLS(r4)
|
||||
+ rlwinm r4, r3, 32-2, 0x3f /* r4 = (r3 / 4) & 0x3f */
|
||||
+ srd r0, r0, r4
|
||||
+ andi. r0, r0, 1
|
||||
+ beq guest_exit_cont
|
||||
+ /* Get pointer to handler, if any, and call it */
|
||||
LOAD_REG_ADDR(r4, hcall_real_table)
|
||||
lwax r3,r3,r4
|
||||
cmpwi r3,0
|
||||
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
|
||||
index 3b82e86..123ac7d 100644
|
||||
--- a/arch/powerpc/kvm/book3s_pr.c
|
||||
+++ b/arch/powerpc/kvm/book3s_pr.c
|
||||
@@ -1597,6 +1597,11 @@ static int kvmppc_core_init_vm_pr(struct kvm *kvm)
|
||||
{
|
||||
mutex_init(&kvm->arch.hpt_mutex);
|
||||
|
||||
+#ifdef CONFIG_PPC_BOOK3S_64
|
||||
+ /* Start out with the default set of hcalls enabled */
|
||||
+ kvmppc_pr_init_default_hcalls(kvm);
|
||||
+#endif
|
||||
+
|
||||
if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
|
||||
spin_lock(&kvm_global_user_count_lock);
|
||||
if (++kvm_global_user_count == 1)
|
||||
diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c
|
||||
index f7c25c6..eacaa6e 100644
|
||||
--- a/arch/powerpc/kvm/book3s_pr_papr.c
|
||||
+++ b/arch/powerpc/kvm/book3s_pr_papr.c
|
||||
@@ -267,6 +267,10 @@ static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
|
||||
|
||||
int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
|
||||
{
|
||||
+ if (cmd <= MAX_HCALL_OPCODE &&
|
||||
+ !test_bit(cmd/4, vcpu->kvm->arch.enabled_hcalls))
|
||||
+ return EMULATE_FAIL;
|
||||
+
|
||||
switch (cmd) {
|
||||
case H_ENTER:
|
||||
return kvmppc_h_pr_enter(vcpu);
|
||||
@@ -304,3 +308,36 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
|
||||
|
||||
return EMULATE_FAIL;
|
||||
}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * List of hcall numbers to enable by default.
|
||||
+ * For compatibility with old userspace, we enable by default
|
||||
+ * all hcalls that were implemented before the hcall-enabling
|
||||
+ * facility was added. Note this list should not include H_RTAS.
|
||||
+ */
|
||||
+static unsigned int default_hcall_list[] = {
|
||||
+ H_ENTER,
|
||||
+ H_REMOVE,
|
||||
+ H_PROTECT,
|
||||
+ H_BULK_REMOVE,
|
||||
+ H_PUT_TCE,
|
||||
+ H_CEDE,
|
||||
+#ifdef CONFIG_KVM_XICS
|
||||
+ H_XIRR,
|
||||
+ H_CPPR,
|
||||
+ H_EOI,
|
||||
+ H_IPI,
|
||||
+ H_IPOLL,
|
||||
+ H_XIRR_X,
|
||||
+#endif
|
||||
+ 0
|
||||
+};
|
||||
+
|
||||
+void kvmppc_pr_init_default_hcalls(struct kvm *kvm)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; default_hcall_list[i]; ++i)
|
||||
+ __set_bit(default_hcall_list[i] / 4, kvm->arch.enabled_hcalls);
|
||||
+}
|
||||
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
|
||||
index 61c738a..3222a4d 100644
|
||||
--- a/arch/powerpc/kvm/powerpc.c
|
||||
+++ b/arch/powerpc/kvm/powerpc.c
|
||||
@@ -387,6 +387,7 @@ int kvm_dev_ioctl_check_extension(long ext)
|
||||
case KVM_CAP_PPC_UNSET_IRQ:
|
||||
case KVM_CAP_PPC_IRQ_LEVEL:
|
||||
case KVM_CAP_ENABLE_CAP:
|
||||
+ case KVM_CAP_ENABLE_CAP_VM:
|
||||
case KVM_CAP_ONE_REG:
|
||||
case KVM_CAP_IOEVENTFD:
|
||||
case KVM_CAP_DEVICE_CTRL:
|
||||
@@ -417,6 +418,7 @@ int kvm_dev_ioctl_check_extension(long ext)
|
||||
case KVM_CAP_PPC_ALLOC_HTAB:
|
||||
case KVM_CAP_PPC_RTAS:
|
||||
case KVM_CAP_PPC_FIXUP_HCALL:
|
||||
+ case KVM_CAP_PPC_ENABLE_HCALL:
|
||||
#ifdef CONFIG_KVM_XICS
|
||||
case KVM_CAP_IRQ_XICS:
|
||||
#endif
|
||||
@@ -1099,6 +1101,40 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+
|
||||
+static int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
|
||||
+ struct kvm_enable_cap *cap)
|
||||
+{
|
||||
+ int r;
|
||||
+
|
||||
+ if (cap->flags)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ switch (cap->cap) {
|
||||
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
|
||||
+ case KVM_CAP_PPC_ENABLE_HCALL: {
|
||||
+ unsigned long hcall = cap->args[0];
|
||||
+
|
||||
+ r = -EINVAL;
|
||||
+ if (hcall > MAX_HCALL_OPCODE || (hcall & 3) ||
|
||||
+ cap->args[1] > 1)
|
||||
+ break;
|
||||
+ if (cap->args[1])
|
||||
+ set_bit(hcall / 4, kvm->arch.enabled_hcalls);
|
||||
+ else
|
||||
+ clear_bit(hcall / 4, kvm->arch.enabled_hcalls);
|
||||
+ r = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+#endif
|
||||
+ default:
|
||||
+ r = -EINVAL;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
long kvm_arch_vm_ioctl(struct file *filp,
|
||||
unsigned int ioctl, unsigned long arg)
|
||||
{
|
||||
@@ -1118,6 +1154,15 @@ long kvm_arch_vm_ioctl(struct file *filp,
|
||||
|
||||
break;
|
||||
}
|
||||
+ case KVM_ENABLE_CAP:
|
||||
+ {
|
||||
+ struct kvm_enable_cap cap;
|
||||
+ r = -EFAULT;
|
||||
+ if (copy_from_user(&cap, argp, sizeof(cap)))
|
||||
+ goto out;
|
||||
+ r = kvm_vm_ioctl_enable_cap(kvm, &cap);
|
||||
+ break;
|
||||
+ }
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
case KVM_CREATE_SPAPR_TCE: {
|
||||
struct kvm_create_spapr_tce create_tce;
|
||||
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
|
||||
index e11d8f1..0418b74 100644
|
||||
--- a/include/uapi/linux/kvm.h
|
||||
+++ b/include/uapi/linux/kvm.h
|
||||
@@ -758,6 +758,7 @@ struct kvm_ppc_smmu_info {
|
||||
#define KVM_CAP_VM_ATTRIBUTES 101
|
||||
#define KVM_CAP_ARM_PSCI_0_2 102
|
||||
#define KVM_CAP_PPC_FIXUP_HCALL 103
|
||||
+#define KVM_CAP_PPC_ENABLE_HCALL 104
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 11 Jun 2014 10:37:52 +0200
|
||||
Subject: KVM: PPC: Book3S HV: Access XICS in BE
|
||||
Origin: https://git.kernel.org/linus/76d072fb05f646eb180f161bbe06ab185af52f38
|
||||
|
||||
On the exit path from the guest we check what type of interrupt we received
|
||||
if we received one. This means we're doing hardware access to the XICS interrupt
|
||||
controller.
|
||||
|
||||
However, when running on a little endian system, this access is byte reversed.
|
||||
|
||||
So let's make sure to swizzle the bytes back again and virtually make XICS
|
||||
accesses big endian.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
index bf5270e..364ca0c 100644
|
||||
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
@@ -2350,7 +2350,18 @@ kvmppc_read_intr:
|
||||
cmpdi r6, 0
|
||||
beq- 1f
|
||||
lwzcix r0, r6, r7
|
||||
- rlwinm. r3, r0, 0, 0xffffff
|
||||
+ /*
|
||||
+ * Save XIRR for later. Since we get in in reverse endian on LE
|
||||
+ * systems, save it byte reversed and fetch it back in host endian.
|
||||
+ */
|
||||
+ li r3, HSTATE_SAVED_XIRR
|
||||
+ STWX_BE r0, r3, r13
|
||||
+#ifdef __LITTLE_ENDIAN__
|
||||
+ lwz r3, HSTATE_SAVED_XIRR(r13)
|
||||
+#else
|
||||
+ mr r3, r0
|
||||
+#endif
|
||||
+ rlwinm. r3, r3, 0, 0xffffff
|
||||
sync
|
||||
beq 1f /* if nothing pending in the ICP */
|
||||
|
||||
@@ -2382,10 +2393,9 @@ kvmppc_read_intr:
|
||||
li r3, -1
|
||||
1: blr
|
||||
|
||||
-42: /* It's not an IPI and it's for the host, stash it in the PACA
|
||||
- * before exit, it will be picked up by the host ICP driver
|
||||
+42: /* It's not an IPI and it's for the host. We saved a copy of XIRR in
|
||||
+ * the PACA earlier, it will be picked up by the host ICP driver
|
||||
*/
|
||||
- stw r0, HSTATE_SAVED_XIRR(r13)
|
||||
li r3, 1
|
||||
b 1b
|
||||
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 11 Jun 2014 10:34:19 +0200
|
||||
Subject: KVM: PPC: Book3S HV: Access guest VPA in BE
|
||||
Origin: https://git.kernel.org/linus/02407552256111479fbfd23a3e01218b399aaa35
|
||||
|
||||
There are a few shared data structures between the host and the guest. Most
|
||||
of them get registered through the VPA interface.
|
||||
|
||||
These data structures are defined to always be in big endian byte order, so
|
||||
let's make sure we always access them in big endian.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/powerpc/kvm/book3s_hv.c | 22 +++++++++++-----------
|
||||
arch/powerpc/kvm/book3s_hv_ras.c | 6 +++---
|
||||
2 files changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
|
||||
index 7db9df2..f1281c4 100644
|
||||
--- a/arch/powerpc/kvm/book3s_hv.c
|
||||
+++ b/arch/powerpc/kvm/book3s_hv.c
|
||||
@@ -272,7 +272,7 @@ struct kvm_vcpu *kvmppc_find_vcpu(struct kvm *kvm, int id)
|
||||
static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa)
|
||||
{
|
||||
vpa->__old_status |= LPPACA_OLD_SHARED_PROC;
|
||||
- vpa->yield_count = 1;
|
||||
+ vpa->yield_count = cpu_to_be32(1);
|
||||
}
|
||||
|
||||
static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v,
|
||||
@@ -295,8 +295,8 @@ static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v,
|
||||
struct reg_vpa {
|
||||
u32 dummy;
|
||||
union {
|
||||
- u16 hword;
|
||||
- u32 word;
|
||||
+ __be16 hword;
|
||||
+ __be32 word;
|
||||
} length;
|
||||
};
|
||||
|
||||
@@ -335,9 +335,9 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
|
||||
if (va == NULL)
|
||||
return H_PARAMETER;
|
||||
if (subfunc == H_VPA_REG_VPA)
|
||||
- len = ((struct reg_vpa *)va)->length.hword;
|
||||
+ len = be16_to_cpu(((struct reg_vpa *)va)->length.hword);
|
||||
else
|
||||
- len = ((struct reg_vpa *)va)->length.word;
|
||||
+ len = be32_to_cpu(((struct reg_vpa *)va)->length.word);
|
||||
kvmppc_unpin_guest_page(kvm, va, vpa, false);
|
||||
|
||||
/* Check length */
|
||||
@@ -542,18 +542,18 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
|
||||
return;
|
||||
memset(dt, 0, sizeof(struct dtl_entry));
|
||||
dt->dispatch_reason = 7;
|
||||
- dt->processor_id = vc->pcpu + vcpu->arch.ptid;
|
||||
- dt->timebase = now + vc->tb_offset;
|
||||
- dt->enqueue_to_dispatch_time = stolen;
|
||||
- dt->srr0 = kvmppc_get_pc(vcpu);
|
||||
- dt->srr1 = vcpu->arch.shregs.msr;
|
||||
+ dt->processor_id = cpu_to_be16(vc->pcpu + vcpu->arch.ptid);
|
||||
+ dt->timebase = cpu_to_be64(now + vc->tb_offset);
|
||||
+ dt->enqueue_to_dispatch_time = cpu_to_be32(stolen);
|
||||
+ dt->srr0 = cpu_to_be64(kvmppc_get_pc(vcpu));
|
||||
+ dt->srr1 = cpu_to_be64(vcpu->arch.shregs.msr);
|
||||
++dt;
|
||||
if (dt == vcpu->arch.dtl.pinned_end)
|
||||
dt = vcpu->arch.dtl.pinned_addr;
|
||||
vcpu->arch.dtl_ptr = dt;
|
||||
/* order writing *dt vs. writing vpa->dtl_idx */
|
||||
smp_wmb();
|
||||
- vpa->dtl_idx = ++vcpu->arch.dtl_index;
|
||||
+ vpa->dtl_idx = cpu_to_be64(++vcpu->arch.dtl_index);
|
||||
vcpu->arch.dtl.dirty = true;
|
||||
}
|
||||
|
||||
diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c
|
||||
index 3a5c568..d562c8e 100644
|
||||
--- a/arch/powerpc/kvm/book3s_hv_ras.c
|
||||
+++ b/arch/powerpc/kvm/book3s_hv_ras.c
|
||||
@@ -45,14 +45,14 @@ static void reload_slb(struct kvm_vcpu *vcpu)
|
||||
return;
|
||||
|
||||
/* Sanity check */
|
||||
- n = min_t(u32, slb->persistent, SLB_MIN_SIZE);
|
||||
+ n = min_t(u32, be32_to_cpu(slb->persistent), SLB_MIN_SIZE);
|
||||
if ((void *) &slb->save_area[n] > vcpu->arch.slb_shadow.pinned_end)
|
||||
return;
|
||||
|
||||
/* Load up the SLB from that */
|
||||
for (i = 0; i < n; ++i) {
|
||||
- unsigned long rb = slb->save_area[i].esid;
|
||||
- unsigned long rs = slb->save_area[i].vsid;
|
||||
+ unsigned long rb = be64_to_cpu(slb->save_area[i].esid);
|
||||
+ unsigned long rs = be64_to_cpu(slb->save_area[i].vsid);
|
||||
|
||||
rb = (rb & ~0xFFFul) | i; /* insert entry number */
|
||||
asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb));
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 11 Jun 2014 10:36:17 +0200
|
||||
Subject: KVM: PPC: Book3S HV: Access host lppaca and shadow slb
|
||||
in BE
|
||||
Origin: https://git.kernel.org/linus/0865a583a4881975cc4b621f4886c02f01600302
|
||||
|
||||
Some data structures are always stored in big endian. Among those are the LPPACA
|
||||
fields as well as the shadow slb. These structures might be shared with a
|
||||
hypervisor.
|
||||
|
||||
So whenever we access those fields, make sure we do so in big endian byte order.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 20 ++++++++++----------
|
||||
1 file changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
index e66c1e38..bf5270e 100644
|
||||
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
@@ -32,10 +32,6 @@
|
||||
|
||||
#define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM)
|
||||
|
||||
-#ifdef __LITTLE_ENDIAN__
|
||||
-#error Need to fix lppaca and SLB shadow accesses in little endian mode
|
||||
-#endif
|
||||
-
|
||||
/* Values in HSTATE_NAPPING(r13) */
|
||||
#define NAPPING_CEDE 1
|
||||
#define NAPPING_NOVCPU 2
|
||||
@@ -595,9 +591,10 @@ kvmppc_got_guest:
|
||||
ld r3, VCPU_VPA(r4)
|
||||
cmpdi r3, 0
|
||||
beq 25f
|
||||
- lwz r5, LPPACA_YIELDCOUNT(r3)
|
||||
+ li r6, LPPACA_YIELDCOUNT
|
||||
+ LWZX_BE r5, r3, r6
|
||||
addi r5, r5, 1
|
||||
- stw r5, LPPACA_YIELDCOUNT(r3)
|
||||
+ STWX_BE r5, r3, r6
|
||||
li r6, 1
|
||||
stb r6, VCPU_VPA_DIRTY(r4)
|
||||
25:
|
||||
@@ -1442,9 +1439,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM)
|
||||
ld r8, VCPU_VPA(r9) /* do they have a VPA? */
|
||||
cmpdi r8, 0
|
||||
beq 25f
|
||||
- lwz r3, LPPACA_YIELDCOUNT(r8)
|
||||
+ li r4, LPPACA_YIELDCOUNT
|
||||
+ LWZX_BE r3, r8, r4
|
||||
addi r3, r3, 1
|
||||
- stw r3, LPPACA_YIELDCOUNT(r8)
|
||||
+ STWX_BE r3, r8, r4
|
||||
li r3, 1
|
||||
stb r3, VCPU_VPA_DIRTY(r9)
|
||||
25:
|
||||
@@ -1757,8 +1755,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||
33: ld r8,PACA_SLBSHADOWPTR(r13)
|
||||
|
||||
.rept SLB_NUM_BOLTED
|
||||
- ld r5,SLBSHADOW_SAVEAREA(r8)
|
||||
- ld r6,SLBSHADOW_SAVEAREA+8(r8)
|
||||
+ li r3, SLBSHADOW_SAVEAREA
|
||||
+ LDX_BE r5, r8, r3
|
||||
+ addi r3, r3, 8
|
||||
+ LDX_BE r6, r8, r3
|
||||
andis. r7,r5,SLB_ESID_V@h
|
||||
beq 1f
|
||||
slbmte r6,r5
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 11 Jun 2014 10:39:38 +0200
|
||||
Subject: KVM: PPC: Book3S HV: Enable for little endian hosts
|
||||
Origin: https://git.kernel.org/linus/6947f948f06128409b94306afaca5ece873ee5a2
|
||||
|
||||
Now that we've fixed all the issues that HV KVM code had on little endian
|
||||
hosts, we can enable it in the kernel configuration for users to play with.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/powerpc/kvm/Kconfig | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
|
||||
index d6a53b9..8aeeda1 100644
|
||||
--- a/arch/powerpc/kvm/Kconfig
|
||||
+++ b/arch/powerpc/kvm/Kconfig
|
||||
@@ -75,7 +75,6 @@ config KVM_BOOK3S_64
|
||||
config KVM_BOOK3S_64_HV
|
||||
tristate "KVM support for POWER7 and PPC970 using hypervisor mode in host"
|
||||
depends on KVM_BOOK3S_64
|
||||
- depends on !CPU_LITTLE_ENDIAN
|
||||
select KVM_BOOK3S_HV_POSSIBLE
|
||||
select MMU_NOTIFIER
|
||||
select CMA
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
From: Anton Blanchard <anton@samba.org>
|
||||
Date: Thu, 12 Jun 2014 18:16:10 +1000
|
||||
Subject: KVM: PPC: Book3S HV: Fix ABIv2 indirect branch issue
|
||||
Origin: https://git.kernel.org/linus/05a308c722822b0fbcc706b54be70f9bb9d52539
|
||||
|
||||
To establish addressability quickly, ABIv2 requires the target
|
||||
address of the function being called to be in r12.
|
||||
|
||||
Signed-off-by: Anton Blanchard <anton@samba.org>
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
index 868347e..da1cac5 100644
|
||||
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
@@ -1913,8 +1913,8 @@ hcall_try_real_mode:
|
||||
lwax r3,r3,r4
|
||||
cmpwi r3,0
|
||||
beq guest_exit_cont
|
||||
- add r3,r3,r4
|
||||
- mtctr r3
|
||||
+ add r12,r3,r4
|
||||
+ mtctr r12
|
||||
mr r3,r9 /* get vcpu pointer */
|
||||
ld r4,VCPU_GPR(R4)(r9)
|
||||
bctrl
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Mon, 16 Jun 2014 14:41:15 +0200
|
||||
Subject: KVM: PPC: Book3S HV: Fix ABIv2 on LE
|
||||
Origin: https://git.kernel.org/linus/9bf163f86d0dc2f9070d9b1b8c27cedcf8eec816
|
||||
|
||||
For code that doesn't live in modules we can just branch to the real function
|
||||
names, giving us compatibility with ABIv1 and ABIv2.
|
||||
|
||||
Do this for the compiled-in code of HV KVM.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 16 ++++++++--------
|
||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
index 364ca0c..855521e 100644
|
||||
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
||||
@@ -668,9 +668,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM)
|
||||
|
||||
mr r31, r4
|
||||
addi r3, r31, VCPU_FPRS_TM
|
||||
- bl .load_fp_state
|
||||
+ bl load_fp_state
|
||||
addi r3, r31, VCPU_VRS_TM
|
||||
- bl .load_vr_state
|
||||
+ bl load_vr_state
|
||||
mr r4, r31
|
||||
lwz r7, VCPU_VRSAVE_TM(r4)
|
||||
mtspr SPRN_VRSAVE, r7
|
||||
@@ -1414,9 +1414,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM)
|
||||
|
||||
/* Save FP/VSX. */
|
||||
addi r3, r9, VCPU_FPRS_TM
|
||||
- bl .store_fp_state
|
||||
+ bl store_fp_state
|
||||
addi r3, r9, VCPU_VRS_TM
|
||||
- bl .store_vr_state
|
||||
+ bl store_vr_state
|
||||
mfspr r6, SPRN_VRSAVE
|
||||
stw r6, VCPU_VRSAVE_TM(r9)
|
||||
1:
|
||||
@@ -2430,11 +2430,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
|
||||
mtmsrd r8
|
||||
isync
|
||||
addi r3,r3,VCPU_FPRS
|
||||
- bl .store_fp_state
|
||||
+ bl store_fp_state
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
BEGIN_FTR_SECTION
|
||||
addi r3,r31,VCPU_VRS
|
||||
- bl .store_vr_state
|
||||
+ bl store_vr_state
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
||||
#endif
|
||||
mfspr r6,SPRN_VRSAVE
|
||||
@@ -2466,11 +2466,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
|
||||
mtmsrd r8
|
||||
isync
|
||||
addi r3,r4,VCPU_FPRS
|
||||
- bl .load_fp_state
|
||||
+ bl load_fp_state
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
BEGIN_FTR_SECTION
|
||||
addi r3,r31,VCPU_VRS
|
||||
- bl .load_vr_state
|
||||
+ bl load_vr_state
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
||||
#endif
|
||||
lwz r7,VCPU_VRSAVE(r31)
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,881 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 11 Jun 2014 10:16:06 +0200
|
||||
Subject: KVM: PPC: Book3S HV: Make HTAB code LE host aware
|
||||
Origin: https://git.kernel.org/linus/6f22bd3265fb542acb2697026b953ec07298242d
|
||||
|
||||
When running on an LE host all data structures are kept in little endian
|
||||
byte order. However, the HTAB still needs to be maintained in big endian.
|
||||
|
||||
So every time we access any HTAB we need to make sure we do so in the right
|
||||
byte order. Fix up all accesses to manually byte swap.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/powerpc/include/asm/kvm_book3s.h | 4
|
||||
arch/powerpc/include/asm/kvm_book3s_64.h | 15 ++-
|
||||
arch/powerpc/kvm/book3s_64_mmu_hv.c | 128 ++++++++++++++-------------
|
||||
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 146 +++++++++++++++++--------------
|
||||
4 files changed, 164 insertions(+), 129 deletions(-)
|
||||
|
||||
--- a/arch/powerpc/include/asm/kvm_book3s.h
|
||||
+++ b/arch/powerpc/include/asm/kvm_book3s.h
|
||||
@@ -163,9 +163,9 @@
|
||||
bool *writable);
|
||||
extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
|
||||
unsigned long *rmap, long pte_index, int realmode);
|
||||
-extern void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
|
||||
+extern void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep,
|
||||
unsigned long pte_index);
|
||||
-void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
|
||||
+void kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep,
|
||||
unsigned long pte_index);
|
||||
extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr,
|
||||
unsigned long *nb_ret);
|
||||
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
|
||||
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
|
||||
@@ -59,20 +59,29 @@
|
||||
/* These bits are reserved in the guest view of the HPTE */
|
||||
#define HPTE_GR_RESERVED HPTE_GR_MODIFIED
|
||||
|
||||
-static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits)
|
||||
+static inline long try_lock_hpte(__be64 *hpte, unsigned long bits)
|
||||
{
|
||||
unsigned long tmp, old;
|
||||
+ __be64 be_lockbit, be_bits;
|
||||
+
|
||||
+ /*
|
||||
+ * We load/store in native endian, but the HTAB is in big endian. If
|
||||
+ * we byte swap all data we apply on the PTE we're implicitly correct
|
||||
+ * again.
|
||||
+ */
|
||||
+ be_lockbit = cpu_to_be64(HPTE_V_HVLOCK);
|
||||
+ be_bits = cpu_to_be64(bits);
|
||||
|
||||
asm volatile(" ldarx %0,0,%2\n"
|
||||
" and. %1,%0,%3\n"
|
||||
" bne 2f\n"
|
||||
- " ori %0,%0,%4\n"
|
||||
+ " or %0,%0,%4\n"
|
||||
" stdcx. %0,0,%2\n"
|
||||
" beq+ 2f\n"
|
||||
" mr %1,%3\n"
|
||||
"2: isync"
|
||||
: "=&r" (tmp), "=&r" (old)
|
||||
- : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
|
||||
+ : "r" (hpte), "r" (be_bits), "r" (be_lockbit)
|
||||
: "cc", "memory");
|
||||
return old == 0;
|
||||
}
|
||||
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
|
||||
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
|
||||
@@ -450,7 +450,7 @@
|
||||
unsigned long slb_v;
|
||||
unsigned long pp, key;
|
||||
unsigned long v, gr;
|
||||
- unsigned long *hptep;
|
||||
+ __be64 *hptep;
|
||||
int index;
|
||||
int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR);
|
||||
|
||||
@@ -473,13 +473,13 @@
|
||||
preempt_enable();
|
||||
return -ENOENT;
|
||||
}
|
||||
- hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
|
||||
- v = hptep[0] & ~HPTE_V_HVLOCK;
|
||||
+ hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
|
||||
+ v = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
|
||||
gr = kvm->arch.revmap[index].guest_rpte;
|
||||
|
||||
/* Unlock the HPTE */
|
||||
asm volatile("lwsync" : : : "memory");
|
||||
- hptep[0] = v;
|
||||
+ hptep[0] = cpu_to_be64(v);
|
||||
preempt_enable();
|
||||
|
||||
gpte->eaddr = eaddr;
|
||||
@@ -583,7 +583,8 @@
|
||||
unsigned long ea, unsigned long dsisr)
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
- unsigned long *hptep, hpte[3], r;
|
||||
+ unsigned long hpte[3], r;
|
||||
+ __be64 *hptep;
|
||||
unsigned long mmu_seq, psize, pte_size;
|
||||
unsigned long gpa_base, gfn_base;
|
||||
unsigned long gpa, gfn, hva, pfn;
|
||||
@@ -606,16 +607,16 @@
|
||||
if (ea != vcpu->arch.pgfault_addr)
|
||||
return RESUME_GUEST;
|
||||
index = vcpu->arch.pgfault_index;
|
||||
- hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
|
||||
+ hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
|
||||
rev = &kvm->arch.revmap[index];
|
||||
preempt_disable();
|
||||
while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
|
||||
cpu_relax();
|
||||
- hpte[0] = hptep[0] & ~HPTE_V_HVLOCK;
|
||||
- hpte[1] = hptep[1];
|
||||
+ hpte[0] = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
|
||||
+ hpte[1] = be64_to_cpu(hptep[1]);
|
||||
hpte[2] = r = rev->guest_rpte;
|
||||
asm volatile("lwsync" : : : "memory");
|
||||
- hptep[0] = hpte[0];
|
||||
+ hptep[0] = cpu_to_be64(hpte[0]);
|
||||
preempt_enable();
|
||||
|
||||
if (hpte[0] != vcpu->arch.pgfault_hpte[0] ||
|
||||
@@ -731,8 +732,9 @@
|
||||
preempt_disable();
|
||||
while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
|
||||
cpu_relax();
|
||||
- if ((hptep[0] & ~HPTE_V_HVLOCK) != hpte[0] || hptep[1] != hpte[1] ||
|
||||
- rev->guest_rpte != hpte[2])
|
||||
+ if ((be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK) != hpte[0] ||
|
||||
+ be64_to_cpu(hptep[1]) != hpte[1] ||
|
||||
+ rev->guest_rpte != hpte[2])
|
||||
/* HPTE has been changed under us; let the guest retry */
|
||||
goto out_unlock;
|
||||
hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
|
||||
@@ -752,20 +754,20 @@
|
||||
rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT;
|
||||
r &= rcbits | ~(HPTE_R_R | HPTE_R_C);
|
||||
|
||||
- if (hptep[0] & HPTE_V_VALID) {
|
||||
+ if (be64_to_cpu(hptep[0]) & HPTE_V_VALID) {
|
||||
/* HPTE was previously valid, so we need to invalidate it */
|
||||
unlock_rmap(rmap);
|
||||
- hptep[0] |= HPTE_V_ABSENT;
|
||||
+ hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
|
||||
kvmppc_invalidate_hpte(kvm, hptep, index);
|
||||
/* don't lose previous R and C bits */
|
||||
- r |= hptep[1] & (HPTE_R_R | HPTE_R_C);
|
||||
+ r |= be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C);
|
||||
} else {
|
||||
kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0);
|
||||
}
|
||||
|
||||
- hptep[1] = r;
|
||||
+ hptep[1] = cpu_to_be64(r);
|
||||
eieio();
|
||||
- hptep[0] = hpte[0];
|
||||
+ hptep[0] = cpu_to_be64(hpte[0]);
|
||||
asm volatile("ptesync" : : : "memory");
|
||||
preempt_enable();
|
||||
if (page && hpte_is_writable(r))
|
||||
@@ -784,7 +786,7 @@
|
||||
return ret;
|
||||
|
||||
out_unlock:
|
||||
- hptep[0] &= ~HPTE_V_HVLOCK;
|
||||
+ hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
|
||||
preempt_enable();
|
||||
goto out_put;
|
||||
}
|
||||
@@ -860,7 +862,7 @@
|
||||
{
|
||||
struct revmap_entry *rev = kvm->arch.revmap;
|
||||
unsigned long h, i, j;
|
||||
- unsigned long *hptep;
|
||||
+ __be64 *hptep;
|
||||
unsigned long ptel, psize, rcbits;
|
||||
|
||||
for (;;) {
|
||||
@@ -876,11 +878,11 @@
|
||||
* rmap chain lock.
|
||||
*/
|
||||
i = *rmapp & KVMPPC_RMAP_INDEX;
|
||||
- hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
|
||||
+ hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4));
|
||||
if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
|
||||
/* unlock rmap before spinning on the HPTE lock */
|
||||
unlock_rmap(rmapp);
|
||||
- while (hptep[0] & HPTE_V_HVLOCK)
|
||||
+ while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK)
|
||||
cpu_relax();
|
||||
continue;
|
||||
}
|
||||
@@ -899,14 +901,14 @@
|
||||
|
||||
/* Now check and modify the HPTE */
|
||||
ptel = rev[i].guest_rpte;
|
||||
- psize = hpte_page_size(hptep[0], ptel);
|
||||
- if ((hptep[0] & HPTE_V_VALID) &&
|
||||
+ psize = hpte_page_size(be64_to_cpu(hptep[0]), ptel);
|
||||
+ if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) &&
|
||||
hpte_rpn(ptel, psize) == gfn) {
|
||||
if (kvm->arch.using_mmu_notifiers)
|
||||
- hptep[0] |= HPTE_V_ABSENT;
|
||||
+ hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
|
||||
kvmppc_invalidate_hpte(kvm, hptep, i);
|
||||
/* Harvest R and C */
|
||||
- rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C);
|
||||
+ rcbits = be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C);
|
||||
*rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT;
|
||||
if (rcbits & ~rev[i].guest_rpte) {
|
||||
rev[i].guest_rpte = ptel | rcbits;
|
||||
@@ -914,7 +916,7 @@
|
||||
}
|
||||
}
|
||||
unlock_rmap(rmapp);
|
||||
- hptep[0] &= ~HPTE_V_HVLOCK;
|
||||
+ hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -961,7 +963,7 @@
|
||||
{
|
||||
struct revmap_entry *rev = kvm->arch.revmap;
|
||||
unsigned long head, i, j;
|
||||
- unsigned long *hptep;
|
||||
+ __be64 *hptep;
|
||||
int ret = 0;
|
||||
|
||||
retry:
|
||||
@@ -977,23 +979,24 @@
|
||||
|
||||
i = head = *rmapp & KVMPPC_RMAP_INDEX;
|
||||
do {
|
||||
- hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
|
||||
+ hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4));
|
||||
j = rev[i].forw;
|
||||
|
||||
/* If this HPTE isn't referenced, ignore it */
|
||||
- if (!(hptep[1] & HPTE_R_R))
|
||||
+ if (!(be64_to_cpu(hptep[1]) & HPTE_R_R))
|
||||
continue;
|
||||
|
||||
if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
|
||||
/* unlock rmap before spinning on the HPTE lock */
|
||||
unlock_rmap(rmapp);
|
||||
- while (hptep[0] & HPTE_V_HVLOCK)
|
||||
+ while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK)
|
||||
cpu_relax();
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Now check and modify the HPTE */
|
||||
- if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_R)) {
|
||||
+ if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) &&
|
||||
+ (be64_to_cpu(hptep[1]) & HPTE_R_R)) {
|
||||
kvmppc_clear_ref_hpte(kvm, hptep, i);
|
||||
if (!(rev[i].guest_rpte & HPTE_R_R)) {
|
||||
rev[i].guest_rpte |= HPTE_R_R;
|
||||
@@ -1001,7 +1004,7 @@
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
- hptep[0] &= ~HPTE_V_HVLOCK;
|
||||
+ hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
|
||||
} while ((i = j) != head);
|
||||
|
||||
unlock_rmap(rmapp);
|
||||
@@ -1035,7 +1038,7 @@
|
||||
do {
|
||||
hp = (unsigned long *)(kvm->arch.hpt_virt + (i << 4));
|
||||
j = rev[i].forw;
|
||||
- if (hp[1] & HPTE_R_R)
|
||||
+ if (be64_to_cpu(hp[1]) & HPTE_R_R)
|
||||
goto out;
|
||||
} while ((i = j) != head);
|
||||
}
|
||||
@@ -1075,7 +1078,7 @@
|
||||
unsigned long head, i, j;
|
||||
unsigned long n;
|
||||
unsigned long v, r;
|
||||
- unsigned long *hptep;
|
||||
+ __be64 *hptep;
|
||||
int npages_dirty = 0;
|
||||
|
||||
retry:
|
||||
@@ -1091,7 +1094,8 @@
|
||||
|
||||
i = head = *rmapp & KVMPPC_RMAP_INDEX;
|
||||
do {
|
||||
- hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
|
||||
+ unsigned long hptep1;
|
||||
+ hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4));
|
||||
j = rev[i].forw;
|
||||
|
||||
/*
|
||||
@@ -1108,29 +1112,30 @@
|
||||
* Otherwise we need to do the tlbie even if C==0 in
|
||||
* order to pick up any delayed writeback of C.
|
||||
*/
|
||||
- if (!(hptep[1] & HPTE_R_C) &&
|
||||
- (!hpte_is_writable(hptep[1]) || vcpus_running(kvm)))
|
||||
+ hptep1 = be64_to_cpu(hptep[1]);
|
||||
+ if (!(hptep1 & HPTE_R_C) &&
|
||||
+ (!hpte_is_writable(hptep1) || vcpus_running(kvm)))
|
||||
continue;
|
||||
|
||||
if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
|
||||
/* unlock rmap before spinning on the HPTE lock */
|
||||
unlock_rmap(rmapp);
|
||||
- while (hptep[0] & HPTE_V_HVLOCK)
|
||||
+ while (hptep[0] & cpu_to_be64(HPTE_V_HVLOCK))
|
||||
cpu_relax();
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Now check and modify the HPTE */
|
||||
- if (!(hptep[0] & HPTE_V_VALID))
|
||||
+ if (!(hptep[0] & cpu_to_be64(HPTE_V_VALID)))
|
||||
continue;
|
||||
|
||||
/* need to make it temporarily absent so C is stable */
|
||||
- hptep[0] |= HPTE_V_ABSENT;
|
||||
+ hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
|
||||
kvmppc_invalidate_hpte(kvm, hptep, i);
|
||||
- v = hptep[0];
|
||||
- r = hptep[1];
|
||||
+ v = be64_to_cpu(hptep[0]);
|
||||
+ r = be64_to_cpu(hptep[1]);
|
||||
if (r & HPTE_R_C) {
|
||||
- hptep[1] = r & ~HPTE_R_C;
|
||||
+ hptep[1] = cpu_to_be64(r & ~HPTE_R_C);
|
||||
if (!(rev[i].guest_rpte & HPTE_R_C)) {
|
||||
rev[i].guest_rpte |= HPTE_R_C;
|
||||
note_hpte_modification(kvm, &rev[i]);
|
||||
@@ -1143,7 +1148,7 @@
|
||||
}
|
||||
v &= ~(HPTE_V_ABSENT | HPTE_V_HVLOCK);
|
||||
v |= HPTE_V_VALID;
|
||||
- hptep[0] = v;
|
||||
+ hptep[0] = cpu_to_be64(v);
|
||||
} while ((i = j) != head);
|
||||
|
||||
unlock_rmap(rmapp);
|
||||
@@ -1307,7 +1312,7 @@
|
||||
* Returns 1 if this HPT entry has been modified or has pending
|
||||
* R/C bit changes.
|
||||
*/
|
||||
-static int hpte_dirty(struct revmap_entry *revp, unsigned long *hptp)
|
||||
+static int hpte_dirty(struct revmap_entry *revp, __be64 *hptp)
|
||||
{
|
||||
unsigned long rcbits_unset;
|
||||
|
||||
@@ -1316,13 +1321,14 @@
|
||||
|
||||
/* Also need to consider changes in reference and changed bits */
|
||||
rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C);
|
||||
- if ((hptp[0] & HPTE_V_VALID) && (hptp[1] & rcbits_unset))
|
||||
+ if ((be64_to_cpu(hptp[0]) & HPTE_V_VALID) &&
|
||||
+ (be64_to_cpu(hptp[1]) & rcbits_unset))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static long record_hpte(unsigned long flags, unsigned long *hptp,
|
||||
+static long record_hpte(unsigned long flags, __be64 *hptp,
|
||||
unsigned long *hpte, struct revmap_entry *revp,
|
||||
int want_valid, int first_pass)
|
||||
{
|
||||
@@ -1337,10 +1343,10 @@
|
||||
return 0;
|
||||
|
||||
valid = 0;
|
||||
- if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) {
|
||||
+ if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)) {
|
||||
valid = 1;
|
||||
if ((flags & KVM_GET_HTAB_BOLTED_ONLY) &&
|
||||
- !(hptp[0] & HPTE_V_BOLTED))
|
||||
+ !(be64_to_cpu(hptp[0]) & HPTE_V_BOLTED))
|
||||
valid = 0;
|
||||
}
|
||||
if (valid != want_valid)
|
||||
@@ -1352,7 +1358,7 @@
|
||||
preempt_disable();
|
||||
while (!try_lock_hpte(hptp, HPTE_V_HVLOCK))
|
||||
cpu_relax();
|
||||
- v = hptp[0];
|
||||
+ v = be64_to_cpu(hptp[0]);
|
||||
|
||||
/* re-evaluate valid and dirty from synchronized HPTE value */
|
||||
valid = !!(v & HPTE_V_VALID);
|
||||
@@ -1360,9 +1366,9 @@
|
||||
|
||||
/* Harvest R and C into guest view if necessary */
|
||||
rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C);
|
||||
- if (valid && (rcbits_unset & hptp[1])) {
|
||||
- revp->guest_rpte |= (hptp[1] & (HPTE_R_R | HPTE_R_C)) |
|
||||
- HPTE_GR_MODIFIED;
|
||||
+ if (valid && (rcbits_unset & be64_to_cpu(hptp[1]))) {
|
||||
+ revp->guest_rpte |= (be64_to_cpu(hptp[1]) &
|
||||
+ (HPTE_R_R | HPTE_R_C)) | HPTE_GR_MODIFIED;
|
||||
dirty = 1;
|
||||
}
|
||||
|
||||
@@ -1381,13 +1387,13 @@
|
||||
revp->guest_rpte = r;
|
||||
}
|
||||
asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
|
||||
- hptp[0] &= ~HPTE_V_HVLOCK;
|
||||
+ hptp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
|
||||
preempt_enable();
|
||||
if (!(valid == want_valid && (first_pass || dirty)))
|
||||
ok = 0;
|
||||
}
|
||||
- hpte[0] = v;
|
||||
- hpte[1] = r;
|
||||
+ hpte[0] = cpu_to_be64(v);
|
||||
+ hpte[1] = cpu_to_be64(r);
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -1397,7 +1403,7 @@
|
||||
struct kvm_htab_ctx *ctx = file->private_data;
|
||||
struct kvm *kvm = ctx->kvm;
|
||||
struct kvm_get_htab_header hdr;
|
||||
- unsigned long *hptp;
|
||||
+ __be64 *hptp;
|
||||
struct revmap_entry *revp;
|
||||
unsigned long i, nb, nw;
|
||||
unsigned long __user *lbuf;
|
||||
@@ -1413,7 +1419,7 @@
|
||||
flags = ctx->flags;
|
||||
|
||||
i = ctx->index;
|
||||
- hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
|
||||
+ hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
|
||||
revp = kvm->arch.revmap + i;
|
||||
lbuf = (unsigned long __user *)buf;
|
||||
|
||||
@@ -1497,7 +1503,7 @@
|
||||
unsigned long i, j;
|
||||
unsigned long v, r;
|
||||
unsigned long __user *lbuf;
|
||||
- unsigned long *hptp;
|
||||
+ __be64 *hptp;
|
||||
unsigned long tmp[2];
|
||||
ssize_t nb;
|
||||
long int err, ret;
|
||||
@@ -1539,7 +1545,7 @@
|
||||
i + hdr.n_valid + hdr.n_invalid > kvm->arch.hpt_npte)
|
||||
break;
|
||||
|
||||
- hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
|
||||
+ hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
|
||||
lbuf = (unsigned long __user *)buf;
|
||||
for (j = 0; j < hdr.n_valid; ++j) {
|
||||
err = -EFAULT;
|
||||
@@ -1551,7 +1557,7 @@
|
||||
lbuf += 2;
|
||||
nb += HPTE_SIZE;
|
||||
|
||||
- if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
|
||||
+ if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT))
|
||||
kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
|
||||
err = -EIO;
|
||||
ret = kvmppc_virtmode_do_h_enter(kvm, H_EXACT, i, v, r,
|
||||
@@ -1577,7 +1583,7 @@
|
||||
}
|
||||
|
||||
for (j = 0; j < hdr.n_invalid; ++j) {
|
||||
- if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
|
||||
+ if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT))
|
||||
kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
|
||||
++i;
|
||||
hptp += 2;
|
||||
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
|
||||
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
|
||||
@@ -154,10 +154,10 @@
|
||||
return kvmppc_read_update_linux_pte(ptep, writing, hugepage_shift);
|
||||
}
|
||||
|
||||
-static inline void unlock_hpte(unsigned long *hpte, unsigned long hpte_v)
|
||||
+static inline void unlock_hpte(__be64 *hpte, unsigned long hpte_v)
|
||||
{
|
||||
asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
|
||||
- hpte[0] = hpte_v;
|
||||
+ hpte[0] = cpu_to_be64(hpte_v);
|
||||
}
|
||||
|
||||
long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
|
||||
@@ -166,7 +166,7 @@
|
||||
{
|
||||
unsigned long i, pa, gpa, gfn, psize;
|
||||
unsigned long slot_fn, hva;
|
||||
- unsigned long *hpte;
|
||||
+ __be64 *hpte;
|
||||
struct revmap_entry *rev;
|
||||
unsigned long g_ptel;
|
||||
struct kvm_memory_slot *memslot;
|
||||
@@ -275,9 +275,9 @@
|
||||
return H_PARAMETER;
|
||||
if (likely((flags & H_EXACT) == 0)) {
|
||||
pte_index &= ~7UL;
|
||||
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
|
||||
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
|
||||
for (i = 0; i < 8; ++i) {
|
||||
- if ((*hpte & HPTE_V_VALID) == 0 &&
|
||||
+ if ((be64_to_cpu(*hpte) & HPTE_V_VALID) == 0 &&
|
||||
try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
|
||||
HPTE_V_ABSENT))
|
||||
break;
|
||||
@@ -292,11 +292,13 @@
|
||||
*/
|
||||
hpte -= 16;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
+ u64 pte;
|
||||
while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
|
||||
cpu_relax();
|
||||
- if (!(*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)))
|
||||
+ pte = be64_to_cpu(*hpte);
|
||||
+ if (!(pte & (HPTE_V_VALID | HPTE_V_ABSENT)))
|
||||
break;
|
||||
- *hpte &= ~HPTE_V_HVLOCK;
|
||||
+ *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK);
|
||||
hpte += 2;
|
||||
}
|
||||
if (i == 8)
|
||||
@@ -304,14 +306,17 @@
|
||||
}
|
||||
pte_index += i;
|
||||
} else {
|
||||
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
|
||||
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
|
||||
if (!try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
|
||||
HPTE_V_ABSENT)) {
|
||||
/* Lock the slot and check again */
|
||||
+ u64 pte;
|
||||
+
|
||||
while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
|
||||
cpu_relax();
|
||||
- if (*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)) {
|
||||
- *hpte &= ~HPTE_V_HVLOCK;
|
||||
+ pte = be64_to_cpu(*hpte);
|
||||
+ if (pte & (HPTE_V_VALID | HPTE_V_ABSENT)) {
|
||||
+ *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK);
|
||||
return H_PTEG_FULL;
|
||||
}
|
||||
}
|
||||
@@ -347,11 +352,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
- hpte[1] = ptel;
|
||||
+ hpte[1] = cpu_to_be64(ptel);
|
||||
|
||||
/* Write the first HPTE dword, unlocking the HPTE and making it valid */
|
||||
eieio();
|
||||
- hpte[0] = pteh;
|
||||
+ hpte[0] = cpu_to_be64(pteh);
|
||||
asm volatile("ptesync" : : : "memory");
|
||||
|
||||
*pte_idx_ret = pte_index;
|
||||
@@ -468,30 +473,35 @@
|
||||
unsigned long pte_index, unsigned long avpn,
|
||||
unsigned long *hpret)
|
||||
{
|
||||
- unsigned long *hpte;
|
||||
+ __be64 *hpte;
|
||||
unsigned long v, r, rb;
|
||||
struct revmap_entry *rev;
|
||||
+ u64 pte;
|
||||
|
||||
if (pte_index >= kvm->arch.hpt_npte)
|
||||
return H_PARAMETER;
|
||||
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
|
||||
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
|
||||
while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
|
||||
cpu_relax();
|
||||
- if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
|
||||
- ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn) ||
|
||||
- ((flags & H_ANDCOND) && (hpte[0] & avpn) != 0)) {
|
||||
- hpte[0] &= ~HPTE_V_HVLOCK;
|
||||
+ pte = be64_to_cpu(hpte[0]);
|
||||
+ if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
|
||||
+ ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) ||
|
||||
+ ((flags & H_ANDCOND) && (pte & avpn) != 0)) {
|
||||
+ hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
|
||||
return H_NOT_FOUND;
|
||||
}
|
||||
|
||||
rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
|
||||
- v = hpte[0] & ~HPTE_V_HVLOCK;
|
||||
+ v = pte & ~HPTE_V_HVLOCK;
|
||||
if (v & HPTE_V_VALID) {
|
||||
- hpte[0] &= ~HPTE_V_VALID;
|
||||
- rb = compute_tlbie_rb(v, hpte[1], pte_index);
|
||||
+ u64 pte1;
|
||||
+
|
||||
+ pte1 = be64_to_cpu(hpte[1]);
|
||||
+ hpte[0] &= ~cpu_to_be64(HPTE_V_VALID);
|
||||
+ rb = compute_tlbie_rb(v, pte1, pte_index);
|
||||
do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
|
||||
/* Read PTE low word after tlbie to get final R/C values */
|
||||
- remove_revmap_chain(kvm, pte_index, rev, v, hpte[1]);
|
||||
+ remove_revmap_chain(kvm, pte_index, rev, v, pte1);
|
||||
}
|
||||
r = rev->guest_rpte & ~HPTE_GR_RESERVED;
|
||||
note_hpte_modification(kvm, rev);
|
||||
@@ -514,12 +524,14 @@
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
unsigned long *args = &vcpu->arch.gpr[4];
|
||||
- unsigned long *hp, *hptes[4], tlbrb[4];
|
||||
+ __be64 *hp, *hptes[4];
|
||||
+ unsigned long tlbrb[4];
|
||||
long int i, j, k, n, found, indexes[4];
|
||||
unsigned long flags, req, pte_index, rcbits;
|
||||
int global;
|
||||
long int ret = H_SUCCESS;
|
||||
struct revmap_entry *rev, *revs[4];
|
||||
+ u64 hp0;
|
||||
|
||||
global = global_invalidates(kvm, 0);
|
||||
for (i = 0; i < 4 && ret == H_SUCCESS; ) {
|
||||
@@ -542,8 +554,7 @@
|
||||
ret = H_PARAMETER;
|
||||
break;
|
||||
}
|
||||
- hp = (unsigned long *)
|
||||
- (kvm->arch.hpt_virt + (pte_index << 4));
|
||||
+ hp = (__be64 *) (kvm->arch.hpt_virt + (pte_index << 4));
|
||||
/* to avoid deadlock, don't spin except for first */
|
||||
if (!try_lock_hpte(hp, HPTE_V_HVLOCK)) {
|
||||
if (n)
|
||||
@@ -552,23 +563,24 @@
|
||||
cpu_relax();
|
||||
}
|
||||
found = 0;
|
||||
- if (hp[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) {
|
||||
+ hp0 = be64_to_cpu(hp[0]);
|
||||
+ if (hp0 & (HPTE_V_ABSENT | HPTE_V_VALID)) {
|
||||
switch (flags & 3) {
|
||||
case 0: /* absolute */
|
||||
found = 1;
|
||||
break;
|
||||
case 1: /* andcond */
|
||||
- if (!(hp[0] & args[j + 1]))
|
||||
+ if (!(hp0 & args[j + 1]))
|
||||
found = 1;
|
||||
break;
|
||||
case 2: /* AVPN */
|
||||
- if ((hp[0] & ~0x7fUL) == args[j + 1])
|
||||
+ if ((hp0 & ~0x7fUL) == args[j + 1])
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
- hp[0] &= ~HPTE_V_HVLOCK;
|
||||
+ hp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
|
||||
args[j] = ((0x90 | flags) << 56) + pte_index;
|
||||
continue;
|
||||
}
|
||||
@@ -577,7 +589,7 @@
|
||||
rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
|
||||
note_hpte_modification(kvm, rev);
|
||||
|
||||
- if (!(hp[0] & HPTE_V_VALID)) {
|
||||
+ if (!(hp0 & HPTE_V_VALID)) {
|
||||
/* insert R and C bits from PTE */
|
||||
rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
|
||||
args[j] |= rcbits << (56 - 5);
|
||||
@@ -585,8 +597,10 @@
|
||||
continue;
|
||||
}
|
||||
|
||||
- hp[0] &= ~HPTE_V_VALID; /* leave it locked */
|
||||
- tlbrb[n] = compute_tlbie_rb(hp[0], hp[1], pte_index);
|
||||
+ /* leave it locked */
|
||||
+ hp[0] &= ~cpu_to_be64(HPTE_V_VALID);
|
||||
+ tlbrb[n] = compute_tlbie_rb(be64_to_cpu(hp[0]),
|
||||
+ be64_to_cpu(hp[1]), pte_index);
|
||||
indexes[n] = j;
|
||||
hptes[n] = hp;
|
||||
revs[n] = rev;
|
||||
@@ -605,7 +619,8 @@
|
||||
pte_index = args[j] & ((1ul << 56) - 1);
|
||||
hp = hptes[k];
|
||||
rev = revs[k];
|
||||
- remove_revmap_chain(kvm, pte_index, rev, hp[0], hp[1]);
|
||||
+ remove_revmap_chain(kvm, pte_index, rev,
|
||||
+ be64_to_cpu(hp[0]), be64_to_cpu(hp[1]));
|
||||
rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
|
||||
args[j] |= rcbits << (56 - 5);
|
||||
hp[0] = 0;
|
||||
@@ -620,23 +635,25 @@
|
||||
unsigned long va)
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
- unsigned long *hpte;
|
||||
+ __be64 *hpte;
|
||||
struct revmap_entry *rev;
|
||||
unsigned long v, r, rb, mask, bits;
|
||||
+ u64 pte;
|
||||
|
||||
if (pte_index >= kvm->arch.hpt_npte)
|
||||
return H_PARAMETER;
|
||||
|
||||
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
|
||||
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
|
||||
while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
|
||||
cpu_relax();
|
||||
- if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
|
||||
- ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn)) {
|
||||
- hpte[0] &= ~HPTE_V_HVLOCK;
|
||||
+ pte = be64_to_cpu(hpte[0]);
|
||||
+ if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
|
||||
+ ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn)) {
|
||||
+ hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
|
||||
return H_NOT_FOUND;
|
||||
}
|
||||
|
||||
- v = hpte[0];
|
||||
+ v = pte;
|
||||
bits = (flags << 55) & HPTE_R_PP0;
|
||||
bits |= (flags << 48) & HPTE_R_KEY_HI;
|
||||
bits |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
|
||||
@@ -650,12 +667,12 @@
|
||||
rev->guest_rpte = r;
|
||||
note_hpte_modification(kvm, rev);
|
||||
}
|
||||
- r = (hpte[1] & ~mask) | bits;
|
||||
+ r = (be64_to_cpu(hpte[1]) & ~mask) | bits;
|
||||
|
||||
/* Update HPTE */
|
||||
if (v & HPTE_V_VALID) {
|
||||
rb = compute_tlbie_rb(v, r, pte_index);
|
||||
- hpte[0] = v & ~HPTE_V_VALID;
|
||||
+ hpte[0] = cpu_to_be64(v & ~HPTE_V_VALID);
|
||||
do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
|
||||
/*
|
||||
* If the host has this page as readonly but the guest
|
||||
@@ -681,9 +698,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
- hpte[1] = r;
|
||||
+ hpte[1] = cpu_to_be64(r);
|
||||
eieio();
|
||||
- hpte[0] = v & ~HPTE_V_HVLOCK;
|
||||
+ hpte[0] = cpu_to_be64(v & ~HPTE_V_HVLOCK);
|
||||
asm volatile("ptesync" : : : "memory");
|
||||
return H_SUCCESS;
|
||||
}
|
||||
@@ -692,7 +709,8 @@
|
||||
unsigned long pte_index)
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
- unsigned long *hpte, v, r;
|
||||
+ __be64 *hpte;
|
||||
+ unsigned long v, r;
|
||||
int i, n = 1;
|
||||
struct revmap_entry *rev = NULL;
|
||||
|
||||
@@ -704,9 +722,9 @@
|
||||
}
|
||||
rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
|
||||
for (i = 0; i < n; ++i, ++pte_index) {
|
||||
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
|
||||
- v = hpte[0] & ~HPTE_V_HVLOCK;
|
||||
- r = hpte[1];
|
||||
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
|
||||
+ v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK;
|
||||
+ r = be64_to_cpu(hpte[1]);
|
||||
if (v & HPTE_V_ABSENT) {
|
||||
v &= ~HPTE_V_ABSENT;
|
||||
v |= HPTE_V_VALID;
|
||||
@@ -721,25 +739,27 @@
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
-void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
|
||||
+void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep,
|
||||
unsigned long pte_index)
|
||||
{
|
||||
unsigned long rb;
|
||||
|
||||
- hptep[0] &= ~HPTE_V_VALID;
|
||||
- rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
|
||||
+ hptep[0] &= ~cpu_to_be64(HPTE_V_VALID);
|
||||
+ rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]),
|
||||
+ pte_index);
|
||||
do_tlbies(kvm, &rb, 1, 1, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvmppc_invalidate_hpte);
|
||||
|
||||
-void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
|
||||
+void kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep,
|
||||
unsigned long pte_index)
|
||||
{
|
||||
unsigned long rb;
|
||||
unsigned char rbyte;
|
||||
|
||||
- rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
|
||||
- rbyte = (hptep[1] & ~HPTE_R_R) >> 8;
|
||||
+ rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]),
|
||||
+ pte_index);
|
||||
+ rbyte = (be64_to_cpu(hptep[1]) & ~HPTE_R_R) >> 8;
|
||||
/* modify only the second-last byte, which contains the ref bit */
|
||||
*((char *)hptep + 14) = rbyte;
|
||||
do_tlbies(kvm, &rb, 1, 1, false);
|
||||
@@ -765,7 +785,7 @@
|
||||
unsigned long somask;
|
||||
unsigned long vsid, hash;
|
||||
unsigned long avpn;
|
||||
- unsigned long *hpte;
|
||||
+ __be64 *hpte;
|
||||
unsigned long mask, val;
|
||||
unsigned long v, r;
|
||||
|
||||
@@ -797,11 +817,11 @@
|
||||
val |= avpn;
|
||||
|
||||
for (;;) {
|
||||
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (hash << 7));
|
||||
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (hash << 7));
|
||||
|
||||
for (i = 0; i < 16; i += 2) {
|
||||
/* Read the PTE racily */
|
||||
- v = hpte[i] & ~HPTE_V_HVLOCK;
|
||||
+ v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK;
|
||||
|
||||
/* Check valid/absent, hash, segment size and AVPN */
|
||||
if (!(v & valid) || (v & mask) != val)
|
||||
@@ -810,8 +830,8 @@
|
||||
/* Lock the PTE and read it under the lock */
|
||||
while (!try_lock_hpte(&hpte[i], HPTE_V_HVLOCK))
|
||||
cpu_relax();
|
||||
- v = hpte[i] & ~HPTE_V_HVLOCK;
|
||||
- r = hpte[i+1];
|
||||
+ v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK;
|
||||
+ r = be64_to_cpu(hpte[i+1]);
|
||||
|
||||
/*
|
||||
* Check the HPTE again, including base page size
|
||||
@@ -822,7 +842,7 @@
|
||||
return (hash << 3) + (i >> 1);
|
||||
|
||||
/* Unlock and move on */
|
||||
- hpte[i] = v;
|
||||
+ hpte[i] = cpu_to_be64(v);
|
||||
}
|
||||
|
||||
if (val & HPTE_V_SECONDARY)
|
||||
@@ -851,7 +871,7 @@
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
long int index;
|
||||
unsigned long v, r, gr;
|
||||
- unsigned long *hpte;
|
||||
+ __be64 *hpte;
|
||||
unsigned long valid;
|
||||
struct revmap_entry *rev;
|
||||
unsigned long pp, key;
|
||||
@@ -867,9 +887,9 @@
|
||||
return status; /* there really was no HPTE */
|
||||
return 0; /* for prot fault, HPTE disappeared */
|
||||
}
|
||||
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
|
||||
- v = hpte[0] & ~HPTE_V_HVLOCK;
|
||||
- r = hpte[1];
|
||||
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
|
||||
+ v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK;
|
||||
+ r = be64_to_cpu(hpte[1]);
|
||||
rev = real_vmalloc_addr(&kvm->arch.revmap[index]);
|
||||
gr = rev->guest_rpte;
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Mon, 16 Jun 2014 13:58:11 +0200
|
||||
Subject: KVM: PPC: Book3S PR: Fix sparse endian checks
|
||||
Origin: https://git.kernel.org/linus/f396df35188c59a5ecb83932190505ef297754e6
|
||||
|
||||
While sending sparse with endian checks over the code base, it triggered at
|
||||
some places that were missing casts or had wrong types. Fix them up.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/powerpc/kvm/book3s_pr_papr.c | 21 +++++++++++----------
|
||||
1 file changed, 11 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c
|
||||
index 52a63bf..f7c25c6 100644
|
||||
--- a/arch/powerpc/kvm/book3s_pr_papr.c
|
||||
+++ b/arch/powerpc/kvm/book3s_pr_papr.c
|
||||
@@ -40,8 +40,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
long flags = kvmppc_get_gpr(vcpu, 4);
|
||||
long pte_index = kvmppc_get_gpr(vcpu, 5);
|
||||
- unsigned long pteg[2 * 8];
|
||||
- unsigned long pteg_addr, i, *hpte;
|
||||
+ __be64 pteg[2 * 8];
|
||||
+ __be64 *hpte;
|
||||
+ unsigned long pteg_addr, i;
|
||||
long int ret;
|
||||
|
||||
i = pte_index & 7;
|
||||
@@ -93,8 +94,8 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
|
||||
pteg = get_pteg_addr(vcpu, pte_index);
|
||||
mutex_lock(&vcpu->kvm->arch.hpt_mutex);
|
||||
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
|
||||
- pte[0] = be64_to_cpu(pte[0]);
|
||||
- pte[1] = be64_to_cpu(pte[1]);
|
||||
+ pte[0] = be64_to_cpu((__force __be64)pte[0]);
|
||||
+ pte[1] = be64_to_cpu((__force __be64)pte[1]);
|
||||
|
||||
ret = H_NOT_FOUND;
|
||||
if ((pte[0] & HPTE_V_VALID) == 0 ||
|
||||
@@ -171,8 +172,8 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
|
||||
|
||||
pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX);
|
||||
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
|
||||
- pte[0] = be64_to_cpu(pte[0]);
|
||||
- pte[1] = be64_to_cpu(pte[1]);
|
||||
+ pte[0] = be64_to_cpu((__force __be64)pte[0]);
|
||||
+ pte[1] = be64_to_cpu((__force __be64)pte[1]);
|
||||
|
||||
/* tsl = AVPN */
|
||||
flags = (tsh & H_BULK_REMOVE_FLAGS) >> 26;
|
||||
@@ -211,8 +212,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
|
||||
pteg = get_pteg_addr(vcpu, pte_index);
|
||||
mutex_lock(&vcpu->kvm->arch.hpt_mutex);
|
||||
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
|
||||
- pte[0] = be64_to_cpu(pte[0]);
|
||||
- pte[1] = be64_to_cpu(pte[1]);
|
||||
+ pte[0] = be64_to_cpu((__force __be64)pte[0]);
|
||||
+ pte[1] = be64_to_cpu((__force __be64)pte[1]);
|
||||
|
||||
ret = H_NOT_FOUND;
|
||||
if ((pte[0] & HPTE_V_VALID) == 0 ||
|
||||
@@ -231,8 +232,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
|
||||
|
||||
rb = compute_tlbie_rb(v, r, pte_index);
|
||||
vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
|
||||
- pte[0] = cpu_to_be64(pte[0]);
|
||||
- pte[1] = cpu_to_be64(pte[1]);
|
||||
+ pte[0] = (__force u64)cpu_to_be64(pte[0]);
|
||||
+ pte[1] = (__force u64)cpu_to_be64(pte[1]);
|
||||
copy_to_user((void __user *)pteg, pte, sizeof(pte));
|
||||
ret = H_SUCCESS;
|
||||
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Mon, 16 Jun 2014 16:37:38 +0200
|
||||
Subject: KVM: PPC: Book3S PR: Handle hyp doorbell exits
|
||||
Origin: https://git.kernel.org/linus/568fccc43f901889b94b228cd0238916cb40e0bd
|
||||
|
||||
If we're running PR KVM in HV mode, we may get hypervisor doorbell interrupts.
|
||||
Handle those the same way we treat normal doorbells.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
arch/powerpc/kvm/book3s_pr.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
|
||||
index 8ea7da4..3b82e86 100644
|
||||
--- a/arch/powerpc/kvm/book3s_pr.c
|
||||
+++ b/arch/powerpc/kvm/book3s_pr.c
|
||||
@@ -988,6 +988,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
case BOOK3S_INTERRUPT_DECREMENTER:
|
||||
case BOOK3S_INTERRUPT_HV_DECREMENTER:
|
||||
case BOOK3S_INTERRUPT_DOORBELL:
|
||||
+ case BOOK3S_INTERRUPT_H_DOORBELL:
|
||||
vcpu->stat.dec_exits++;
|
||||
r = RESUME_GUEST;
|
||||
break;
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 11 Jun 2014 17:13:55 +0200
|
||||
Subject: KVM: PPC: Book3s HV: Fix tlbie compile error
|
||||
Origin: https://git.kernel.org/linus/f6bf3a66227447f89f25b9db0ae39357decf2509
|
||||
|
||||
Some compilers complain about uninitialized variables in the compute_tlbie_rb
|
||||
function. When you follow the code path you'll realize that we'll never get
|
||||
to that point, but the compiler isn't all that smart.
|
||||
|
||||
So just default to 4k page sizes for everything, making the compiler happy
|
||||
and the code slightly easier to read.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
Acked-by: Paul Mackerras <paulus@samba.org>
|
||||
---
|
||||
arch/powerpc/include/asm/kvm_book3s_64.h | 8 ++------
|
||||
1 file changed, 2 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
|
||||
index fddb72b..c7871f3 100644
|
||||
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
|
||||
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
|
||||
@@ -110,16 +110,12 @@ static inline int __hpte_actual_psize(unsigned int lp, int psize)
|
||||
static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
|
||||
unsigned long pte_index)
|
||||
{
|
||||
- int b_psize, a_psize;
|
||||
+ int b_psize = MMU_PAGE_4K, a_psize = MMU_PAGE_4K;
|
||||
unsigned int penc;
|
||||
unsigned long rb = 0, va_low, sllp;
|
||||
unsigned int lp = (r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
|
||||
|
||||
- if (!(v & HPTE_V_LARGE)) {
|
||||
- /* both base and actual psize is 4k */
|
||||
- b_psize = MMU_PAGE_4K;
|
||||
- a_psize = MMU_PAGE_4K;
|
||||
- } else {
|
||||
+ if (v & HPTE_V_LARGE) {
|
||||
for (b_psize = 0; b_psize < MMU_PAGE_COUNT; b_psize++) {
|
||||
|
||||
/* valid entries have a shift value */
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Mon, 9 Jun 2014 01:16:32 +0200
|
||||
Subject: KVM: PPC: Book3s PR: Disable AIL mode with OPAL
|
||||
Origin: https://git.kernel.org/linus/fb4188bad02f4871b26cf19b98e8d92499ca5d31
|
||||
|
||||
When we're using PR KVM we must not allow the CPU to take interrupts
|
||||
in virtual mode, as the SLB does not contain host kernel mappings
|
||||
when running inside the guest context.
|
||||
|
||||
To make sure we get good performance for non-KVM tasks but still
|
||||
properly functioning PR KVM, let's just disable AIL whenever a vcpu
|
||||
is scheduled in.
|
||||
|
||||
This is fundamentally different from how we deal with AIL on pSeries
|
||||
type machines where we disable AIL for the whole machine as soon as
|
||||
a single KVM VM is up.
|
||||
|
||||
The reason for that is easy - on pSeries we do not have control over
|
||||
per-cpu configuration of AIL. We also don't want to mess with CPU hotplug
|
||||
races and AIL configuration, so setting it per CPU is easier and more
|
||||
flexible.
|
||||
|
||||
This patch fixes running PR KVM on POWER8 bare metal for me.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
Acked-by: Paul Mackerras <paulus@samba.org>
|
||||
---
|
||||
arch/powerpc/kvm/book3s_pr.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
|
||||
index 3da412e..8ea7da4 100644
|
||||
--- a/arch/powerpc/kvm/book3s_pr.c
|
||||
+++ b/arch/powerpc/kvm/book3s_pr.c
|
||||
@@ -71,6 +71,12 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
|
||||
svcpu->in_use = 0;
|
||||
svcpu_put(svcpu);
|
||||
#endif
|
||||
+
|
||||
+ /* Disable AIL if supported */
|
||||
+ if (cpu_has_feature(CPU_FTR_HVMODE) &&
|
||||
+ cpu_has_feature(CPU_FTR_ARCH_207S))
|
||||
+ mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~LPCR_AIL);
|
||||
+
|
||||
vcpu->cpu = smp_processor_id();
|
||||
#ifdef CONFIG_PPC_BOOK3S_32
|
||||
current->thread.kvm_shadow_vcpu = vcpu->arch.shadow_vcpu;
|
||||
@@ -91,6 +97,12 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
|
||||
|
||||
kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
|
||||
kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
|
||||
+
|
||||
+ /* Enable AIL if supported */
|
||||
+ if (cpu_has_feature(CPU_FTR_HVMODE) &&
|
||||
+ cpu_has_feature(CPU_FTR_ARCH_207S))
|
||||
+ mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_AIL_3);
|
||||
+
|
||||
vcpu->cpu = -1;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,193 +0,0 @@
|
|||
From: Paul Mackerras <paulus@samba.org>
|
||||
Date: Mon, 30 Jun 2014 20:51:14 +1000
|
||||
Subject: KVM: PPC: Enable IRQFD support for the XICS interrupt
|
||||
controller
|
||||
Origin: https://git.kernel.org/linus/25a2150bee00b4d996487552948b9b3ba21d0257
|
||||
|
||||
This makes it possible to use IRQFDs on platforms that use the XICS
|
||||
interrupt controller. To do this we implement kvm_irq_map_gsi() and
|
||||
kvm_irq_map_chip_pin() in book3s_xics.c, so as to provide a 1-1 mapping
|
||||
between global interrupt numbers and XICS interrupt source numbers.
|
||||
For now, all interrupts are mapped as "IRQCHIP" interrupts, and no
|
||||
MSI support is provided.
|
||||
|
||||
This means that kvm_set_irq can now get called with level == 0 or 1
|
||||
as well as the powerpc-specific values KVM_INTERRUPT_SET,
|
||||
KVM_INTERRUPT_UNSET and KVM_INTERRUPT_SET_LEVEL. We change
|
||||
ics_deliver_irq() to accept all those values, and remove its
|
||||
report_status argument, as it is always false, given that we don't
|
||||
support KVM_IRQ_LINE_STATUS.
|
||||
|
||||
This also adds support for interrupt ack notifiers to the XICS code
|
||||
so that the IRQFD resampler functionality can be supported.
|
||||
|
||||
Signed-off-by: Paul Mackerras <paulus@samba.org>
|
||||
Tested-by: Eric Auger <eric.auger@linaro.org>
|
||||
Tested-by: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
arch/powerpc/kvm/Kconfig | 2 ++
|
||||
arch/powerpc/kvm/book3s_hv_rm_xics.c | 5 ++++
|
||||
arch/powerpc/kvm/book3s_xics.c | 55 ++++++++++++++++++++++++++++------
|
||||
arch/powerpc/kvm/book3s_xics.h | 2 ++
|
||||
4 files changed, 55 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
|
||||
index d4741db..602eb51 100644
|
||||
--- a/arch/powerpc/kvm/Kconfig
|
||||
+++ b/arch/powerpc/kvm/Kconfig
|
||||
@@ -170,6 +170,8 @@ config KVM_MPIC
|
||||
config KVM_XICS
|
||||
bool "KVM in-kernel XICS emulation"
|
||||
depends on KVM_BOOK3S_64 && !KVM_MPIC
|
||||
+ select HAVE_KVM_IRQCHIP
|
||||
+ select HAVE_KVM_IRQFD
|
||||
---help---
|
||||
Include support for the XICS (eXternal Interrupt Controller
|
||||
Specification) interrupt controller architecture used on
|
||||
diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c
|
||||
index b4b0082..3ee38e6 100644
|
||||
--- a/arch/powerpc/kvm/book3s_hv_rm_xics.c
|
||||
+++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c
|
||||
@@ -401,6 +401,11 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
|
||||
icp->rm_action |= XICS_RM_REJECT;
|
||||
icp->rm_reject = irq;
|
||||
}
|
||||
+
|
||||
+ if (!hlist_empty(&vcpu->kvm->irq_ack_notifier_list)) {
|
||||
+ icp->rm_action |= XICS_RM_NOTIFY_EOI;
|
||||
+ icp->rm_eoied_irq = irq;
|
||||
+ }
|
||||
bail:
|
||||
return check_too_hard(xics, icp);
|
||||
}
|
||||
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
|
||||
index d1acd32..eaeb780 100644
|
||||
--- a/arch/powerpc/kvm/book3s_xics.c
|
||||
+++ b/arch/powerpc/kvm/book3s_xics.c
|
||||
@@ -64,8 +64,12 @@
|
||||
static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
|
||||
u32 new_irq);
|
||||
|
||||
-static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level,
|
||||
- bool report_status)
|
||||
+/*
|
||||
+ * Return value ideally indicates how the interrupt was handled, but no
|
||||
+ * callers look at it (given that we don't implement KVM_IRQ_LINE_STATUS),
|
||||
+ * so just return 0.
|
||||
+ */
|
||||
+static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level)
|
||||
{
|
||||
struct ics_irq_state *state;
|
||||
struct kvmppc_ics *ics;
|
||||
@@ -82,17 +86,14 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level,
|
||||
if (!state->exists)
|
||||
return -EINVAL;
|
||||
|
||||
- if (report_status)
|
||||
- return state->asserted;
|
||||
-
|
||||
/*
|
||||
* We set state->asserted locklessly. This should be fine as
|
||||
* we are the only setter, thus concurrent access is undefined
|
||||
* to begin with.
|
||||
*/
|
||||
- if (level == KVM_INTERRUPT_SET_LEVEL)
|
||||
+ if (level == 1 || level == KVM_INTERRUPT_SET_LEVEL)
|
||||
state->asserted = 1;
|
||||
- else if (level == KVM_INTERRUPT_UNSET) {
|
||||
+ else if (level == 0 || level == KVM_INTERRUPT_UNSET) {
|
||||
state->asserted = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -100,7 +101,7 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level,
|
||||
/* Attempt delivery */
|
||||
icp_deliver_irq(xics, NULL, irq);
|
||||
|
||||
- return state->asserted;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
|
||||
@@ -772,6 +773,8 @@ static noinline int kvmppc_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
|
||||
if (state->asserted)
|
||||
icp_deliver_irq(xics, icp, irq);
|
||||
|
||||
+ kvm_notify_acked_irq(vcpu->kvm, 0, irq);
|
||||
+
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -789,6 +792,8 @@ static noinline int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall)
|
||||
icp_check_resend(xics, icp);
|
||||
if (icp->rm_action & XICS_RM_REJECT)
|
||||
icp_deliver_irq(xics, icp, icp->rm_reject);
|
||||
+ if (icp->rm_action & XICS_RM_NOTIFY_EOI)
|
||||
+ kvm_notify_acked_irq(vcpu->kvm, 0, icp->rm_eoied_irq);
|
||||
|
||||
icp->rm_action = 0;
|
||||
|
||||
@@ -1170,7 +1175,16 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
|
||||
{
|
||||
struct kvmppc_xics *xics = kvm->arch.xics;
|
||||
|
||||
- return ics_deliver_irq(xics, irq, level, line_status);
|
||||
+ return ics_deliver_irq(xics, irq, level);
|
||||
+}
|
||||
+
|
||||
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm,
|
||||
+ int irq_source_id, int level, bool line_status)
|
||||
+{
|
||||
+ if (!level)
|
||||
+ return -1;
|
||||
+ return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi,
|
||||
+ level, line_status);
|
||||
}
|
||||
|
||||
static int xics_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
|
||||
@@ -1301,3 +1315,26 @@ void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu)
|
||||
vcpu->arch.icp = NULL;
|
||||
vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT;
|
||||
}
|
||||
+
|
||||
+static int xics_set_irq(struct kvm_kernel_irq_routing_entry *e,
|
||||
+ struct kvm *kvm, int irq_source_id, int level,
|
||||
+ bool line_status)
|
||||
+{
|
||||
+ return kvm_set_irq(kvm, irq_source_id, e->gsi, level, line_status);
|
||||
+}
|
||||
+
|
||||
+int kvm_irq_map_gsi(struct kvm *kvm,
|
||||
+ struct kvm_kernel_irq_routing_entry *entries, int gsi)
|
||||
+{
|
||||
+ entries->gsi = gsi;
|
||||
+ entries->type = KVM_IRQ_ROUTING_IRQCHIP;
|
||||
+ entries->set = xics_set_irq;
|
||||
+ entries->irqchip.irqchip = 0;
|
||||
+ entries->irqchip.pin = gsi;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin)
|
||||
+{
|
||||
+ return pin;
|
||||
+}
|
||||
diff --git a/arch/powerpc/kvm/book3s_xics.h b/arch/powerpc/kvm/book3s_xics.h
|
||||
index dd9326c..e8aaa7a 100644
|
||||
--- a/arch/powerpc/kvm/book3s_xics.h
|
||||
+++ b/arch/powerpc/kvm/book3s_xics.h
|
||||
@@ -71,9 +71,11 @@ struct kvmppc_icp {
|
||||
#define XICS_RM_KICK_VCPU 0x1
|
||||
#define XICS_RM_CHECK_RESEND 0x2
|
||||
#define XICS_RM_REJECT 0x4
|
||||
+#define XICS_RM_NOTIFY_EOI 0x8
|
||||
u32 rm_action;
|
||||
struct kvm_vcpu *rm_kick_target;
|
||||
u32 rm_reject;
|
||||
+ u32 rm_eoied_irq;
|
||||
|
||||
/* Debug stuff for real mode */
|
||||
union kvmppc_icp_state rm_dbgstate;
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Mon, 14 Jul 2014 18:27:35 +0200
|
||||
Subject: KVM: Rename and add argument to check_extension
|
||||
Origin: https://git.kernel.org/linus/784aa3d7fb6f729c06d5836c9d9569f58e4d05ae
|
||||
|
||||
In preparation to make the check_extension function available to VM scope
|
||||
we add a struct kvm * argument to the function header and rename the function
|
||||
accordingly. It will still be called from the /dev/kvm fd, but with a NULL
|
||||
argument for struct kvm *.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
arch/arm/kvm/arm.c | 2 +-
|
||||
arch/ia64/kvm/kvm-ia64.c | 2 +-
|
||||
arch/mips/kvm/kvm_mips.c | 2 +-
|
||||
arch/powerpc/kvm/powerpc.c | 2 +-
|
||||
arch/s390/kvm/kvm-s390.c | 2 +-
|
||||
arch/x86/kvm/x86.c | 2 +-
|
||||
include/linux/kvm_host.h | 2 +-
|
||||
virt/kvm/kvm_main.c | 6 +++---
|
||||
8 files changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
|
||||
index 3c82b37..cb77f999 100644
|
||||
--- a/arch/arm/kvm/arm.c
|
||||
+++ b/arch/arm/kvm/arm.c
|
||||
@@ -184,7 +184,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
|
||||
}
|
||||
}
|
||||
|
||||
-int kvm_dev_ioctl_check_extension(long ext)
|
||||
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
{
|
||||
int r;
|
||||
switch (ext) {
|
||||
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
|
||||
index 6a4309b..0729ba6 100644
|
||||
--- a/arch/ia64/kvm/kvm-ia64.c
|
||||
+++ b/arch/ia64/kvm/kvm-ia64.c
|
||||
@@ -190,7 +190,7 @@ void kvm_arch_check_processor_compat(void *rtn)
|
||||
*(int *)rtn = 0;
|
||||
}
|
||||
|
||||
-int kvm_dev_ioctl_check_extension(long ext)
|
||||
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
{
|
||||
|
||||
int r;
|
||||
diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/kvm_mips.c
|
||||
index d687c6e..3ca79aa 100644
|
||||
--- a/arch/mips/kvm/kvm_mips.c
|
||||
+++ b/arch/mips/kvm/kvm_mips.c
|
||||
@@ -885,7 +885,7 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
||||
-int kvm_dev_ioctl_check_extension(long ext)
|
||||
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
{
|
||||
int r;
|
||||
|
||||
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
|
||||
index 8e03568..d870bac 100644
|
||||
--- a/arch/powerpc/kvm/powerpc.c
|
||||
+++ b/arch/powerpc/kvm/powerpc.c
|
||||
@@ -391,7 +391,7 @@ void kvm_arch_sync_events(struct kvm *kvm)
|
||||
{
|
||||
}
|
||||
|
||||
-int kvm_dev_ioctl_check_extension(long ext)
|
||||
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
{
|
||||
int r;
|
||||
/* FIXME!!
|
||||
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
|
||||
index 2f3e14f..00268ca 100644
|
||||
--- a/arch/s390/kvm/kvm-s390.c
|
||||
+++ b/arch/s390/kvm/kvm-s390.c
|
||||
@@ -146,7 +146,7 @@ long kvm_arch_dev_ioctl(struct file *filp,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
-int kvm_dev_ioctl_check_extension(long ext)
|
||||
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
{
|
||||
int r;
|
||||
|
||||
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
|
||||
index 5a8691b..5a62d91 100644
|
||||
--- a/arch/x86/kvm/x86.c
|
||||
+++ b/arch/x86/kvm/x86.c
|
||||
@@ -2616,7 +2616,7 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
-int kvm_dev_ioctl_check_extension(long ext)
|
||||
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
{
|
||||
int r;
|
||||
|
||||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
|
||||
index ec4e3bd..5065b95 100644
|
||||
--- a/include/linux/kvm_host.h
|
||||
+++ b/include/linux/kvm_host.h
|
||||
@@ -602,7 +602,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
|
||||
unsigned int ioctl, unsigned long arg);
|
||||
int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf);
|
||||
|
||||
-int kvm_dev_ioctl_check_extension(long ext);
|
||||
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext);
|
||||
|
||||
int kvm_get_dirty_log(struct kvm *kvm,
|
||||
struct kvm_dirty_log *log, int *is_dirty);
|
||||
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
|
||||
index 4b6c01b..e28f3ca 100644
|
||||
--- a/virt/kvm/kvm_main.c
|
||||
+++ b/virt/kvm/kvm_main.c
|
||||
@@ -2571,7 +2571,7 @@ static int kvm_dev_ioctl_create_vm(unsigned long type)
|
||||
return r;
|
||||
}
|
||||
|
||||
-static long kvm_dev_ioctl_check_extension_generic(long arg)
|
||||
+static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
|
||||
{
|
||||
switch (arg) {
|
||||
case KVM_CAP_USER_MEMORY:
|
||||
@@ -2595,7 +2595,7 @@ static long kvm_dev_ioctl_check_extension_generic(long arg)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
- return kvm_dev_ioctl_check_extension(arg);
|
||||
+ return kvm_vm_ioctl_check_extension(kvm, arg);
|
||||
}
|
||||
|
||||
static long kvm_dev_ioctl(struct file *filp,
|
||||
@@ -2614,7 +2614,7 @@ static long kvm_dev_ioctl(struct file *filp,
|
||||
r = kvm_dev_ioctl_create_vm(arg);
|
||||
break;
|
||||
case KVM_CHECK_EXTENSION:
|
||||
- r = kvm_dev_ioctl_check_extension_generic(arg);
|
||||
+ r = kvm_vm_ioctl_check_extension_generic(NULL, arg);
|
||||
break;
|
||||
case KVM_GET_VCPU_MMAP_SIZE:
|
||||
r = -EINVAL;
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,278 +0,0 @@
|
|||
From: Paul Mackerras <paulus@samba.org>
|
||||
Date: Mon, 30 Jun 2014 20:51:10 +1000
|
||||
Subject: KVM: irqchip: Provide and use accessors for irq
|
||||
routing table
|
||||
Origin: https://git.kernel.org/linus/8ba918d488caded2c4368b0b922eb905fe3bb101
|
||||
|
||||
This provides accessor functions for the KVM interrupt mappings, in
|
||||
order to reduce the amount of code that accesses the fields of the
|
||||
kvm_irq_routing_table struct, and restrict that code to one file,
|
||||
virt/kvm/irqchip.c. The new functions are kvm_irq_map_gsi(), which
|
||||
maps from a global interrupt number to a set of IRQ routing entries,
|
||||
and kvm_irq_map_chip_pin, which maps from IRQ chip and pin numbers to
|
||||
a global interrupt number.
|
||||
|
||||
This also moves the update of kvm_irq_routing_table::chip[][]
|
||||
into irqchip.c, out of the various kvm_set_routing_entry
|
||||
implementations. That means that none of the kvm_set_routing_entry
|
||||
implementations need the kvm_irq_routing_table argument anymore,
|
||||
so this removes it.
|
||||
|
||||
This does not change any locking or data lifetime rules.
|
||||
|
||||
Signed-off-by: Paul Mackerras <paulus@samba.org>
|
||||
Tested-by: Eric Auger <eric.auger@linaro.org>
|
||||
Tested-by: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
arch/powerpc/kvm/mpic.c | 4 +---
|
||||
arch/s390/kvm/interrupt.c | 3 +--
|
||||
include/linux/kvm_host.h | 8 ++++++--
|
||||
virt/kvm/eventfd.c | 10 ++++++----
|
||||
virt/kvm/irq_comm.c | 20 +++++++++-----------
|
||||
virt/kvm/irqchip.c | 42 ++++++++++++++++++++++++++++++++++--------
|
||||
6 files changed, 57 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/kvm/mpic.c b/arch/powerpc/kvm/mpic.c
|
||||
index b68d0dc..39b3a8f 100644
|
||||
--- a/arch/powerpc/kvm/mpic.c
|
||||
+++ b/arch/powerpc/kvm/mpic.c
|
||||
@@ -1826,8 +1826,7 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
|
||||
- struct kvm_kernel_irq_routing_entry *e,
|
||||
+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
|
||||
const struct kvm_irq_routing_entry *ue)
|
||||
{
|
||||
int r = -EINVAL;
|
||||
@@ -1839,7 +1838,6 @@ int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
|
||||
e->irqchip.pin = ue->u.irqchip.pin;
|
||||
if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS)
|
||||
goto out;
|
||||
- rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi;
|
||||
break;
|
||||
case KVM_IRQ_ROUTING_MSI:
|
||||
e->set = kvm_set_msi;
|
||||
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
|
||||
index 92528a0..f4c819b 100644
|
||||
--- a/arch/s390/kvm/interrupt.c
|
||||
+++ b/arch/s390/kvm/interrupt.c
|
||||
@@ -1556,8 +1556,7 @@ static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
|
||||
- struct kvm_kernel_irq_routing_entry *e,
|
||||
+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
|
||||
const struct kvm_irq_routing_entry *ue)
|
||||
{
|
||||
int ret;
|
||||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
|
||||
index 5065b95..4956149 100644
|
||||
--- a/include/linux/kvm_host.h
|
||||
+++ b/include/linux/kvm_host.h
|
||||
@@ -752,6 +752,11 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
|
||||
void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
|
||||
bool mask);
|
||||
|
||||
+int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries,
|
||||
+ struct kvm_irq_routing_table *irq_rt, int gsi);
|
||||
+int kvm_irq_map_chip_pin(struct kvm_irq_routing_table *irq_rt,
|
||||
+ unsigned irqchip, unsigned pin);
|
||||
+
|
||||
int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
|
||||
bool line_status);
|
||||
int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level);
|
||||
@@ -942,8 +947,7 @@ int kvm_set_irq_routing(struct kvm *kvm,
|
||||
const struct kvm_irq_routing_entry *entries,
|
||||
unsigned nr,
|
||||
unsigned flags);
|
||||
-int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
|
||||
- struct kvm_kernel_irq_routing_entry *e,
|
||||
+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
|
||||
const struct kvm_irq_routing_entry *ue);
|
||||
void kvm_free_irq_routing(struct kvm *kvm);
|
||||
|
||||
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
|
||||
index bae593a..15fa948 100644
|
||||
--- a/virt/kvm/eventfd.c
|
||||
+++ b/virt/kvm/eventfd.c
|
||||
@@ -282,20 +282,22 @@ static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd,
|
||||
struct kvm_irq_routing_table *irq_rt)
|
||||
{
|
||||
struct kvm_kernel_irq_routing_entry *e;
|
||||
+ struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS];
|
||||
+ int i, n_entries;
|
||||
+
|
||||
+ n_entries = kvm_irq_map_gsi(entries, irq_rt, irqfd->gsi);
|
||||
|
||||
write_seqcount_begin(&irqfd->irq_entry_sc);
|
||||
|
||||
irqfd->irq_entry.type = 0;
|
||||
- if (irqfd->gsi >= irq_rt->nr_rt_entries)
|
||||
- goto out;
|
||||
|
||||
- hlist_for_each_entry(e, &irq_rt->map[irqfd->gsi], link) {
|
||||
+ e = entries;
|
||||
+ for (i = 0; i < n_entries; ++i, ++e) {
|
||||
/* Only fast-path MSI. */
|
||||
if (e->type == KVM_IRQ_ROUTING_MSI)
|
||||
irqfd->irq_entry = *e;
|
||||
}
|
||||
|
||||
- out:
|
||||
write_seqcount_end(&irqfd->irq_entry_sc);
|
||||
}
|
||||
|
||||
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
|
||||
index a228ee8..1758445 100644
|
||||
--- a/virt/kvm/irq_comm.c
|
||||
+++ b/virt/kvm/irq_comm.c
|
||||
@@ -160,6 +160,7 @@ static int kvm_set_msi_inatomic(struct kvm_kernel_irq_routing_entry *e,
|
||||
*/
|
||||
int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level)
|
||||
{
|
||||
+ struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS];
|
||||
struct kvm_kernel_irq_routing_entry *e;
|
||||
int ret = -EINVAL;
|
||||
struct kvm_irq_routing_table *irq_rt;
|
||||
@@ -177,14 +178,13 @@ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level)
|
||||
*/
|
||||
idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
|
||||
- if (irq < irq_rt->nr_rt_entries)
|
||||
- hlist_for_each_entry(e, &irq_rt->map[irq], link) {
|
||||
- if (likely(e->type == KVM_IRQ_ROUTING_MSI))
|
||||
- ret = kvm_set_msi_inatomic(e, kvm);
|
||||
- else
|
||||
- ret = -EWOULDBLOCK;
|
||||
- break;
|
||||
- }
|
||||
+ if (kvm_irq_map_gsi(entries, irq_rt, irq) > 0) {
|
||||
+ e = &entries[0];
|
||||
+ if (likely(e->type == KVM_IRQ_ROUTING_MSI))
|
||||
+ ret = kvm_set_msi_inatomic(e, kvm);
|
||||
+ else
|
||||
+ ret = -EWOULDBLOCK;
|
||||
+ }
|
||||
srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
return ret;
|
||||
}
|
||||
@@ -272,8 +272,7 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
|
||||
srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
}
|
||||
|
||||
-int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
|
||||
- struct kvm_kernel_irq_routing_entry *e,
|
||||
+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
|
||||
const struct kvm_irq_routing_entry *ue)
|
||||
{
|
||||
int r = -EINVAL;
|
||||
@@ -304,7 +303,6 @@ int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
|
||||
e->irqchip.pin = ue->u.irqchip.pin + delta;
|
||||
if (e->irqchip.pin >= max_pin)
|
||||
goto out;
|
||||
- rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi;
|
||||
break;
|
||||
case KVM_IRQ_ROUTING_MSI:
|
||||
e->set = kvm_set_msi;
|
||||
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
|
||||
index b43c275..f4648dd 100644
|
||||
--- a/virt/kvm/irqchip.c
|
||||
+++ b/virt/kvm/irqchip.c
|
||||
@@ -31,13 +31,37 @@
|
||||
#include <trace/events/kvm.h>
|
||||
#include "irq.h"
|
||||
|
||||
+int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries,
|
||||
+ struct kvm_irq_routing_table *irq_rt, int gsi)
|
||||
+{
|
||||
+ struct kvm_kernel_irq_routing_entry *e;
|
||||
+ int n = 0;
|
||||
+
|
||||
+ if (gsi < irq_rt->nr_rt_entries) {
|
||||
+ hlist_for_each_entry(e, &irq_rt->map[gsi], link) {
|
||||
+ entries[n] = *e;
|
||||
+ ++n;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
+int kvm_irq_map_chip_pin(struct kvm_irq_routing_table *irq_rt,
|
||||
+ unsigned irqchip, unsigned pin)
|
||||
+{
|
||||
+ return irq_rt->chip[irqchip][pin];
|
||||
+}
|
||||
+
|
||||
bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin)
|
||||
{
|
||||
+ struct kvm_irq_routing_table *irq_rt;
|
||||
struct kvm_irq_ack_notifier *kian;
|
||||
int gsi, idx;
|
||||
|
||||
idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
- gsi = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu)->chip[irqchip][pin];
|
||||
+ irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
|
||||
+ gsi = kvm_irq_map_chip_pin(irq_rt, irqchip, pin);
|
||||
if (gsi != -1)
|
||||
hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
|
||||
link)
|
||||
@@ -54,13 +78,15 @@ EXPORT_SYMBOL_GPL(kvm_irq_has_notifier);
|
||||
|
||||
void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
|
||||
{
|
||||
+ struct kvm_irq_routing_table *irq_rt;
|
||||
struct kvm_irq_ack_notifier *kian;
|
||||
int gsi, idx;
|
||||
|
||||
trace_kvm_ack_irq(irqchip, pin);
|
||||
|
||||
idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
- gsi = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu)->chip[irqchip][pin];
|
||||
+ irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
|
||||
+ gsi = kvm_irq_map_chip_pin(irq_rt, irqchip, pin);
|
||||
if (gsi != -1)
|
||||
hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
|
||||
link)
|
||||
@@ -115,8 +141,8 @@ int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
|
||||
int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
|
||||
bool line_status)
|
||||
{
|
||||
- struct kvm_kernel_irq_routing_entry *e, irq_set[KVM_NR_IRQCHIPS];
|
||||
- int ret = -1, i = 0, idx;
|
||||
+ struct kvm_kernel_irq_routing_entry irq_set[KVM_NR_IRQCHIPS];
|
||||
+ int ret = -1, i, idx;
|
||||
struct kvm_irq_routing_table *irq_rt;
|
||||
|
||||
trace_kvm_set_irq(irq, level, irq_source_id);
|
||||
@@ -127,9 +153,7 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
|
||||
*/
|
||||
idx = srcu_read_lock(&kvm->irq_srcu);
|
||||
irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
|
||||
- if (irq < irq_rt->nr_rt_entries)
|
||||
- hlist_for_each_entry(e, &irq_rt->map[irq], link)
|
||||
- irq_set[i++] = *e;
|
||||
+ i = kvm_irq_map_gsi(irq_set, irq_rt, irq);
|
||||
srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||
|
||||
while(i--) {
|
||||
@@ -171,9 +195,11 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt,
|
||||
|
||||
e->gsi = ue->gsi;
|
||||
e->type = ue->type;
|
||||
- r = kvm_set_routing_entry(rt, e, ue);
|
||||
+ r = kvm_set_routing_entry(e, ue);
|
||||
if (r)
|
||||
goto out;
|
||||
+ if (e->type == KVM_IRQ_ROUTING_IRQCHIP)
|
||||
+ rt->chip[e->irqchip.irqchip][e->irqchip.pin] = e->gsi;
|
||||
|
||||
hlist_add_head(&e->link, &rt->map[e->gsi]);
|
||||
r = 0;
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
From: David Hildenbrand <dahi@linux.vnet.ibm.com>
|
||||
Date: Mon, 12 May 2014 16:05:13 +0200
|
||||
Subject: KVM: prepare for KVM_(S|G)ET_MP_STATE on other
|
||||
architectures
|
||||
Origin: https://git.kernel.org/linus/0b4820d6d8b6448bc9f7fac1bb1a801a53b425e1
|
||||
|
||||
Highlight the aspects of the ioctls that are actually specific to x86
|
||||
and ia64. As defined restrictions (irqchip) and mp states may not apply
|
||||
to other architectures, these parts are flagged to belong to x86 and ia64.
|
||||
|
||||
In preparation for the use of KVM_(S|G)ET_MP_STATE by s390.
|
||||
Fix a spelling error (KVM_SET_MP_STATE vs. KVM_SET_MPSTATE) on the way.
|
||||
|
||||
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
|
||||
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||
---
|
||||
Documentation/virtual/kvm/api.txt | 21 ++++++++++++---------
|
||||
include/uapi/linux/kvm.h | 3 ++-
|
||||
2 files changed, 14 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
|
||||
index 0fe3649..904c61c 100644
|
||||
--- a/Documentation/virtual/kvm/api.txt
|
||||
+++ b/Documentation/virtual/kvm/api.txt
|
||||
@@ -988,18 +988,20 @@ uniprocessor guests).
|
||||
|
||||
Possible values are:
|
||||
|
||||
- - KVM_MP_STATE_RUNNABLE: the vcpu is currently running
|
||||
+ - KVM_MP_STATE_RUNNABLE: the vcpu is currently running [x86, ia64]
|
||||
- KVM_MP_STATE_UNINITIALIZED: the vcpu is an application processor (AP)
|
||||
- which has not yet received an INIT signal
|
||||
+ which has not yet received an INIT signal [x86,
|
||||
+ ia64]
|
||||
- KVM_MP_STATE_INIT_RECEIVED: the vcpu has received an INIT signal, and is
|
||||
- now ready for a SIPI
|
||||
+ now ready for a SIPI [x86, ia64]
|
||||
- KVM_MP_STATE_HALTED: the vcpu has executed a HLT instruction and
|
||||
- is waiting for an interrupt
|
||||
+ is waiting for an interrupt [x86, ia64]
|
||||
- KVM_MP_STATE_SIPI_RECEIVED: the vcpu has just received a SIPI (vector
|
||||
- accessible via KVM_GET_VCPU_EVENTS)
|
||||
+ accessible via KVM_GET_VCPU_EVENTS) [x86, ia64]
|
||||
|
||||
-This ioctl is only useful after KVM_CREATE_IRQCHIP. Without an in-kernel
|
||||
-irqchip, the multiprocessing state must be maintained by userspace.
|
||||
+On x86 and ia64, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
|
||||
+in-kernel irqchip, the multiprocessing state must be maintained by userspace on
|
||||
+these architectures.
|
||||
|
||||
|
||||
4.39 KVM_SET_MP_STATE
|
||||
@@ -1013,8 +1015,9 @@ Returns: 0 on success; -1 on error
|
||||
Sets the vcpu's current "multiprocessing state"; see KVM_GET_MP_STATE for
|
||||
arguments.
|
||||
|
||||
-This ioctl is only useful after KVM_CREATE_IRQCHIP. Without an in-kernel
|
||||
-irqchip, the multiprocessing state must be maintained by userspace.
|
||||
+On x86 and ia64, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
|
||||
+in-kernel irqchip, the multiprocessing state must be maintained by userspace on
|
||||
+these architectures.
|
||||
|
||||
|
||||
4.40 KVM_SET_IDENTITY_MAP_ADDR
|
||||
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
|
||||
index e11d8f1..37d4ec6 100644
|
||||
--- a/include/uapi/linux/kvm.h
|
||||
+++ b/include/uapi/linux/kvm.h
|
||||
@@ -399,8 +399,9 @@ struct kvm_vapic_addr {
|
||||
__u64 vapic_addr;
|
||||
};
|
||||
|
||||
-/* for KVM_SET_MPSTATE */
|
||||
+/* for KVM_SET_MP_STATE */
|
||||
|
||||
+/* not all states are valid on all architectures */
|
||||
#define KVM_MP_STATE_RUNNABLE 0
|
||||
#define KVM_MP_STATE_UNINITIALIZED 1
|
||||
#define KVM_MP_STATE_INIT_RECEIVED 2
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 11 Jun 2014 10:07:40 +0200
|
||||
Subject: PPC: Add asm helpers for BE 32bit load/store
|
||||
Origin: https://git.kernel.org/linus/8f6822c4b9fac6e47414d2f1e11dbabda9bc2163
|
||||
|
||||
From assembly code we might not only have to explicitly BE access 64bit values,
|
||||
but sometimes also 32bit ones. Add helpers that allow for easy use of lwzx/stwx
|
||||
in their respective byte-reverse or native form.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
|
||||
---
|
||||
arch/powerpc/include/asm/asm-compat.h | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h
|
||||
index 4b237aa..21be8ae 100644
|
||||
--- a/arch/powerpc/include/asm/asm-compat.h
|
||||
+++ b/arch/powerpc/include/asm/asm-compat.h
|
||||
@@ -34,10 +34,14 @@
|
||||
#define PPC_MIN_STKFRM 112
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
+#define LWZX_BE stringify_in_c(lwzx)
|
||||
#define LDX_BE stringify_in_c(ldx)
|
||||
+#define STWX_BE stringify_in_c(stwx)
|
||||
#define STDX_BE stringify_in_c(stdx)
|
||||
#else
|
||||
+#define LWZX_BE stringify_in_c(lwbrx)
|
||||
#define LDX_BE stringify_in_c(ldbrx)
|
||||
+#define STWX_BE stringify_in_c(stwbrx)
|
||||
#define STDX_BE stringify_in_c(stdbrx)
|
||||
#endif
|
||||
|
||||
--
|
||||
1.7.10.4
|
||||
|
|
@ -18,13 +18,13 @@ bugfix/all/radeon-firmware-is-required-for-drm-and-kms-on-r600-onward.patch
|
|||
|
||||
# Patches and source files from aufs3 repository, imported with
|
||||
# debian/patches/features/all/aufs3/gen-patch.
|
||||
features/all/aufs3/aufs3-kbuild.patch
|
||||
features/all/aufs3/aufs3-base.patch
|
||||
features/all/aufs3/aufs3-mmap.patch
|
||||
features/all/aufs3/aufs3-standalone.patch
|
||||
features/all/aufs3/aufs3-add.patch
|
||||
#features/all/aufs3/aufs3-kbuild.patch
|
||||
#features/all/aufs3/aufs3-base.patch
|
||||
#features/all/aufs3/aufs3-mmap.patch
|
||||
#features/all/aufs3/aufs3-standalone.patch
|
||||
#features/all/aufs3/aufs3-add.patch
|
||||
# Debian-specific changes
|
||||
debian/aufs3-mark-as-staging.patch
|
||||
#debian/aufs3-mark-as-staging.patch
|
||||
|
||||
# Change some defaults for security reasons
|
||||
debian/af_802154-Disable-auto-loading-as-mitigation-against.patch
|
||||
|
@ -52,75 +52,23 @@ bugfix/mips/disable-advansys.patch
|
|||
bugfix/arm/ixp4xx_iobe.patch
|
||||
bugfix/m68k/ethernat-kconfig.patch
|
||||
bugfix/mips/MIPS-ZBOOT-add-missing-linux-string.h-include.patch
|
||||
bugfix/mips/MIPS-OCTEON-make-get_system_type-thread-safe.patch
|
||||
bugfix/mips/MIPS-O32-32-bit-Fix-bug-which-can-cause-incorrect-sy.patch
|
||||
bugfix/mips/MIPS-tlbex-fix-a-missing-statement-for-HUGETLB.patch
|
||||
bugfix/mips/MIPS-prevent-user-from-setting-FCSR-cause-bits.patch
|
||||
bugfix/mips/MIPS-Remove-BUG_ON-is_fpu_owner-in-do_ade.patch
|
||||
bugfix/x86/x86-reject-x32-executables-if-x32-abi-not-supported.patch
|
||||
bugfix/s390/s390-3215-fix-hanging-console-issue.patch
|
||||
|
||||
# Arch features
|
||||
features/mips/MIPS-Support-hard-limit-of-cpu-count-nr_cpu_ids.patch
|
||||
features/mips/MIPS-Support-CPU-topology-files-in-sysfs.patch
|
||||
features/mips/MIPS-Loongson-Modify-ChipConfig-register-definition.patch
|
||||
features/mips/MIPS-Add-NUMA-support-for-Loongson-3.patch
|
||||
features/mips/MIPS-Add-numa-api-support.patch
|
||||
features/mips/MIPS-Add-Loongson-3B-support.patch
|
||||
features/mips/MIPS-Loongson-3-Enable-the-COP2-usage.patch
|
||||
features/mips/MIPS-Loongson-Rename-CONFIG_LEMOTE_MACH3A-to-CONFIG_.patch
|
||||
features/mips/MIPS-Loongson-3-Add-Loongson-LS3A-RS780E-1-way-machi.patch
|
||||
features/powerpc/KVM-prepare-for-KVM_-S-G-ET_MP_STATE-on-other-archit.patch
|
||||
features/powerpc/KVM-PPC-Book3s-PR-Disable-AIL-mode-with-OPAL.patch
|
||||
features/powerpc/KVM-PPC-Book3s-HV-Fix-tlbie-compile-error.patch
|
||||
features/powerpc/KVM-PPC-Book3S-PR-Handle-hyp-doorbell-exits.patch
|
||||
features/powerpc/KVM-PPC-Book3S-HV-Fix-ABIv2-indirect-branch-issue.patch
|
||||
features/powerpc/KVM-PPC-Book3S-PR-Fix-sparse-endian-checks.patch
|
||||
features/powerpc/KVM-PPC-Book3S-Controls-for-in-kernel-sPAPR-hypercal.patch
|
||||
features/powerpc/PPC-Add-asm-helpers-for-BE-32bit-load-store.patch
|
||||
features/powerpc/KVM-PPC-Book3S-HV-Make-HTAB-code-LE-host-aware.patch
|
||||
features/powerpc/KVM-PPC-Book3S-HV-Access-guest-VPA-in-BE.patch
|
||||
features/powerpc/KVM-PPC-Book3S-HV-Access-host-lppaca-and-shadow-slb-.patch
|
||||
features/powerpc/KVM-PPC-Book3S-HV-Access-XICS-in-BE.patch
|
||||
features/powerpc/KVM-PPC-Book3S-HV-Fix-ABIv2-on-LE.patch
|
||||
features/powerpc/KVM-PPC-Book3S-HV-Enable-for-little-endian-hosts.patch
|
||||
features/powerpc/KVM-Rename-and-add-argument-to-check_extension.patch
|
||||
features/powerpc/KVM-Allow-KVM_CHECK_EXTENSION-on-the-vm-fd.patch
|
||||
features/powerpc/KVM-Don-t-keep-reference-to-irq-routing-table-in-irq.patch
|
||||
features/powerpc/KVM-irqchip-Provide-and-use-accessors-for-irq-routin.patch
|
||||
features/powerpc/KVM-Move-all-accesses-to-kvm-irq_routing-into-irqchi.patch
|
||||
features/powerpc/KVM-Move-irq-notifier-implementation-into-eventfd.c.patch
|
||||
features/powerpc/KVM-Give-IRQFD-its-own-separate-enabling-Kconfig-opt.patch
|
||||
features/powerpc/KVM-PPC-Enable-IRQFD-support-for-the-XICS-interrupt-.patch
|
||||
features/powerpc/deb-pkg-add-support-for-powerpc-little-endian.patch
|
||||
features/x86/x86-memtest-WARN-if-bad-RAM-found.patch
|
||||
features/x86/x86-make-x32-syscall-support-conditional.patch
|
||||
features/arm/deb-pkg-add-automatic-support-for-armhf-architecture.patch
|
||||
features/arm64/drivers-net-Add-APM-X-Gene-SoC-ethernet-driver-suppo.patch
|
||||
features/arm64/drivers-net-NET_XGENE-should-depend-on-HAS_DMA.patch
|
||||
features/arm64/net-xgene-Check-negative-return-value-of-xgene_enet_.patch
|
||||
features/arm64/net-xgene-fix-possible-NULL-dereference-in-xgene_ene.patch
|
||||
features/arm64/dts-Add-bindings-for-APM-X-Gene-SoC-ethernet-driver.patch
|
||||
|
||||
# Miscellaneous bug fixes
|
||||
bugfix/all/misc-bmp085-Enable-building-as-a-module.patch
|
||||
bugfix/all/kbuild-use-nostdinc-in-compile-tests.patch
|
||||
bugfix/all/disable-some-marvell-phys.patch
|
||||
bugfix/all/aio-fix-reqs_available-handling.patch
|
||||
bugfix/all/mnt-Only-change-user-settable-mount-flags-in-remount.patch
|
||||
bugfix/all/mnt-Move-the-test-for-MNT_LOCK_READONLY-from-change_.patch
|
||||
bugfix/all/mnt-Correct-permission-checks-in-do_remount.patch
|
||||
bugfix/all/mnt-Change-the-default-remount-atime-from-relatime-t.patch
|
||||
bugfix/all/mnt-Add-tests-for-unprivileged-remount-cases-that-ha.patch
|
||||
debian/i2o-disable-i2o_ext_adaptec-on-64bit.patch
|
||||
bugfix/all/aic94xx-remove-broken-fallback-for-missing-ctrl-a.patch
|
||||
bugfix/all/builddeb-put-the-dbg-files-into-the-correct-director.patch
|
||||
bugfix/all/libceph-set-last_piece-in-ceph_msg_data_pages_cursor.patch
|
||||
bugfix/all/libceph-gracefully-handle-large-reply-messages-from-.patch
|
||||
bugfix/all/libceph-add-process_one_ticket-helper.patch
|
||||
bugfix/all/libceph-do-not-hard-code-max-auth-ticket-len.patch
|
||||
|
||||
# Miscellaneous features
|
||||
features/all/efi-autoload-efivars.patch
|
||||
features/all/virtio-scsi-Implement-change_queue_depth-for-virtscs.patch
|
||||
debian/revert-staging-sm7xxfb-remove-driver.patch
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
+ debian/dfsg/drivers-media-dvb-dvb-usb-af9005-disable.patch
|
||||
+ debian/dfsg/vs6624-disable.patch
|
||||
+ debian/dfsg/drivers-net-appletalk-cops.patch
|
||||
+ debian/dfsg/drivers-staging-wlags49_h2-disable.patch
|
||||
+ debian/dfsg/drivers-staging-wlags49_h25-disable.patch
|
||||
+ debian/dfsg/video-remove-nvidiafb-and-rivafb.patch
|
||||
+ debian/dfsg/firmware-cleanup.patch
|
||||
X debian/dfsg/files-1
|
||||
|
|
Loading…
Reference in New Issue