* Re: [PATCHv2] powerpc/crypto: Add property for 'era' in SEC dts crypto node
From: Kumar Gala @ 2013-04-11 13:34 UTC (permalink / raw)
To: Vakul Garg
Cc: Shaveta Leekha, linux-kernel, Andy Fleming, Paul Mackerras,
linuxppc-dev
In-Reply-To: <1365651923-24017-1-git-send-email-vakul@freescale.com>
On Apr 10, 2013, at 10:45 PM, Vakul Garg wrote:
> The crypto node now contains a new property 'fsl,sec-era'.
> This is required so that applications can retrieve era info without
> having to be able to read SEC's register space.
>
> Signed-off-by: Vakul Garg <vakul@freescale.com>
> ---
> Changelog:
>
> v2: Added era in p1023si-post.dtsi as per Kim's comments.
>
> arch/powerpc/boot/dts/fsl/p1023si-post.dtsi | 1 +
> arch/powerpc/boot/dts/fsl/pq3-sec4.4-0.dtsi | 1 +
> arch/powerpc/boot/dts/fsl/qoriq-sec4.0-0.dtsi | 1 +
> arch/powerpc/boot/dts/fsl/qoriq-sec4.2-0.dtsi | 1 +
> arch/powerpc/boot/dts/fsl/qoriq-sec5.0-0.dtsi | 1 +
> arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi | 1 +
> arch/powerpc/boot/dts/fsl/qoriq-sec5.3-0.dtsi | 1 +
> 7 files changed, 7 insertions(+), 0 deletions(-)
applied to next
- k
^ permalink raw reply
* Re: [PATCH] powerpc/crypto: removed qoriq-sec4.1-0.dtsi.
From: Kumar Gala @ 2013-04-11 13:33 UTC (permalink / raw)
To: Vakul Garg
Cc: Shaveta Leekha, linux-kernel, Andy Fleming, Paul Mackerras,
linuxppc-dev
In-Reply-To: <1365651819-23350-1-git-send-email-vakul@freescale.com>
On Apr 10, 2013, at 10:43 PM, Vakul Garg wrote:
> Removing qoriq-sec4.1-0.dtsi as it is not used by any soc anymore.
>=20
> Signed-off-by: Vakul Garg <vakul@freescale.com>
> ---
> arch/powerpc/boot/dts/fsl/qoriq-sec4.1-0.dtsi | 109 =
-------------------------
> 1 files changed, 0 insertions(+), 109 deletions(-)
> delete mode 100644 arch/powerpc/boot/dts/fsl/qoriq-sec4.1-0.dtsi
applied to next
- k=
^ permalink raw reply
* [PATCH 10/26] fsl_udc: Don't use create_proc_read_entry() [RFC]
From: David Howells @ 2013-04-11 13:29 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, linux-usb, Felipe Balbi, viro, linuxppc-dev
In-Reply-To: <20130411132739.32763.82609.stgit@warthog.procyon.org.uk>
Don't use create_proc_read_entry() as that is deprecated, but rather use
proc_create_data() and seq_file instead.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Li Yang <leoli@freescale.com>
cc: Felipe Balbi <balbi@ti.com>
cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
cc: linux-usb@vger.kernel.org
cc: linuxppc-dev@lists.ozlabs.org
---
drivers/usb/gadget/fsl_udc_core.c | 124 +++++++++++++------------------------
1 file changed, 43 insertions(+), 81 deletions(-)
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 04d5fef..ede70ff 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -2038,47 +2038,37 @@ static int fsl_udc_stop(struct usb_gadget *g,
static const char proc_filename[] = "driver/fsl_usb2_udc";
-static int fsl_proc_read(char *page, char **start, off_t off, int count,
- int *eof, void *_dev)
+static int fsl_proc_read(struct seq_file *m, void *v)
{
- char *buf = page;
- char *next = buf;
- unsigned size = count;
unsigned long flags;
- int t, i;
+ int i;
u32 tmp_reg;
struct fsl_ep *ep = NULL;
struct fsl_req *req;
struct fsl_udc *udc = udc_controller;
- if (off != 0)
- return 0;
spin_lock_irqsave(&udc->lock, flags);
/* ------basic driver information ---- */
- t = scnprintf(next, size,
+ seq_printf(m,
DRIVER_DESC "\n"
"%s version: %s\n"
"Gadget driver: %s\n\n",
driver_name, DRIVER_VERSION,
udc->driver ? udc->driver->driver.name : "(none)");
- size -= t;
- next += t;
/* ------ DR Registers ----- */
tmp_reg = fsl_readl(&dr_regs->usbcmd);
- t = scnprintf(next, size,
+ seq_printf(m,
"USBCMD reg:\n"
"SetupTW: %d\n"
"Run/Stop: %s\n\n",
(tmp_reg & USB_CMD_SUTW) ? 1 : 0,
(tmp_reg & USB_CMD_RUN_STOP) ? "Run" : "Stop");
- size -= t;
- next += t;
tmp_reg = fsl_readl(&dr_regs->usbsts);
- t = scnprintf(next, size,
+ seq_printf(m,
"USB Status Reg:\n"
"Dr Suspend: %d Reset Received: %d System Error: %s "
"USB Error Interrupt: %s\n\n",
@@ -2086,11 +2076,9 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
(tmp_reg & USB_STS_RESET) ? 1 : 0,
(tmp_reg & USB_STS_SYS_ERR) ? "Err" : "Normal",
(tmp_reg & USB_STS_ERR) ? "Err detected" : "No err");
- size -= t;
- next += t;
tmp_reg = fsl_readl(&dr_regs->usbintr);
- t = scnprintf(next, size,
+ seq_printf(m,
"USB Interrupt Enable Reg:\n"
"Sleep Enable: %d SOF Received Enable: %d "
"Reset Enable: %d\n"
@@ -2104,33 +2092,25 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
(tmp_reg & USB_INTR_PTC_DETECT_EN) ? 1 : 0,
(tmp_reg & USB_INTR_ERR_INT_EN) ? 1 : 0,
(tmp_reg & USB_INTR_INT_EN) ? 1 : 0);
- size -= t;
- next += t;
tmp_reg = fsl_readl(&dr_regs->frindex);
- t = scnprintf(next, size,
+ seq_printf(m,
"USB Frame Index Reg: Frame Number is 0x%x\n\n",
(tmp_reg & USB_FRINDEX_MASKS));
- size -= t;
- next += t;
tmp_reg = fsl_readl(&dr_regs->deviceaddr);
- t = scnprintf(next, size,
+ seq_printf(m,
"USB Device Address Reg: Device Addr is 0x%x\n\n",
(tmp_reg & USB_DEVICE_ADDRESS_MASK));
- size -= t;
- next += t;
tmp_reg = fsl_readl(&dr_regs->endpointlistaddr);
- t = scnprintf(next, size,
+ seq_printf(m,
"USB Endpoint List Address Reg: "
"Device Addr is 0x%x\n\n",
(tmp_reg & USB_EP_LIST_ADDRESS_MASK));
- size -= t;
- next += t;
tmp_reg = fsl_readl(&dr_regs->portsc1);
- t = scnprintf(next, size,
+ seq_printf(m,
"USB Port Status&Control Reg:\n"
"Port Transceiver Type : %s Port Speed: %s\n"
"PHY Low Power Suspend: %s Port Reset: %s "
@@ -2139,7 +2119,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
"Port Enable/Disable Change: %s\n"
"Port Enabled/Disabled: %s "
"Current Connect Status: %s\n\n", ( {
- char *s;
+ const char *s;
switch (tmp_reg & PORTSCX_PTS_FSLS) {
case PORTSCX_PTS_UTMI:
s = "UTMI"; break;
@@ -2165,13 +2145,11 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
"Not correct",
(tmp_reg & PORTSCX_CURRENT_CONNECT_STATUS) ?
"Attached" : "Not-Att");
- size -= t;
- next += t;
tmp_reg = fsl_readl(&dr_regs->usbmode);
- t = scnprintf(next, size,
+ seq_printf(m,
"USB Mode Reg: Controller Mode is: %s\n\n", ( {
- char *s;
+ const char *s;
switch (tmp_reg & USB_MODE_CTRL_MODE_HOST) {
case USB_MODE_CTRL_MODE_IDLE:
s = "Idle"; break;
@@ -2184,103 +2162,87 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
}
s;
} ));
- size -= t;
- next += t;
tmp_reg = fsl_readl(&dr_regs->endptsetupstat);
- t = scnprintf(next, size,
+ seq_printf(m,
"Endpoint Setup Status Reg: SETUP on ep 0x%x\n\n",
(tmp_reg & EP_SETUP_STATUS_MASK));
- size -= t;
- next += t;
for (i = 0; i < udc->max_ep / 2; i++) {
tmp_reg = fsl_readl(&dr_regs->endptctrl[i]);
- t = scnprintf(next, size, "EP Ctrl Reg [0x%x]: = [0x%x]\n",
- i, tmp_reg);
- size -= t;
- next += t;
+ seq_printf(m, "EP Ctrl Reg [0x%x]: = [0x%x]\n", i, tmp_reg);
}
tmp_reg = fsl_readl(&dr_regs->endpointprime);
- t = scnprintf(next, size, "EP Prime Reg = [0x%x]\n\n", tmp_reg);
- size -= t;
- next += t;
+ seq_printf(m, "EP Prime Reg = [0x%x]\n\n", tmp_reg);
#ifndef CONFIG_ARCH_MXC
if (udc->pdata->have_sysif_regs) {
tmp_reg = usb_sys_regs->snoop1;
- t = scnprintf(next, size, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
- size -= t;
- next += t;
+ seq_printf(m, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
tmp_reg = usb_sys_regs->control;
- t = scnprintf(next, size, "General Control Reg : = [0x%x]\n\n",
- tmp_reg);
- size -= t;
- next += t;
+ seq_printf(m, "General Control Reg : = [0x%x]\n\n", tmp_reg);
}
#endif
/* ------fsl_udc, fsl_ep, fsl_request structure information ----- */
ep = &udc->eps[0];
- t = scnprintf(next, size, "For %s Maxpkt is 0x%x index is 0x%x\n",
+ seq_printf(m, "For %s Maxpkt is 0x%x index is 0x%x\n",
ep->ep.name, ep_maxpacket(ep), ep_index(ep));
- size -= t;
- next += t;
if (list_empty(&ep->queue)) {
- t = scnprintf(next, size, "its req queue is empty\n\n");
- size -= t;
- next += t;
+ seq_puts(m, "its req queue is empty\n\n");
} else {
list_for_each_entry(req, &ep->queue, queue) {
- t = scnprintf(next, size,
+ seq_printf(m,
"req %p actual 0x%x length 0x%x buf %p\n",
&req->req, req->req.actual,
req->req.length, req->req.buf);
- size -= t;
- next += t;
}
}
/* other gadget->eplist ep */
list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
if (ep->ep.desc) {
- t = scnprintf(next, size,
+ seq_printf(m,
"\nFor %s Maxpkt is 0x%x "
"index is 0x%x\n",
ep->ep.name, ep_maxpacket(ep),
ep_index(ep));
- size -= t;
- next += t;
if (list_empty(&ep->queue)) {
- t = scnprintf(next, size,
- "its req queue is empty\n\n");
- size -= t;
- next += t;
+ seq_puts(m, "its req queue is empty\n\n");
} else {
list_for_each_entry(req, &ep->queue, queue) {
- t = scnprintf(next, size,
+ seq_printf(m,
"req %p actual 0x%x length "
"0x%x buf %p\n",
&req->req, req->req.actual,
req->req.length, req->req.buf);
- size -= t;
- next += t;
- } /* end for each_entry of ep req */
- } /* end for else */
- } /* end for if(ep->queue) */
- } /* end (ep->desc) */
+ } /* end for each_entry of ep req */
+ } /* end for else */
+ } /* end for if(ep->queue) */
+ } /* end (ep->desc) */
spin_unlock_irqrestore(&udc->lock, flags);
+ return 0;
+}
- *eof = 1;
- return count - size;
+/*
+ * seq_file wrappers for procfile show routines.
+ */
+static int fsl_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, fsl_proc_read, NULL);
}
-#define create_proc_file() create_proc_read_entry(proc_filename, \
- 0, NULL, fsl_proc_read, NULL)
+static const struct file_operations fsl_proc_fops = {
+ .open = fsl_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+#define create_proc_file() proc_create(proc_filename, 0, NULL, &fsl_proc_fops)
#define remove_proc_file() remove_proc_entry(proc_filename, NULL)
#else /* !CONFIG_USB_GADGET_DEBUG_FILES */
^ permalink raw reply related
* Re: [PATCH 0/2] enable the coreint for the mpc85xx 64bit boards
From: Kumar Gala @ 2013-04-11 13:21 UTC (permalink / raw)
To: Wood Scott-B07421; +Cc: Kevin Hao, linuxppc
In-Reply-To: <1365643954-20798-1-git-send-email-haokexin@gmail.com>
On Apr 10, 2013, at 8:32 PM, Kevin Hao wrote:
> Hi,
>
> With the rework of the lazy EE, it seems that 64bit kernel works pretty
> well on mpc85xx 64bit boards with lazy EE enabled. So this patch series
> tries to enable the coreint for these boards by default. This passed
> the ltp test on a t4240qds board and is based on Kumar's next branch.
>
> ---
> Kevin Hao (2):
> powerpc/irq: remove the unneeded flag PACA_IRQ_EE_EDGE
> powerpc/85xx: enable coreint for all the 64bit boards
>
> arch/powerpc/include/asm/hw_irq.h | 1 -
> arch/powerpc/kernel/exceptions-64e.S | 1 -
> arch/powerpc/kernel/irq.c | 8 --------
> arch/powerpc/platforms/85xx/p5020_ds.c | 5 -----
> arch/powerpc/platforms/85xx/p5040_ds.c | 5 -----
> arch/powerpc/platforms/85xx/t4240_qds.c | 5 -----
> 6 files changed, 25 deletions(-)
Scott,
I'd appreciate your review and ack on this change.
thanks
- k
^ permalink raw reply
* Re: [PATCH] net: mv643xx_eth: Add GRO support
From: Willy Tarreau @ 2013-04-11 13:13 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: Andrew Lunn, Jason Cooper, linux-kernel, Florian Fainelli,
Soeren Moch, Paul Mackerras, Lennert Buytenhek, Dale Farnsworth,
netdev, linuxppc-dev, David S. Miller, linux-arm-kernel
In-Reply-To: <1365684023-9967-1-git-send-email-sebastian.hesselbarth@gmail.com>
Hi,
On Thu, Apr 11, 2013 at 02:40:23PM +0200, Sebastian Hesselbarth wrote:
> This patch adds GRO support to mv643xx_eth by making it invoke
> napi_gro_receive instead of netif_receive_skb.
>
> Signed-off-by: Soeren Moch <smoch@web.de>
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> ---
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Lennert Buytenhek <buytenh@wantstofly.org>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Florian Fainelli <florian@openwrt.org>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Dale Farnsworth <dale@farnsworth.org>
> Cc: netdev@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-kernel@vger.kernel.org
> ---
> drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
> index 305038f..c850d04 100644
> --- a/drivers/net/ethernet/marvell/mv643xx_eth.c
> +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
> @@ -604,7 +604,7 @@ static int rxq_process(struct rx_queue *rxq, int budget)
> lro_receive_skb(&rxq->lro_mgr, skb, (void *)cmd_sts);
> lro_flush_needed = 1;
> } else
> - netif_receive_skb(skb);
> + napi_gro_receive(&mp->napi, skb);
>
> continue;
I remember having experimented with this on 3.6 a few months ago with this
driver and finally switching back to something like this instead which
showed better performance on my tests :
if (skb->ip_summed == CHECKSUM_UNNECESSARY)
napi_gro_receive(napi, skb);
else
netif_receive_skb(skb);
Unfortunately I don't have more details as my commit message was rather
short due to this resulting from experimentation. Did you verify that
you did not lose any performance in various workloads ? I was playing
with bridges at this time, it's possible that I got better performance
on bridging with netif_receive_skb() than with napi_gro_receive().
Regards,
Willy
^ permalink raw reply
* [PATCHv3 0/2] Speed Cap fixes for ppc64
From: Lucas Kannebley Tavares @ 2013-04-11 13:13 UTC (permalink / raw)
To: linuxppc-dev, dri-devel, Benjamin Herrenschmidt, Bjorn Helgaas,
David Airlie
Cc: Kleber Sacilotto de Souza, Alex Deucher, Jerome Glisse,
Thadeu Lima de Souza Cascardo, Lucas Kannebley Tavares,
Brian King
After all the comments in the last patch series, I did a refactoring of what I was proposing and came up with this. Basically, now:
1. max_bus_speed is used to set the device to gen2 speeds
2. on power there's no longer a conflict between the pseries call and other architectures, because the overwrite is done via a ppc_md hook
3. radeon is using bus->max_bus_speed instead of drm_pcie_get_speed_cap_mask for gen2 capability detection
The first patch consists of some architecture changes, such as adding a hook on powerpc for pci_root_bridge_prepare, so that pseries will initialize it to a function, while all other architectures get a NULL pointer. So that whenever whenever pci_create_root_bus is called, we'll get max_bus_speed properly setup from OpenFirmware.
The second patch consists of simple radeon changes not to call drm_get_pcie_speed_cap_mask anymore. I assume that on x86 machines, the max_bus_speed property will be properly set already.
Lucas Kannebley Tavares (2):
ppc64: perform proper max_bus_speed detection
radeon: use max_bus_speed to activate gen2 speeds
arch/powerpc/include/asm/machdep.h | 2 +
arch/powerpc/kernel/pci-common.c | 8 +++++
arch/powerpc/platforms/pseries/pci.c | 51 ++++++++++++++++++++++++++++++++
arch/powerpc/platforms/pseries/setup.c | 4 ++
drivers/gpu/drm/radeon/evergreen.c | 9 +----
drivers/gpu/drm/radeon/r600.c | 8 +----
drivers/gpu/drm/radeon/rv770.c | 8 +----
7 files changed, 69 insertions(+), 21 deletions(-)
--
1.7.4.4
^ permalink raw reply
* [PATCHv3 1/2] ppc64: perform proper max_bus_speed detection
From: Lucas Kannebley Tavares @ 2013-04-11 13:13 UTC (permalink / raw)
To: linuxppc-dev, dri-devel, Benjamin Herrenschmidt, Bjorn Helgaas,
David Airlie
Cc: Kleber Sacilotto de Souza, Alex Deucher, Jerome Glisse,
Thadeu Lima de Souza Cascardo, Lucas Kannebley Tavares,
Brian King
In-Reply-To: <1365685994-32603-1-git-send-email-lucaskt@linux.vnet.ibm.com>
On pseries machines the detection for max_bus_speed should be done
through an OpenFirmware property. This patch adds a function to perform this
detection and a hook to perform dynamic adding of the function only for
pseries.
Signed-off-by: Lucas Kannebley Tavares <lucaskt@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/machdep.h | 2 +
arch/powerpc/kernel/pci-common.c | 8 +++++
arch/powerpc/platforms/pseries/pci.c | 51 ++++++++++++++++++++++++++++++++
arch/powerpc/platforms/pseries/setup.c | 4 ++
4 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 3d6b410..8f558bf 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -107,6 +107,8 @@ struct machdep_calls {
void (*pcibios_fixup)(void);
int (*pci_probe_mode)(struct pci_bus *);
void (*pci_irq_fixup)(struct pci_dev *dev);
+ int (*pcibios_root_bridge_prepare)(struct pci_host_bridge
+ *bridge);
/* To setup PHBs when using automatic OF platform driver for PCI */
int (*pci_setup_phb)(struct pci_controller *host);
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index fa12ae4..80986cf 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -844,6 +844,14 @@ int pci_proc_domain(struct pci_bus *bus)
return 1;
}
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+ if (ppc_md.pcibios_root_bridge_prepare)
+ return ppc_md.pcibios_root_bridge_prepare(bridge);
+
+ return 0;
+}
+
/* This header fixup will do the resource fixup for all devices as they are
* probed, but not for bridge ranges
*/
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index 0b580f4..7f9c956 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -108,3 +108,54 @@ static void fixup_winbond_82c105(struct pci_dev* dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
fixup_winbond_82c105);
+
+int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+ struct device_node *dn, *pdn;
+ struct pci_bus *bus;
+ const uint32_t *pcie_link_speed_stats;
+
+ bus = bridge->bus;
+
+ dn = pcibios_get_phb_of_node(bus);
+ if (!dn)
+ return 0;
+
+ for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
+ pcie_link_speed_stats = (const uint32_t *) of_get_property(dn,
+ "ibm,pcie-link-speed-stats", NULL);
+ if (pcie_link_speed_stats)
+ break;
+ }
+
+ if (!pcie_link_speed_stats) {
+ pr_err("no ibm,pcie-link-speed-stats property\n");
+ return 0;
+ }
+
+ switch (pcie_link_speed_stats[0]) {
+ case 0x01:
+ bus->max_bus_speed = PCIE_SPEED_2_5GT;
+ break;
+ case 0x02:
+ bus->max_bus_speed = PCIE_SPEED_5_0GT;
+ break;
+ default:
+ bus->max_bus_speed = PCI_SPEED_UNKNOWN;
+ break;
+ }
+
+ switch (pcie_link_speed_stats[1]) {
+ case 0x01:
+ bus->cur_bus_speed = PCIE_SPEED_2_5GT;
+ break;
+ case 0x02:
+ bus->cur_bus_speed = PCIE_SPEED_5_0GT;
+ break;
+ default:
+ bus->cur_bus_speed = PCI_SPEED_UNKNOWN;
+ break;
+ }
+
+ return 0;
+}
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 8bcc9ca..15796b5 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -430,6 +430,8 @@ static void pSeries_machine_kexec(struct kimage *image)
}
#endif
+int pseries_root_bridge_prepare(struct pci_host_bridge *bridge);
+
static void __init pSeries_setup_arch(void)
{
panic_timeout = 10;
@@ -466,6 +468,8 @@ static void __init pSeries_setup_arch(void)
else
ppc_md.enable_pmcs = power4_enable_pmcs;
+ ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare;
+
if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
long rc;
if ((rc = pSeries_enable_reloc_on_exc()) != H_SUCCESS) {
--
1.7.4.4
^ permalink raw reply related
* [PATCHv3 2/2] radeon: use max_bus_speed to activate gen2 speeds
From: Lucas Kannebley Tavares @ 2013-04-11 13:13 UTC (permalink / raw)
To: linuxppc-dev, dri-devel, Benjamin Herrenschmidt, Bjorn Helgaas,
David Airlie
Cc: Kleber Sacilotto de Souza, Alex Deucher, Jerome Glisse,
Thadeu Lima de Souza Cascardo, Lucas Kannebley Tavares,
Brian King
In-Reply-To: <1365685994-32603-1-git-send-email-lucaskt@linux.vnet.ibm.com>
radeon currently uses a drm function to get the speed capabilities for
the bus. However, this is a non-standard method of performing this
detection and this patch changes it to use the max_bus_speed attribute.
---
drivers/gpu/drm/radeon/evergreen.c | 9 ++-------
drivers/gpu/drm/radeon/r600.c | 8 +-------
drivers/gpu/drm/radeon/rv770.c | 8 +-------
3 files changed, 4 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 305a657..3291f62 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -3855,8 +3855,7 @@ void evergreen_fini(struct radeon_device *rdev)
void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
{
- u32 link_width_cntl, speed_cntl, mask;
- int ret;
+ u32 link_width_cntl, speed_cntl;
if (radeon_pcie_gen2 == 0)
return;
@@ -3871,11 +3870,7 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
if (ASIC_IS_X2(rdev))
return;
- ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask);
- if (ret != 0)
- return;
-
- if (!(mask & DRM_PCIE_SPEED_50))
+ if (rdev->pdev->bus->max_bus_speed < PCIE_SPEED_5_0GT)
return;
speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 0740db3..64b90c0 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -4351,8 +4351,6 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)
{
u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp;
u16 link_cntl2;
- u32 mask;
- int ret;
if (radeon_pcie_gen2 == 0)
return;
@@ -4371,11 +4369,7 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)
if (rdev->family <= CHIP_R600)
return;
- ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask);
- if (ret != 0)
- return;
-
- if (!(mask & DRM_PCIE_SPEED_50))
+ if (rdev->pdev->bus->max_bus_speed < PCIE_SPEED_5_0GT)
return;
speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index d63fe1d..c683c36 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -1238,8 +1238,6 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev)
{
u32 link_width_cntl, lanes, speed_cntl, tmp;
u16 link_cntl2;
- u32 mask;
- int ret;
if (radeon_pcie_gen2 == 0)
return;
@@ -1254,11 +1252,7 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev)
if (ASIC_IS_X2(rdev))
return;
- ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask);
- if (ret != 0)
- return;
-
- if (!(mask & DRM_PCIE_SPEED_50))
+ if (rdev->pdev->bus->max_bus_speed < PCIE_SPEED_5_0GT)
return;
DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
--
1.7.4.4
^ permalink raw reply related
* [PATCH] net: mv643xx_eth: Add GRO support
From: Sebastian Hesselbarth @ 2013-04-11 12:40 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: Andrew Lunn, Jason Cooper, linux-kernel, David S. Miller,
Soeren Moch, Paul Mackerras, linux-arm-kernel, Dale Farnsworth,
netdev, linuxppc-dev, Florian Fainelli, Lennert Buytenhek
This patch adds GRO support to mv643xx_eth by making it invoke
napi_gro_receive instead of netif_receive_skb.
Signed-off-by: Soeren Moch <smoch@web.de>
Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Lennert Buytenhek <buytenh@wantstofly.org>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Florian Fainelli <florian@openwrt.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Dale Farnsworth <dale@farnsworth.org>
Cc: netdev@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
---
drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 305038f..c850d04 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -604,7 +604,7 @@ static int rxq_process(struct rx_queue *rxq, int budget)
lro_receive_skb(&rxq->lro_mgr, skb, (void *)cmd_sts);
lro_flush_needed = 1;
} else
- netif_receive_skb(skb);
+ napi_gro_receive(&mp->napi, skb);
continue;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 7/8 v3] KVM: PPC: e500mc: Enable e6500 cores
From: Mihai Caraman @ 2013-04-11 10:03 UTC (permalink / raw)
To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1365674594-17410-1-git-send-email-mihai.caraman@freescale.com>
Extend processor compatibility names to e6500 cores.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
---
v3:
- No change
arch/powerpc/kvm/e500mc.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
index ab073a8..c3bdc0a 100644
--- a/arch/powerpc/kvm/e500mc.c
+++ b/arch/powerpc/kvm/e500mc.c
@@ -172,6 +172,8 @@ int kvmppc_core_check_processor_compat(void)
r = 0;
else if (strcmp(cur_cpu_spec->cpu_name, "e5500") == 0)
r = 0;
+ else if (strcmp(cur_cpu_spec->cpu_name, "e6500") == 0)
+ r = 0;
else
r = -ENOTSUPP;
--
1.7.4.1
^ permalink raw reply related
* [PATCH 8/8 v3] KVM: PPC: e500: Add e6500 core to Kconfig description
From: Mihai Caraman @ 2013-04-11 10:03 UTC (permalink / raw)
To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1365674594-17410-1-git-send-email-mihai.caraman@freescale.com>
Add e6500 core to Kconfig description.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
- No change
arch/powerpc/kvm/Kconfig | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index 63c67ec..4489520 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -136,15 +136,15 @@ config KVM_E500V2
If unsure, say N.
config KVM_E500MC
- bool "KVM support for PowerPC E500MC/E5500 processors"
+ bool "KVM support for PowerPC E500MC/E5500/E6500 processors"
depends on PPC_E500MC
select KVM
select KVM_MMIO
select KVM_BOOKE_HV
select MMU_NOTIFIER
---help---
- Support running unmodified E500MC/E5500 (32-bit) guest kernels in
- virtual machines on E500MC/E5500 host processors.
+ Support running unmodified E500MC/E5500/E6500 guest kernels in
+ virtual machines on E500MC/E5500/E6500 host processors.
This module provides access to the hardware capabilities through
a character device node named /dev/kvm.
--
1.7.4.1
^ permalink raw reply related
* [PATCH 6/8 v3] KVM: PPC: e500: Remove E.PT and E.HV.LRAT categories from VCPUs
From: Mihai Caraman @ 2013-04-11 10:03 UTC (permalink / raw)
To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1365674594-17410-1-git-send-email-mihai.caraman@freescale.com>
Embedded.Page Table (E.PT) category is not supported yet in e6500 kernel.
Configure TLBnCFG to remove E.PT and E.HV.LRAT categories from VCPUs.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
- No change
arch/powerpc/kvm/e500_mmu.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kvm/e500_mmu.c b/arch/powerpc/kvm/e500_mmu.c
index 1c1c5cb..c41a5a9 100644
--- a/arch/powerpc/kvm/e500_mmu.c
+++ b/arch/powerpc/kvm/e500_mmu.c
@@ -885,8 +885,12 @@ static int vcpu_mmu_init(struct kvm_vcpu *vcpu,
vcpu->arch.tlbps[0] = mfspr(SPRN_TLB0PS);
vcpu->arch.tlbps[1] = mfspr(SPRN_TLB1PS);
+ vcpu->arch.mmucfg &= ~MMUCFG_LRAT;
+
/* Guest mmu emulation currently doesn't handle E.PT */
vcpu->arch.eptcfg = 0;
+ vcpu->arch.tlbcfg[0] &= ~TLBnCFG_PT;
+ vcpu->arch.tlbcfg[1] &= ~TLBnCFG_IND;
}
return 0;
--
1.7.4.1
^ permalink raw reply related
* [PATCH 5/8] KVM: PPC: e500: Add support for EPTCFG register
From: Mihai Caraman @ 2013-04-11 10:03 UTC (permalink / raw)
To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1365674594-17410-1-git-send-email-mihai.caraman@freescale.com>
EPTCFG register defined by E.PT is accessed unconditionally by Linux guests
in the presence of MAV 2.0. Emulate it now.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
- Initialize EPTCFG to 0 since E.PT is not supported now
Documentation/virtual/kvm/api.txt | 1 +
arch/powerpc/include/asm/kvm_host.h | 1 +
arch/powerpc/include/uapi/asm/kvm.h | 1 +
arch/powerpc/kvm/e500_emulate.c | 9 +++++++++
arch/powerpc/kvm/e500_mmu.c | 12 ++++++++++++
5 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index f045377..a1f2200 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1807,6 +1807,7 @@ registers, find a list below:
PPC | KVM_REG_PPC_TLB1PS | 32
PPC | KVM_REG_PPC_TLB2PS | 32
PPC | KVM_REG_PPC_TLB3PS | 32
+ PPC | KVM_REG_PPC_EPTCFG | 32
ARM registers are mapped using the lower 32 bits. The upper 16 of that
is the register group type, or coprocessor number:
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 3b6cee3..8a48e68 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -504,6 +504,7 @@ struct kvm_vcpu_arch {
u32 tlbcfg[4];
u32 tlbps[4];
u32 mmucfg;
+ u32 eptcfg;
u32 epr;
u32 crit_save;
struct kvmppc_booke_debug_reg dbg_reg;
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index 91341d9..7f4d191 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -446,5 +446,6 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_TLB1PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x98)
#define KVM_REG_PPC_TLB2PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x99)
#define KVM_REG_PPC_TLB3PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a)
+#define KVM_REG_PPC_EPTCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9b)
#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index 12b8de2..b10a012 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -317,6 +317,15 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
case SPRN_MMUCFG:
*spr_val = vcpu->arch.mmucfg;
break;
+ case SPRN_EPTCFG:
+ if (!has_feature(vcpu, VCPU_FTR_MMU_V2))
+ return EMULATE_FAIL;
+ /*
+ * Legacy Linux guests access EPTCFG register even if the E.PT
+ * category is disabled in the VM. Give them a chance to live.
+ */
+ *spr_val = vcpu->arch.eptcfg;
+ break;
/* extra exceptions */
case SPRN_IVOR32:
diff --git a/arch/powerpc/kvm/e500_mmu.c b/arch/powerpc/kvm/e500_mmu.c
index a863dc1..1c1c5cb 100644
--- a/arch/powerpc/kvm/e500_mmu.c
+++ b/arch/powerpc/kvm/e500_mmu.c
@@ -624,6 +624,9 @@ int kvmppc_get_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_MMUCFG:
*val = get_reg_val(id, vcpu->arch.mmucfg);
break;
+ case KVM_REG_PPC_EPTCFG:
+ *val = get_reg_val(id, vcpu->arch.eptcfg);
+ break;
case KVM_REG_PPC_TLB0CFG:
case KVM_REG_PPC_TLB1CFG:
case KVM_REG_PPC_TLB2CFG:
@@ -678,6 +681,12 @@ int kvmppc_set_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
r = -EINVAL;
break;
}
+ case KVM_REG_PPC_EPTCFG: {
+ u32 reg = set_reg_val(id, *val);
+ if (reg != vcpu->arch.eptcfg)
+ r = -EINVAL;
+ break;
+ }
case KVM_REG_PPC_TLB0CFG:
case KVM_REG_PPC_TLB1CFG:
case KVM_REG_PPC_TLB2CFG:
@@ -875,6 +884,9 @@ static int vcpu_mmu_init(struct kvm_vcpu *vcpu,
if (has_feature(vcpu, VCPU_FTR_MMU_V2)) {
vcpu->arch.tlbps[0] = mfspr(SPRN_TLB0PS);
vcpu->arch.tlbps[1] = mfspr(SPRN_TLB1PS);
+
+ /* Guest mmu emulation currently doesn't handle E.PT */
+ vcpu->arch.eptcfg = 0;
}
return 0;
--
1.7.4.1
^ permalink raw reply related
* [PATCH 1/8 v3] KVM: PPC: Book3E: Refactor ONE_REG ioctl implementation
From: Mihai Caraman @ 2013-04-11 10:03 UTC (permalink / raw)
To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1365674594-17410-1-git-send-email-mihai.caraman@freescale.com>
Refactor Book3E ONE_REG ioctl implementation to use kvmppc_get_one_reg/
kvmppc_set_one_reg delegation interface introduced by Book3S. This is
necessary for MMU SPRs which are platform specifics.
Get rid of useless case braces in the process.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
- Split ONE_REG ioctl refactoring in its own patch
arch/powerpc/kvm/44x.c | 12 +++++
arch/powerpc/kvm/booke.c | 102 ++++++++++++++++++++++++---------------------
arch/powerpc/kvm/e500.c | 12 +++++
arch/powerpc/kvm/e500mc.c | 12 +++++
4 files changed, 91 insertions(+), 47 deletions(-)
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c
index 3d7fd21..2f5c6b6 100644
--- a/arch/powerpc/kvm/44x.c
+++ b/arch/powerpc/kvm/44x.c
@@ -124,6 +124,18 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
return kvmppc_set_sregs_ivor(vcpu, sregs);
}
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
+{
+ return -EINVAL;
+}
+
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
+{
+ return -EINVAL;
+}
+
struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
{
struct kvmppc_vcpu_44x *vcpu_44x;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index a49a68a..08f6540 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -1412,117 +1412,125 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
{
- int r = -EINVAL;
+ int r = 0;
+ union kvmppc_one_reg val;
+ int size;
+ long int i;
+
+ size = one_reg_size(reg->id);
+ if (size > sizeof(val))
+ return -EINVAL;
switch (reg->id) {
case KVM_REG_PPC_IAC1:
case KVM_REG_PPC_IAC2:
case KVM_REG_PPC_IAC3:
- case KVM_REG_PPC_IAC4: {
- int iac = reg->id - KVM_REG_PPC_IAC1;
- r = copy_to_user((u64 __user *)(long)reg->addr,
- &vcpu->arch.dbg_reg.iac[iac], sizeof(u64));
+ case KVM_REG_PPC_IAC4:
+ i = reg->id - KVM_REG_PPC_IAC1;
+ val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac[i]);
break;
- }
case KVM_REG_PPC_DAC1:
- case KVM_REG_PPC_DAC2: {
- int dac = reg->id - KVM_REG_PPC_DAC1;
- r = copy_to_user((u64 __user *)(long)reg->addr,
- &vcpu->arch.dbg_reg.dac[dac], sizeof(u64));
+ case KVM_REG_PPC_DAC2:
+ i = reg->id - KVM_REG_PPC_DAC1;
+ val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac[i]);
break;
- }
case KVM_REG_PPC_EPR: {
u32 epr = get_guest_epr(vcpu);
- r = put_user(epr, (u32 __user *)(long)reg->addr);
+ val = get_reg_val(reg->id, epr);
break;
}
#if defined(CONFIG_64BIT)
case KVM_REG_PPC_EPCR:
- r = put_user(vcpu->arch.epcr, (u32 __user *)(long)reg->addr);
+ val = get_reg_val(reg->id, vcpu->arch.epcr);
break;
#endif
case KVM_REG_PPC_TCR:
- r = put_user(vcpu->arch.tcr, (u32 __user *)(long)reg->addr);
+ val = get_reg_val(reg->id, vcpu->arch.tcr);
break;
case KVM_REG_PPC_TSR:
- r = put_user(vcpu->arch.tsr, (u32 __user *)(long)reg->addr);
+ val = get_reg_val(reg->id, vcpu->arch.tsr);
break;
- case KVM_REG_PPC_DEBUG_INST: {
- u32 opcode = KVMPPC_INST_EHPRIV;
- r = copy_to_user((u32 __user *)(long)reg->addr,
- &opcode, sizeof(u32));
+ case KVM_REG_PPC_DEBUG_INST:
+ val = get_reg_val(reg->id, KVMPPC_INST_EHPRIV);
break;
- }
default:
+ r = kvmppc_get_one_reg(vcpu, reg->id, &val);
break;
}
+
+ if (r)
+ return r;
+
+ if (copy_to_user((char __user *)(unsigned long)reg->addr, &val, size))
+ r = -EFAULT;
+
return r;
}
int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
{
- int r = -EINVAL;
+ int r = 0;
+ union kvmppc_one_reg val;
+ int size;
+ long int i;
+
+ size = one_reg_size(reg->id);
+ if (size > sizeof(val))
+ return -EINVAL;
+
+ if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size))
+ return -EFAULT;
switch (reg->id) {
case KVM_REG_PPC_IAC1:
case KVM_REG_PPC_IAC2:
case KVM_REG_PPC_IAC3:
- case KVM_REG_PPC_IAC4: {
- int iac = reg->id - KVM_REG_PPC_IAC1;
- r = copy_from_user(&vcpu->arch.dbg_reg.iac[iac],
- (u64 __user *)(long)reg->addr, sizeof(u64));
+ case KVM_REG_PPC_IAC4:
+ i = reg->id - KVM_REG_PPC_IAC1;
+ vcpu->arch.dbg_reg.iac[i] = set_reg_val(reg->id, val);
break;
- }
case KVM_REG_PPC_DAC1:
- case KVM_REG_PPC_DAC2: {
- int dac = reg->id - KVM_REG_PPC_DAC1;
- r = copy_from_user(&vcpu->arch.dbg_reg.dac[dac],
- (u64 __user *)(long)reg->addr, sizeof(u64));
+ case KVM_REG_PPC_DAC2:
+ i = reg->id - KVM_REG_PPC_DAC1;
+ vcpu->arch.dbg_reg.dac[i] = set_reg_val(reg->id, val);
break;
- }
case KVM_REG_PPC_EPR: {
- u32 new_epr;
- r = get_user(new_epr, (u32 __user *)(long)reg->addr);
- if (!r)
- kvmppc_set_epr(vcpu, new_epr);
+ u32 new_epr = set_reg_val(reg->id, val);
+ kvmppc_set_epr(vcpu, new_epr);
break;
}
#if defined(CONFIG_64BIT)
case KVM_REG_PPC_EPCR: {
- u32 new_epcr;
- r = get_user(new_epcr, (u32 __user *)(long)reg->addr);
- if (r == 0)
- kvmppc_set_epcr(vcpu, new_epcr);
+ u32 new_epcr = set_reg_val(reg->id, val);
+ kvmppc_set_epcr(vcpu, new_epcr);
break;
}
#endif
case KVM_REG_PPC_OR_TSR: {
- u32 tsr_bits;
- r = get_user(tsr_bits, (u32 __user *)(long)reg->addr);
+ u32 tsr_bits = set_reg_val(reg->id, val);
kvmppc_set_tsr_bits(vcpu, tsr_bits);
break;
}
case KVM_REG_PPC_CLEAR_TSR: {
- u32 tsr_bits;
- r = get_user(tsr_bits, (u32 __user *)(long)reg->addr);
+ u32 tsr_bits = set_reg_val(reg->id, val);
kvmppc_clr_tsr_bits(vcpu, tsr_bits);
break;
}
case KVM_REG_PPC_TSR: {
- u32 tsr;
- r = get_user(tsr, (u32 __user *)(long)reg->addr);
+ u32 tsr = set_reg_val(reg->id, val);
kvmppc_set_tsr(vcpu, tsr);
break;
}
case KVM_REG_PPC_TCR: {
- u32 tcr;
- r = get_user(tcr, (u32 __user *)(long)reg->addr);
+ u32 tcr = set_reg_val(reg->id, val);
kvmppc_set_tcr(vcpu, tcr);
break;
}
default:
+ r = kvmppc_set_one_reg(vcpu, reg->id, &val);
break;
}
+
return r;
}
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index 6dd4de7..576010f 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -425,6 +425,18 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
return kvmppc_set_sregs_ivor(vcpu, sregs);
}
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
+{
+ return -EINVAL;
+}
+
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
+{
+ return -EINVAL;
+}
+
struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
{
struct kvmppc_vcpu_e500 *vcpu_e500;
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
index 1f89d26..b071bdc 100644
--- a/arch/powerpc/kvm/e500mc.c
+++ b/arch/powerpc/kvm/e500mc.c
@@ -255,6 +255,18 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
return kvmppc_set_sregs_ivor(vcpu, sregs);
}
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
+{
+ return -EINVAL;
+}
+
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
+{
+ return -EINVAL;
+}
+
struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
{
struct kvmppc_vcpu_e500 *vcpu_e500;
--
1.7.4.1
^ permalink raw reply related
* [PATCH 0/8 v3] KVM: PPC: e500: Enable FSL e6500 core
From: Mihai Caraman @ 2013-04-11 10:03 UTC (permalink / raw)
To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
Enable basic support for Freescale e6500 core, adding MAV 2.0 support.
Validated on T4240QDS platfrom. Altivec, Multithreading and HW Tablewalk
are not addressed by this patchset.
Mihai Caraman (8):
KVM: PPC: Book3E: Refactor ONE_REG ioctl implementation
KVM: PPC: e500: Expose MMU registers via ONE_REG
KVM: PPC: e500: Move vcpu's MMU configuration to dedicated functions
KVM: PPC: e500: Add support for TLBnPS registers
KVM: PPC: e500: Add support for EPTCFG register
KVM: PPC: e500: Remove E.PT and E.HV.LRAT categories from VCPUs
KVM: PPC: e500mc: Enable e6500 cores
KVM: PPC: e500: Add e6500 core to Kconfig description
Documentation/virtual/kvm/api.txt | 16 +++
arch/powerpc/include/asm/kvm_host.h | 2 +
arch/powerpc/include/uapi/asm/kvm.h | 22 ++++
arch/powerpc/kvm/44x.c | 12 ++
arch/powerpc/kvm/Kconfig | 6 +-
arch/powerpc/kvm/booke.c | 102 ++++++++++---------
arch/powerpc/kvm/e500.c | 14 +++
arch/powerpc/kvm/e500.h | 22 ++++
arch/powerpc/kvm/e500_emulate.c | 19 ++++
arch/powerpc/kvm/e500_mmu.c | 192 +++++++++++++++++++++++++++++++----
arch/powerpc/kvm/e500mc.c | 16 +++
11 files changed, 351 insertions(+), 72 deletions(-)
--
1.7.4.1
^ permalink raw reply
* [PATCH 3/8 v3] KVM: PPC: e500: Move vcpu's MMU configuration to dedicated functions
From: Mihai Caraman @ 2013-04-11 10:03 UTC (permalink / raw)
To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1365674594-17410-1-git-send-email-mihai.caraman@freescale.com>
Vcpu's MMU default configuration and geometry update logic was buried in
a chunk of code. Move them to dedicated functions to add more clarity.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
- No change
v2:
- Add better patch description
arch/powerpc/kvm/e500_mmu.c | 60 +++++++++++++++++++++++++++---------------
1 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/arch/powerpc/kvm/e500_mmu.c b/arch/powerpc/kvm/e500_mmu.c
index 44f7762..08a5b0d 100644
--- a/arch/powerpc/kvm/e500_mmu.c
+++ b/arch/powerpc/kvm/e500_mmu.c
@@ -690,6 +690,20 @@ int kvmppc_set_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
return r;
}
+static int vcpu_mmu_geometry_update(struct kvm_vcpu *vcpu,
+ struct kvm_book3e_206_tlb_params *params)
+{
+ vcpu->arch.tlbcfg[0] &= ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+ if (params->tlb_sizes[0] <= 2048)
+ vcpu->arch.tlbcfg[0] |= params->tlb_sizes[0];
+ vcpu->arch.tlbcfg[0] |= params->tlb_ways[0] << TLBnCFG_ASSOC_SHIFT;
+
+ vcpu->arch.tlbcfg[1] &= ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+ vcpu->arch.tlbcfg[1] |= params->tlb_sizes[1];
+ vcpu->arch.tlbcfg[1] |= params->tlb_ways[1] << TLBnCFG_ASSOC_SHIFT;
+ return 0;
+}
+
int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
struct kvm_config_tlb *cfg)
{
@@ -786,16 +800,8 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
vcpu_e500->gtlb_offset[0] = 0;
vcpu_e500->gtlb_offset[1] = params.tlb_sizes[0];
- vcpu->arch.mmucfg = mfspr(SPRN_MMUCFG) & ~MMUCFG_LPIDSIZE;
-
- vcpu->arch.tlbcfg[0] &= ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
- if (params.tlb_sizes[0] <= 2048)
- vcpu->arch.tlbcfg[0] |= params.tlb_sizes[0];
- vcpu->arch.tlbcfg[0] |= params.tlb_ways[0] << TLBnCFG_ASSOC_SHIFT;
-
- vcpu->arch.tlbcfg[1] &= ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
- vcpu->arch.tlbcfg[1] |= params.tlb_sizes[1];
- vcpu->arch.tlbcfg[1] |= params.tlb_ways[1] << TLBnCFG_ASSOC_SHIFT;
+ /* Update vcpu's MMU geometry based on SW_TLB input */
+ vcpu_mmu_geometry_update(vcpu, ¶ms);
vcpu_e500->shared_tlb_pages = pages;
vcpu_e500->num_shared_tlb_pages = num_pages;
@@ -831,6 +837,27 @@ int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu,
return 0;
}
+/* Vcpu's MMU default configuration */
+static int vcpu_mmu_init(struct kvm_vcpu *vcpu,
+ struct kvmppc_e500_tlb_params *params)
+{
+ /* Initialize RASIZE, PIDSIZE, NTLBS and MAVN fields with host values*/
+ vcpu->arch.mmucfg = mfspr(SPRN_MMUCFG) & ~MMUCFG_LPIDSIZE;
+
+ /* Initialize TLBnCFG fields with host values and SW_TLB geometry*/
+ vcpu->arch.tlbcfg[0] = mfspr(SPRN_TLB0CFG) &
+ ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+ vcpu->arch.tlbcfg[0] |= params[0].entries;
+ vcpu->arch.tlbcfg[0] |= params[0].ways << TLBnCFG_ASSOC_SHIFT;
+
+ vcpu->arch.tlbcfg[1] = mfspr(SPRN_TLB1CFG) &
+ ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+ vcpu->arch.tlbcfg[1] |= params[1].entries;
+ vcpu->arch.tlbcfg[1] |= params[1].ways << TLBnCFG_ASSOC_SHIFT;
+
+ return 0;
+}
+
int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
{
struct kvm_vcpu *vcpu = &vcpu_e500->vcpu;
@@ -875,18 +902,7 @@ int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
if (!vcpu_e500->g2h_tlb1_map)
goto err;
- /* Init TLB configuration register */
- vcpu->arch.tlbcfg[0] = mfspr(SPRN_TLB0CFG) &
- ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
- vcpu->arch.tlbcfg[0] |= vcpu_e500->gtlb_params[0].entries;
- vcpu->arch.tlbcfg[0] |=
- vcpu_e500->gtlb_params[0].ways << TLBnCFG_ASSOC_SHIFT;
-
- vcpu->arch.tlbcfg[1] = mfspr(SPRN_TLB1CFG) &
- ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
- vcpu->arch.tlbcfg[1] |= vcpu_e500->gtlb_params[1].entries;
- vcpu->arch.tlbcfg[1] |=
- vcpu_e500->gtlb_params[1].ways << TLBnCFG_ASSOC_SHIFT;
+ vcpu_mmu_init(vcpu, vcpu_e500->gtlb_params);
kvmppc_recalc_tlb1map_range(vcpu_e500);
return 0;
--
1.7.4.1
^ permalink raw reply related
* [PATCH 4/8 v3] KVM: PPC: e500: Add support for TLBnPS registers
From: Mihai Caraman @ 2013-04-11 10:03 UTC (permalink / raw)
To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1365674594-17410-1-git-send-email-mihai.caraman@freescale.com>
Add support for TLBnPS registers available in MMU Architecture Version
(MAV) 2.0.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
- Add vcpu_ftr enum
v2:
- Add vcpu generic function has_feature()
Documentation/virtual/kvm/api.txt | 4 ++++
arch/powerpc/include/asm/kvm_host.h | 1 +
arch/powerpc/include/uapi/asm/kvm.h | 4 ++++
arch/powerpc/kvm/e500.h | 18 ++++++++++++++++++
arch/powerpc/kvm/e500_emulate.c | 10 ++++++++++
arch/powerpc/kvm/e500_mmu.c | 22 ++++++++++++++++++++++
6 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 1a76663..f045377 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1803,6 +1803,10 @@ registers, find a list below:
PPC | KVM_REG_PPC_TLB1CFG | 32
PPC | KVM_REG_PPC_TLB2CFG | 32
PPC | KVM_REG_PPC_TLB3CFG | 32
+ PPC | KVM_REG_PPC_TLB0PS | 32
+ PPC | KVM_REG_PPC_TLB1PS | 32
+ PPC | KVM_REG_PPC_TLB2PS | 32
+ PPC | KVM_REG_PPC_TLB3PS | 32
ARM registers are mapped using the lower 32 bits. The upper 16 of that
is the register group type, or coprocessor number:
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index e34f8fe..3b6cee3 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -502,6 +502,7 @@ struct kvm_vcpu_arch {
spinlock_t wdt_lock;
struct timer_list wdt_timer;
u32 tlbcfg[4];
+ u32 tlbps[4];
u32 mmucfg;
u32 epr;
u32 crit_save;
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index 93d063f..91341d9 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -442,5 +442,9 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_TLB1CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x94)
#define KVM_REG_PPC_TLB2CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x95)
#define KVM_REG_PPC_TLB3CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x96)
+#define KVM_REG_PPC_TLB0PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x97)
+#define KVM_REG_PPC_TLB1PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x98)
+#define KVM_REG_PPC_TLB2PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x99)
+#define KVM_REG_PPC_TLB3PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a)
#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index b73ca7a..c2e5e98 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -23,6 +23,10 @@
#include <asm/mmu-book3e.h>
#include <asm/tlb.h>
+enum vcpu_ftr {
+ VCPU_FTR_MMU_V2
+};
+
#define E500_PID_NUM 3
#define E500_TLB_NUM 2
@@ -299,4 +303,18 @@ static inline unsigned int get_tlbmiss_tid(struct kvm_vcpu *vcpu)
#define get_tlb_sts(gtlbe) (MAS1_TS)
#endif /* !BOOKE_HV */
+static inline bool has_feature(const struct kvm_vcpu *vcpu,
+ enum vcpu_ftr ftr)
+{
+ bool has_ftr;
+ switch (ftr) {
+ case VCPU_FTR_MMU_V2:
+ has_ftr = ((vcpu->arch.mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V2);
+ break;
+ default:
+ return false;
+ }
+ return has_ftr;
+}
+
#endif /* KVM_E500_H */
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index e78f353..12b8de2 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -284,6 +284,16 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
case SPRN_TLB1CFG:
*spr_val = vcpu->arch.tlbcfg[1];
break;
+ case SPRN_TLB0PS:
+ if (!has_feature(vcpu, VCPU_FTR_MMU_V2))
+ return EMULATE_FAIL;
+ *spr_val = vcpu->arch.tlbps[0];
+ break;
+ case SPRN_TLB1PS:
+ if (!has_feature(vcpu, VCPU_FTR_MMU_V2))
+ return EMULATE_FAIL;
+ *spr_val = vcpu->arch.tlbps[1];
+ break;
case SPRN_L1CSR0:
*spr_val = vcpu_e500->l1csr0;
break;
diff --git a/arch/powerpc/kvm/e500_mmu.c b/arch/powerpc/kvm/e500_mmu.c
index 08a5b0d..a863dc1 100644
--- a/arch/powerpc/kvm/e500_mmu.c
+++ b/arch/powerpc/kvm/e500_mmu.c
@@ -631,6 +631,13 @@ int kvmppc_get_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
i = id - KVM_REG_PPC_TLB0CFG;
*val = get_reg_val(id, vcpu->arch.tlbcfg[i]);
break;
+ case KVM_REG_PPC_TLB0PS:
+ case KVM_REG_PPC_TLB1PS:
+ case KVM_REG_PPC_TLB2PS:
+ case KVM_REG_PPC_TLB3PS:
+ i = id - KVM_REG_PPC_TLB0PS;
+ *val = get_reg_val(id, vcpu->arch.tlbps[i]);
+ break;
default:
r = -EINVAL;
break;
@@ -682,6 +689,16 @@ int kvmppc_set_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
r = -EINVAL;
break;
}
+ case KVM_REG_PPC_TLB0PS:
+ case KVM_REG_PPC_TLB1PS:
+ case KVM_REG_PPC_TLB2PS:
+ case KVM_REG_PPC_TLB3PS: {
+ u32 reg = set_reg_val(id, *val);
+ i = id - KVM_REG_PPC_TLB0PS;
+ if (reg != vcpu->arch.tlbps[i])
+ r = -EINVAL;
+ break;
+ }
default:
r = -EINVAL;
break;
@@ -855,6 +872,11 @@ static int vcpu_mmu_init(struct kvm_vcpu *vcpu,
vcpu->arch.tlbcfg[1] |= params[1].entries;
vcpu->arch.tlbcfg[1] |= params[1].ways << TLBnCFG_ASSOC_SHIFT;
+ if (has_feature(vcpu, VCPU_FTR_MMU_V2)) {
+ vcpu->arch.tlbps[0] = mfspr(SPRN_TLB0PS);
+ vcpu->arch.tlbps[1] = mfspr(SPRN_TLB1PS);
+ }
+
return 0;
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH 2/8 v3] KVM: PPC: e500: Expose MMU registers via ONE_REG
From: Mihai Caraman @ 2013-04-11 10:03 UTC (permalink / raw)
To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
In-Reply-To: <1365674594-17410-1-git-send-email-mihai.caraman@freescale.com>
MMU registers were exposed to user-space using sregs interface. Add them
to ONE_REG interface using kvmppc_get_one_reg/kvmppc_set_one_reg delegation
mechanism.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
---
v3:
- Fix case breaks
v2:
- Restrict set_one_reg operation for MMU registers to HW values
Documentation/virtual/kvm/api.txt | 11 ++++
arch/powerpc/include/uapi/asm/kvm.h | 17 ++++++
arch/powerpc/kvm/e500.c | 6 ++-
arch/powerpc/kvm/e500.h | 4 ++
arch/powerpc/kvm/e500_mmu.c | 94 +++++++++++++++++++++++++++++++++++
arch/powerpc/kvm/e500mc.c | 6 ++-
6 files changed, 134 insertions(+), 4 deletions(-)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 976eb65..1a76663 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1792,6 +1792,17 @@ registers, find a list below:
PPC | KVM_REG_PPC_TSR | 32
PPC | KVM_REG_PPC_OR_TSR | 32
PPC | KVM_REG_PPC_CLEAR_TSR | 32
+ PPC | KVM_REG_PPC_MAS0 | 32
+ PPC | KVM_REG_PPC_MAS1 | 32
+ PPC | KVM_REG_PPC_MAS2 | 64
+ PPC | KVM_REG_PPC_MAS7_3 | 64
+ PPC | KVM_REG_PPC_MAS4 | 32
+ PPC | KVM_REG_PPC_MAS6 | 32
+ PPC | KVM_REG_PPC_MMUCFG | 32
+ PPC | KVM_REG_PPC_TLB0CFG | 32
+ PPC | KVM_REG_PPC_TLB1CFG | 32
+ PPC | KVM_REG_PPC_TLB2CFG | 32
+ PPC | KVM_REG_PPC_TLB3CFG | 32
ARM registers are mapped using the lower 32 bits. The upper 16 of that
is the register group type, or coprocessor number:
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index c2ff99c..93d063f 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -426,4 +426,21 @@ struct kvm_get_htab_header {
/* Debugging: Special instruction for software breakpoint */
#define KVM_REG_PPC_DEBUG_INST (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8b)
+/* MMU registers */
+#define KVM_REG_PPC_MAS0 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8c)
+#define KVM_REG_PPC_MAS1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8d)
+#define KVM_REG_PPC_MAS2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8e)
+#define KVM_REG_PPC_MAS7_3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8f)
+#define KVM_REG_PPC_MAS4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x90)
+#define KVM_REG_PPC_MAS6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x91)
+#define KVM_REG_PPC_MMUCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x92)
+/*
+ * TLBnCFG fields TLBnCFG_N_ENTRY and TLBnCFG_ASSOC can be changed only using
+ * KVM_CAP_SW_TLB ioctl
+ */
+#define KVM_REG_PPC_TLB0CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x93)
+#define KVM_REG_PPC_TLB1CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x94)
+#define KVM_REG_PPC_TLB2CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x95)
+#define KVM_REG_PPC_TLB3CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x96)
+
#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index 576010f..ce6b73c 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -428,13 +428,15 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
union kvmppc_one_reg *val)
{
- return -EINVAL;
+ int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
+ return r;
}
int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
union kvmppc_one_reg *val)
{
- return -EINVAL;
+ int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
+ return r;
}
struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index 33db48a..b73ca7a 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -131,6 +131,10 @@ void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500);
void kvmppc_get_sregs_e500_tlb(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
int kvmppc_set_sregs_e500_tlb(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
+int kvmppc_get_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val);
+int kvmppc_set_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val);
#ifdef CONFIG_KVM_E500V2
unsigned int kvmppc_e500_get_sid(struct kvmppc_vcpu_e500 *vcpu_e500,
diff --git a/arch/powerpc/kvm/e500_mmu.c b/arch/powerpc/kvm/e500_mmu.c
index 5c44759..44f7762 100644
--- a/arch/powerpc/kvm/e500_mmu.c
+++ b/arch/powerpc/kvm/e500_mmu.c
@@ -596,6 +596,100 @@ int kvmppc_set_sregs_e500_tlb(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
return 0;
}
+int kvmppc_get_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
+{
+ int r = 0;
+ long int i;
+
+ switch (id) {
+ case KVM_REG_PPC_MAS0:
+ *val = get_reg_val(id, vcpu->arch.shared->mas0);
+ break;
+ case KVM_REG_PPC_MAS1:
+ *val = get_reg_val(id, vcpu->arch.shared->mas1);
+ break;
+ case KVM_REG_PPC_MAS2:
+ *val = get_reg_val(id, vcpu->arch.shared->mas2);
+ break;
+ case KVM_REG_PPC_MAS7_3:
+ *val = get_reg_val(id, vcpu->arch.shared->mas7_3);
+ break;
+ case KVM_REG_PPC_MAS4:
+ *val = get_reg_val(id, vcpu->arch.shared->mas4);
+ break;
+ case KVM_REG_PPC_MAS6:
+ *val = get_reg_val(id, vcpu->arch.shared->mas6);
+ break;
+ case KVM_REG_PPC_MMUCFG:
+ *val = get_reg_val(id, vcpu->arch.mmucfg);
+ break;
+ case KVM_REG_PPC_TLB0CFG:
+ case KVM_REG_PPC_TLB1CFG:
+ case KVM_REG_PPC_TLB2CFG:
+ case KVM_REG_PPC_TLB3CFG:
+ i = id - KVM_REG_PPC_TLB0CFG;
+ *val = get_reg_val(id, vcpu->arch.tlbcfg[i]);
+ break;
+ default:
+ r = -EINVAL;
+ break;
+ }
+
+ return r;
+}
+
+int kvmppc_set_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
+ union kvmppc_one_reg *val)
+{
+ int r = 0;
+ long int i;
+
+ switch (id) {
+ case KVM_REG_PPC_MAS0:
+ vcpu->arch.shared->mas0 = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_MAS1:
+ vcpu->arch.shared->mas1 = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_MAS2:
+ vcpu->arch.shared->mas2 = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_MAS7_3:
+ vcpu->arch.shared->mas7_3 = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_MAS4:
+ vcpu->arch.shared->mas4 = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_MAS6:
+ vcpu->arch.shared->mas6 = set_reg_val(id, *val);
+ break;
+ /* Only allow MMU registers to be set to the config supported by KVM */
+ case KVM_REG_PPC_MMUCFG: {
+ u32 reg = set_reg_val(id, *val);
+ if (reg != vcpu->arch.mmucfg)
+ r = -EINVAL;
+ break;
+ }
+ case KVM_REG_PPC_TLB0CFG:
+ case KVM_REG_PPC_TLB1CFG:
+ case KVM_REG_PPC_TLB2CFG:
+ case KVM_REG_PPC_TLB3CFG: {
+ /* MMU geometry (N_ENTRY/ASSOC) can be set only using SW_TLB */
+ u32 reg = set_reg_val(id, *val);
+ i = id - KVM_REG_PPC_TLB0CFG;
+ if (reg != vcpu->arch.tlbcfg[i])
+ r = -EINVAL;
+ break;
+ }
+ default:
+ r = -EINVAL;
+ break;
+ }
+
+ return r;
+}
+
int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
struct kvm_config_tlb *cfg)
{
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
index b071bdc..ab073a8 100644
--- a/arch/powerpc/kvm/e500mc.c
+++ b/arch/powerpc/kvm/e500mc.c
@@ -258,13 +258,15 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
union kvmppc_one_reg *val)
{
- return -EINVAL;
+ int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
+ return r;
}
int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
union kvmppc_one_reg *val)
{
- return -EINVAL;
+ int r = kvmppc_set_one_reg_e500_tlb(vcpu, id, val);
+ return r;
}
struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH 0/2] net: mv643xx_eth: use managed clk and allocation
From: Florian Fainelli @ 2013-04-11 9:32 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: Andrew Lunn, Jason Cooper, Sergei Shtylyov, linux-doc,
devicetree-discuss, linux-kernel, Rob Herring, Paul Mackerras,
Rob Landley, netdev, linuxppc-dev, Lennert Buytenhek
In-Reply-To: <1365672574-31123-1-git-send-email-sebastian.hesselbarth@gmail.com>
Le 04/11/13 11:29, Sebastian Hesselbarth a écrit :
> With introduction of common clock framework and the ability to provide
> gated clocks, mv643xx_eth required calls to get and enable these clock
> gates on some platforms. Back then, common clock framework api wasn't
> safe for architectures without support for common clocks. This has
> changed now and there are also managed (devm_) counterparts for clock
> related functions.
>
> The second patch in this series, also converts kzalloc to devm_kzalloc
> where applicable.
>
> Both patches have been sent to the corresponding mailing lists as
> individual patches before. To get the order required to apply them right,
> this patch set combines both patches into one set.
>
> Sebastian Hesselbarth (2):
> net: mv643xx_eth: add shared clk and cleanup existing clk handling
> net: mv643xx_eth: use managed devm_kzalloc
Looks good, thanks Sebastian!
Acked-by: Florian Fainelli <florian@openwrt.org>
--
Florian
^ permalink raw reply
* [PATCH v2 2/2] net: mv643xx_eth: use managed devm_kzalloc
From: Sebastian Hesselbarth @ 2013-04-11 9:29 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: Andrew Lunn, Jason Cooper, Sergei Shtylyov, linux-doc,
devicetree-discuss, linux-kernel, Rob Herring, Paul Mackerras,
Rob Landley, netdev, linuxppc-dev, Florian Fainelli,
Lennert Buytenhek
In-Reply-To: <1365672574-31123-1-git-send-email-sebastian.hesselbarth@gmail.com>
This patch moves shared private data kzalloc to managed devm_kzalloc and
cleans now unneccessary kfree and error handling.
Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
Changes from v1:
- replaced EADDRNOTAVAIL with ENOMEM on failing ioremap (Reported by
Sergei Shtylyov)
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Lennert Buytenhek <buytenh@wantstofly.org>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Florian Fainelli <florian@openwrt.org>
Cc: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-doc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
---
drivers/net/ethernet/marvell/mv643xx_eth.c | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index bbe6104..305038f 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -2547,25 +2547,22 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
struct mv643xx_eth_shared_private *msp;
const struct mbus_dram_target_info *dram;
struct resource *res;
- int ret;
if (!mv643xx_eth_version_printed++)
pr_notice("MV-643xx 10/100/1000 ethernet driver version %s\n",
mv643xx_eth_driver_version);
- ret = -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL)
- goto out;
+ return -EINVAL;
- ret = -ENOMEM;
- msp = kzalloc(sizeof(*msp), GFP_KERNEL);
+ msp = devm_kzalloc(&pdev->dev, sizeof(*msp), GFP_KERNEL);
if (msp == NULL)
- goto out;
+ return -ENOMEM;
msp->base = ioremap(res->start, resource_size(res));
if (msp->base == NULL)
- goto out_free;
+ return -ENOMEM;
msp->clk = devm_clk_get(&pdev->dev, NULL);
if (!IS_ERR(msp->clk))
@@ -2585,11 +2582,6 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, msp);
return 0;
-
-out_free:
- kfree(msp);
-out:
- return ret;
}
static int mv643xx_eth_shared_remove(struct platform_device *pdev)
@@ -2599,7 +2591,6 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev)
iounmap(msp->base);
if (!IS_ERR(msp->clk))
clk_disable_unprepare(msp->clk);
- kfree(msp);
return 0;
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH 1/2] net: mv643xx_eth: add shared clk and cleanup existing clk handling
From: Sebastian Hesselbarth @ 2013-04-11 9:29 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: Andrew Lunn, Jason Cooper, Sergei Shtylyov, linux-doc,
devicetree-discuss, linux-kernel, Rob Herring, Paul Mackerras,
Rob Landley, netdev, linuxppc-dev, Florian Fainelli,
Lennert Buytenhek
In-Reply-To: <1365672574-31123-1-git-send-email-sebastian.hesselbarth@gmail.com>
This patch adds an optional shared block clock to avoid lockups on
clock gated controllers. Besides the new clock, clock handling for
existing clocks is cleaned up and moved to devm_clk_get. Device
tree binding documentation is updated for the new clocks property.
Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Lennert Buytenhek <buytenh@wantstofly.org>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Florian Fainelli <florian@openwrt.org>
Cc: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-doc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
---
Documentation/devicetree/bindings/marvell.txt | 3 +++
drivers/net/ethernet/marvell/mv643xx_eth.c | 27 ++++++++++---------------
2 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/Documentation/devicetree/bindings/marvell.txt b/Documentation/devicetree/bindings/marvell.txt
index f1533d9..f7a0da6 100644
--- a/Documentation/devicetree/bindings/marvell.txt
+++ b/Documentation/devicetree/bindings/marvell.txt
@@ -115,6 +115,9 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd.
- compatible : "marvell,mv64360-eth-block"
- reg : Offset and length of the register set for this block
+ Optional properties:
+ - clocks : Phandle to the clock control device and gate bit
+
Example Discovery Ethernet block node:
ethernet-block@2000 {
#address-cells = <1>;
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index aedbd82..bbe6104 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -268,7 +268,7 @@ struct mv643xx_eth_shared_private {
int extended_rx_coal_limit;
int tx_bw_control;
int tx_csum_limit;
-
+ struct clk *clk;
};
#define TX_BW_CONTROL_ABSENT 0
@@ -410,9 +410,7 @@ struct mv643xx_eth_private {
/*
* Hardware-specific parameters.
*/
-#if defined(CONFIG_HAVE_CLK)
struct clk *clk;
-#endif
unsigned int t_clk;
};
@@ -2569,6 +2567,10 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
if (msp->base == NULL)
goto out_free;
+ msp->clk = devm_clk_get(&pdev->dev, NULL);
+ if (!IS_ERR(msp->clk))
+ clk_prepare_enable(msp->clk);
+
/*
* (Re-)program MBUS remapping windows if we are asked to.
*/
@@ -2595,6 +2597,8 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev)
struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev);
iounmap(msp->base);
+ if (!IS_ERR(msp->clk))
+ clk_disable_unprepare(msp->clk);
kfree(msp);
return 0;
@@ -2801,13 +2805,12 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
* it to override the default.
*/
mp->t_clk = 133000000;
-#if defined(CONFIG_HAVE_CLK)
- mp->clk = clk_get(&pdev->dev, (pdev->id ? "1" : "0"));
+ mp->clk = devm_clk_get(&pdev->dev, NULL);
if (!IS_ERR(mp->clk)) {
clk_prepare_enable(mp->clk);
mp->t_clk = clk_get_rate(mp->clk);
}
-#endif
+
set_params(mp, pd);
netif_set_real_num_tx_queues(dev, mp->txq_count);
netif_set_real_num_rx_queues(dev, mp->rxq_count);
@@ -2889,12 +2892,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
return 0;
out:
-#if defined(CONFIG_HAVE_CLK)
- if (!IS_ERR(mp->clk)) {
+ if (!IS_ERR(mp->clk))
clk_disable_unprepare(mp->clk);
- clk_put(mp->clk);
- }
-#endif
free_netdev(dev);
return err;
@@ -2909,12 +2908,8 @@ static int mv643xx_eth_remove(struct platform_device *pdev)
phy_detach(mp->phy);
cancel_work_sync(&mp->tx_timeout_task);
-#if defined(CONFIG_HAVE_CLK)
- if (!IS_ERR(mp->clk)) {
+ if (!IS_ERR(mp->clk))
clk_disable_unprepare(mp->clk);
- clk_put(mp->clk);
- }
-#endif
free_netdev(mp->dev);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 0/2] net: mv643xx_eth: use managed clk and allocation
From: Sebastian Hesselbarth @ 2013-04-11 9:29 UTC (permalink / raw)
To: Sebastian Hesselbarth
Cc: Andrew Lunn, Jason Cooper, Sergei Shtylyov, linux-doc,
devicetree-discuss, linux-kernel, Rob Herring, Paul Mackerras,
Rob Landley, netdev, linuxppc-dev, Florian Fainelli,
Lennert Buytenhek
With introduction of common clock framework and the ability to provide
gated clocks, mv643xx_eth required calls to get and enable these clock
gates on some platforms. Back then, common clock framework api wasn't
safe for architectures without support for common clocks. This has
changed now and there are also managed (devm_) counterparts for clock
related functions.
The second patch in this series, also converts kzalloc to devm_kzalloc
where applicable.
Both patches have been sent to the corresponding mailing lists as
individual patches before. To get the order required to apply them right,
this patch set combines both patches into one set.
Sebastian Hesselbarth (2):
net: mv643xx_eth: add shared clk and cleanup existing clk handling
net: mv643xx_eth: use managed devm_kzalloc
Documentation/devicetree/bindings/marvell.txt | 3 ++
drivers/net/ethernet/marvell/mv643xx_eth.c | 44 +++++++++----------------
2 files changed, 18 insertions(+), 29 deletions(-)
---
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Lennert Buytenhek <buytenh@wantstofly.org>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Florian Fainelli <florian@openwrt.org>
Cc: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-doc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
--
1.7.10.4
^ permalink raw reply
* [PATCH V6] powerpc/85xx: Add machine check handler to fix PCIe erratum on mpc85xx
From: Jia Hongtao @ 2013-04-11 8:36 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: B07421, hongtao.jia
A PCIe erratum of mpc85xx may causes a core hang when a link of PCIe
goes down. when the link goes down, Non-posted transactions issued
via the ATMU requiring completion result in an instruction stall.
At the same time a machine-check exception is generated to the core
to allow further processing by the handler. We implements the handler
which skips the instruction caused the stall.
This patch depends on patch:
powerpc/85xx: Add platform_device declaration to fsl_pci.h
Signed-off-by: Zhao Chenhui <b35336@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Liu Shuo <soniccat.liu@gmail.com>
Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com>
---
V5:
* Move OP and XOP defines to a new header file: asm/ppc-disassemble.h
* Add X UX BRX variant of load instruction emulation
* Remove A variant of load instruction emulation
V4:
* Fill rd with all-Fs if the skipped instruction is load and emulate the
instruction.
* Let KVM/QEMU deal with the exception if the machine check comes from KVM.
arch/powerpc/include/asm/ppc-disassemble.h | 31 +++++++
arch/powerpc/kernel/cpu_setup_fsl_booke.S | 2 +-
arch/powerpc/kernel/traps.c | 3 +
arch/powerpc/sysdev/fsl_pci.c | 140 +++++++++++++++++++++++++++++
arch/powerpc/sysdev/fsl_pci.h | 6 ++
5 files changed, 181 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/include/asm/ppc-disassemble.h
diff --git a/arch/powerpc/include/asm/ppc-disassemble.h b/arch/powerpc/include/asm/ppc-disassemble.h
new file mode 100644
index 0000000..f9782b8
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc-disassemble.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * provides opcode and xopcode images for use by emulating
+ * instructions
+ */
+#ifndef _ASM_POWERPC_PPC_DISASSEMBLE_H
+#define _ASM_POWERPC_PPC_DISASSEMBLE_H
+
+#define OP_LWZ 32
+#define OP_LWZU 33
+#define OP_LBZ 34
+#define OP_LBZU 35
+#define OP_LHZ 40
+#define OP_LHZU 41
+
+#define OP_31_XOP_LWZX 23
+#define OP_31_XOP_LWZUX 55
+#define OP_31_XOP_LBZX 87
+#define OP_31_XOP_LBZUX 119
+#define OP_31_XOP_LHZX 279
+#define OP_31_XOP_LHZUX 311
+#define OP_31_XOP_LWBRX 534
+#define OP_31_XOP_LHBRX 790
+
+#endif
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
index dcd8819..f1bde90 100644
--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -66,7 +66,7 @@ _GLOBAL(__setup_cpu_e500v2)
bl __e500_icache_setup
bl __e500_dcache_setup
bl __setup_e500_ivors
-#ifdef CONFIG_FSL_RIO
+#if defined(CONFIG_FSL_RIO) || defined(CONFIG_FSL_PCI)
/* Ensure that RFXE is set */
mfspr r3,SPRN_HID1
oris r3,r3,HID1_RFXE@h
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index a008cf5..dd275a4 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -59,6 +59,7 @@
#include <asm/fadump.h>
#include <asm/switch_to.h>
#include <asm/debug.h>
+#include <sysdev/fsl_pci.h>
#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
int (*__debugger)(struct pt_regs *regs) __read_mostly;
@@ -556,6 +557,8 @@ int machine_check_e500(struct pt_regs *regs)
if (reason & MCSR_BUS_RBERR) {
if (fsl_rio_mcheck_exception(regs))
return 1;
+ if (fsl_pci_mcheck_exception(regs))
+ return 1;
}
printk("Machine check in kernel mode.\n");
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 682084d..aaa54c5 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -26,11 +26,15 @@
#include <linux/memblock.h>
#include <linux/log2.h>
#include <linux/slab.h>
+#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
#include <asm/machdep.h>
+#include <asm/disassemble.h>
+#include <asm/ppc-disassemble.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
@@ -826,6 +830,142 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose)
return 0;
}
+#ifdef CONFIG_E500
+static int mcheck_handle_load(struct pt_regs *regs, u32 inst)
+{
+ unsigned int rd, ra, rb, d;
+
+ rd = get_rt(inst);
+ ra = get_ra(inst);
+ rb = get_rb(inst);
+ d = get_d(inst);
+
+ switch (get_op(inst)) {
+ case 31:
+ switch (get_xop(inst)) {
+ case OP_31_XOP_LWZX:
+ case OP_31_XOP_LWBRX:
+ regs->gpr[rd] = 0xffffffff;
+ break;
+
+ case OP_31_XOP_LWZUX:
+ regs->gpr[rd] = 0xffffffff;
+ regs->gpr[ra] += regs->gpr[rb];
+ break;
+
+ case OP_31_XOP_LBZX:
+ regs->gpr[rd] = 0xff;
+ break;
+
+ case OP_31_XOP_LBZUX:
+ regs->gpr[rd] = 0xff;
+ regs->gpr[ra] += regs->gpr[rb];
+ break;
+
+ case OP_31_XOP_LHZX:
+ case OP_31_XOP_LHBRX:
+ regs->gpr[rd] = 0xffff;
+ break;
+
+ case OP_31_XOP_LHZUX:
+ regs->gpr[rd] = 0xffff;
+ regs->gpr[ra] += regs->gpr[rb];
+ break;
+
+ default:
+ return 0;
+ }
+ break;
+
+ case OP_LWZ:
+ regs->gpr[rd] = 0xffffffff;
+ break;
+
+ case OP_LWZU:
+ regs->gpr[rd] = 0xffffffff;
+ regs->gpr[ra] += (s16)d;
+ break;
+
+ case OP_LBZ:
+ regs->gpr[rd] = 0xff;
+ break;
+
+ case OP_LBZU:
+ regs->gpr[rd] = 0xff;
+ regs->gpr[ra] += (s16)d;
+ break;
+
+ case OP_LHZ:
+ regs->gpr[rd] = 0xffff;
+ break;
+
+ case OP_LHZU:
+ regs->gpr[rd] = 0xffff;
+ regs->gpr[ra] += (s16)d;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int is_in_pci_mem_space(phys_addr_t addr)
+{
+ struct pci_controller *hose;
+ struct resource *res;
+ int i;
+
+ list_for_each_entry(hose, &hose_list, list_node) {
+ if (!early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP))
+ continue;
+
+ for (i = 0; i < 3; i++) {
+ res = &hose->mem_resources[i];
+ if ((res->flags & IORESOURCE_MEM) &&
+ addr >= res->start && addr <= res->end)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int fsl_pci_mcheck_exception(struct pt_regs *regs)
+{
+ u32 inst;
+ int ret;
+ phys_addr_t addr = 0;
+
+ /* Let KVM/QEMU deal with the exception */
+ if (regs->msr & MSR_GS)
+ return 0;
+
+#ifdef CONFIG_PHYS_64BIT
+ addr = mfspr(SPRN_MCARU);
+ addr <<= 32;
+#endif
+ addr += mfspr(SPRN_MCAR);
+
+ if (is_in_pci_mem_space(addr)) {
+ if (user_mode(regs)) {
+ pagefault_disable();
+ ret = get_user(regs->nip, &inst);
+ pagefault_enable();
+ } else {
+ ret = probe_kernel_address(regs->nip, inst);
+ }
+
+ if (mcheck_handle_load(regs, inst)) {
+ regs->nip += 4;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+#endif
+
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
static const struct of_device_id pci_ids[] = {
{ .compatible = "fsl,mpc8540-pci", },
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index 851dd56..b0d01ea 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -115,5 +115,11 @@ static inline int mpc85xx_pci_err_probe(struct platform_device *op)
}
#endif
+#ifdef CONFIG_FSL_PCI
+extern int fsl_pci_mcheck_exception(struct pt_regs *);
+#else
+static inline int fsl_pci_mcheck_exception(struct pt_regs *regs) {return 0; }
+#endif
+
#endif /* __POWERPC_FSL_PCI_H */
#endif /* __KERNEL__ */
--
1.8.0
^ permalink raw reply related
* RE: [PATCH V5] powerpc/85xx: Add machine check handler to fix PCIe erratum on mpc85xx
From: Jia Hongtao-B38951 @ 2013-04-11 9:14 UTC (permalink / raw)
To: Wood Scott-B07421; +Cc: linuxppc-dev@lists.ozlabs.org, Li Yang-R58472
In-Reply-To: <1365630703.8381.23@snotra>
> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Thursday, April 11, 2013 5:52 AM
> To: Jia Hongtao-B38951
> Cc: linuxppc-dev@lists.ozlabs.org; galak@kernel.crashing.org; Wood Scott-
> B07421; Li Yang-R58472; Jia Hongtao-B38951
> Subject: Re: [PATCH V5] powerpc/85xx: Add machine check handler to fix
> PCIe erratum on mpc85xx
>=20
> On 04/08/2013 03:26:54 AM, Jia Hongtao wrote:
> > @@ -826,6 +829,124 @@ u64 fsl_pci_immrbar_base(struct pci_controller
> > *hose)
> > return 0;
> > }
> >
> > +#ifdef CONFIG_E500
> > +
> > +#define OP_LWZ 32
> > +#define OP_LWZU 33
> > +#define OP_LBZ 34
> > +#define OP_LBZU 35
> > +#define OP_LHZ 40
> > +#define OP_LHZU 41
> > +#define OP_LHA 42
> > +#define OP_LHAU 43
>=20
> Can you move these to asm/ppc-opcode.h (or possibly
> asm/ppc-disassemble.h if we don't want to mix the two methods of
> describing instructions)?
Yes, mix the two methods is not appropriate.
asm/ppc-disassemble.h is a nice choice.
>=20
> > +static int mcheck_handle_load(struct pt_regs *regs, u32 inst)
> > +{
> > + unsigned int rd, ra, d;
> > +
> > + rd =3D get_rt(inst);
> > + ra =3D get_ra(inst);
> > + d =3D get_d(inst);
> > +
> > + switch (get_op(inst)) {
> > + case OP_LWZ:
> > + regs->gpr[rd] =3D 0xffffffff;
> > + break;
> > +
> > + case OP_LWZU:
> > + regs->gpr[rd] =3D 0xffffffff;
> > + regs->gpr[ra] +=3D (s16)d;
> > + break;
> > +
> > + case OP_LBZ:
> > + regs->gpr[rd] =3D 0xff;
> > + break;
> > +
> > + case OP_LBZU:
> > + regs->gpr[rd] =3D 0xff;
> > + regs->gpr[ra] +=3D (s16)d;
> > + break;
> > +
> > + case OP_LHZ:
> > + regs->gpr[rd] =3D 0xffff;
> > + break;
> > +
> > + case OP_LHZU:
> > + regs->gpr[rd] =3D 0xffff;
> > + regs->gpr[ra] +=3D (s16)d;
> > + break;
> > +
> > + case OP_LHA:
> > + regs->gpr[rd] =3D 0xffff;
> > + break;
> > +
> > + case OP_LHAU:
> > + regs->gpr[rd] =3D 0xffff;
> > + regs->gpr[ra] +=3D (s16)d;
> > + break;
>=20
> The X and (especially for PCI) BRX versions are important -- probably
> more so than the U versions. I doubt we need the A variant.
Then I will add X and BRX variant and remove A variant.
>=20
> If you do support the A variant, why are you not sign-extending the
> value?
Just curious, sign-extending the value means fill rd with 0xffffffff?
>=20
> Is this erratum present on any 64-bit chips?
No. This erratum only happened in e500 core chips.
>=20
> -Scott
Thanks.
-Hongtao
^ permalink raw reply
* Re: [PATCH -V5 17/25] powerpc/THP: Implement transparent hugepages for ppc64
From: Aneesh Kumar K.V @ 2013-04-11 7:40 UTC (permalink / raw)
To: David Gibson; +Cc: paulus, linuxppc-dev, linux-mm
In-Reply-To: <20130411053823.GE8165@truffula.fritz.box>
David Gibson <dwg@au1.ibm.com> writes:
> On Thu, Apr 04, 2013 at 11:27:55AM +0530, Aneesh Kumar K.V wrote:
>> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
>>
>> We now have pmd entries covering to 16MB range. To implement THP on powerpc,
>> we double the size of PMD. The second half is used to deposit the pgtable (PTE page).
>> We also use the depoisted PTE page for tracking the HPTE information. The information
>> include [ secondary group | 3 bit hidx | valid ]. We use one byte per each HPTE entry.
>> With 16MB hugepage and 64K HPTE we need 256 entries and with 4K HPTE we need
>> 4096 entries. Both will fit in a 4K PTE page.
>>
>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
>> ---
>> arch/powerpc/include/asm/page.h | 2 +-
>> arch/powerpc/include/asm/pgtable-ppc64-64k.h | 3 +-
>> arch/powerpc/include/asm/pgtable-ppc64.h | 2 +-
>> arch/powerpc/include/asm/pgtable.h | 240 ++++++++++++++++++++
>> arch/powerpc/mm/pgtable.c | 314 ++++++++++++++++++++++++++
>> arch/powerpc/mm/pgtable_64.c | 13 ++
>> arch/powerpc/platforms/Kconfig.cputype | 1 +
>> 7 files changed, 572 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
>> index 38e7ff6..b927447 100644
>> --- a/arch/powerpc/include/asm/page.h
>> +++ b/arch/powerpc/include/asm/page.h
>> @@ -40,7 +40,7 @@
>> #ifdef CONFIG_HUGETLB_PAGE
>> extern unsigned int HPAGE_SHIFT;
>> #else
>> -#define HPAGE_SHIFT PAGE_SHIFT
>> +#define HPAGE_SHIFT PMD_SHIFT
>
> That looks like it could break everything except the 64k page size
> 64-bit base.
How about
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index b927447..fadb1ce 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -37,10 +37,19 @@
#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
#ifndef __ASSEMBLY__
-#ifdef CONFIG_HUGETLB_PAGE
+/*
+ * With hugetlbfs enabled we allow the HPAGE_SHIFT to run time
+ * configurable. But we enable THP only with 16MB hugepage.
+ * With only THP configured, we force hugepage size to 16MB.
+ * This should ensure that all subarchs that doesn't support
+ * THP continue to work fine with HPAGE_SHIFT usage.
+ */
+#if defined(CONFIG_HUGETLB_PAGE)
extern unsigned int HPAGE_SHIFT;
-#else
+#elif defined(CONFIG_TRANSPARENT_HUGEPAGE)
#define HPAGE_SHIFT PMD_SHIFT
+#else
+#define HPAGE_SHIFT PAGE_SHIFT
#endif
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
>
>> #endif
>> #define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
>> #define HPAGE_MASK (~(HPAGE_SIZE - 1))
>> diff --git a/arch/powerpc/include/asm/pgtable-ppc64-64k.h b/arch/powerpc/include/asm/pgtable-ppc64-64k.h
>> index 3c529b4..5c5541a 100644
>> --- a/arch/powerpc/include/asm/pgtable-ppc64-64k.h
>> +++ b/arch/powerpc/include/asm/pgtable-ppc64-64k.h
>> @@ -33,7 +33,8 @@
>> #define PGDIR_MASK (~(PGDIR_SIZE-1))
>>
>> /* Bits to mask out from a PMD to get to the PTE page */
>> -#define PMD_MASKED_BITS 0x1ff
>> +/* PMDs point to PTE table fragments which are 4K aligned. */
>> +#define PMD_MASKED_BITS 0xfff
>> /* Bits to mask out from a PGD/PUD to get to the PMD page */
>> #define PUD_MASKED_BITS 0x1ff
>>
>> diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
>> index 0182c20..c0747c7 100644
>> --- a/arch/powerpc/include/asm/pgtable-ppc64.h
>> +++ b/arch/powerpc/include/asm/pgtable-ppc64.h
>> @@ -150,7 +150,7 @@
>> #define pmd_present(pmd) (pmd_val(pmd) != 0)
>> #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0)
>> #define pmd_page_vaddr(pmd) (pmd_val(pmd) & ~PMD_MASKED_BITS)
>> -#define pmd_page(pmd) virt_to_page(pmd_page_vaddr(pmd))
>> +extern struct page *pmd_page(pmd_t pmd);
>
> Does unconditionally changing pmd_page() from a macro to an external
> function have a noticeable performance impact?
I did measure performance impact with THP enabled. Didn't do a micro
benchmark to measure impact of this change. Any suggestion what test
results you would like to see ?
>
>> #define pud_set(pudp, pudval) (pud_val(*(pudp)) = (pudval))
>> #define pud_none(pud) (!pud_val(pud))
>> diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
>> index 4b52726..9fbe2a7 100644
>> --- a/arch/powerpc/include/asm/pgtable.h
>> +++ b/arch/powerpc/include/asm/pgtable.h
>> @@ -23,7 +23,247 @@ struct mm_struct;
>> */
>> #define PTE_PAGE_HIDX_OFFSET (PTRS_PER_PTE * 8)
>>
>> +/* A large part matches with pte bits */
>> +#define PMD_HUGE_PRESENT 0x001 /* software: pte contains a translation */
>> +#define PMD_HUGE_USER 0x002 /* matches one of the PP bits */
>> +#define PMD_HUGE_FILE 0x002 /* (!present only) software: pte holds file offset */
>
> Can we actually get hugepage PMDs that are in this state?
Currently we can't, but we would start supporting THP for page cache later.
>
>> +#define PMD_HUGE_EXEC 0x004 /* No execute on POWER4 and newer (we invert) */
>> +#define PMD_HUGE_SPLITTING 0x008
>> +#define PMD_HUGE_SAO 0x010 /* strong Access order */
>> +#define PMD_HUGE_HASHPTE 0x020
>> +#define PMD_ISHUGE 0x040
>> +#define PMD_HUGE_DIRTY 0x080 /* C: page changed */
>> +#define PMD_HUGE_ACCESSED 0x100 /* R: page referenced */
>> +#define PMD_HUGE_RW 0x200 /* software: user write access allowed */
>> +#define PMD_HUGE_BUSY 0x800 /* software: PTE & hash are busy */
>> +#define PMD_HUGE_HPTEFLAGS (PMD_HUGE_BUSY | PMD_HUGE_HASHPTE)
>> +/*
>> + * We keep both the pmd and pte rpn shift same, eventhough we use only
>> + * lower 12 bits for hugepage flags at pmd level
>
> Why?
>
I was trying to keep PTE level access code to as much similar to huge
PMD level code. hence retained the same RPN SHIFT, since that would work.
>> + */
>> +#define PMD_HUGE_RPN_SHIFT PTE_RPN_SHIFT
>> +#define HUGE_PAGE_SIZE (ASM_CONST(1) << 24)
>> +#define HUGE_PAGE_MASK (~(HUGE_PAGE_SIZE - 1))
>> +
.....
>> diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
>> index 214130a..9f33780 100644
>> --- a/arch/powerpc/mm/pgtable.c
>> +++ b/arch/powerpc/mm/pgtable.c
>> @@ -31,6 +31,7 @@
>> #include <asm/pgalloc.h>
>> #include <asm/tlbflush.h>
>> #include <asm/tlb.h>
>> +#include <asm/machdep.h>
>>
>> #include "mmu_decl.h"
>>
>> @@ -240,3 +241,316 @@ void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
>> }
>> #endif /* CONFIG_DEBUG_VM */
>>
>> +
>> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
>> +static pmd_t set_hugepage_access_flags_filter(pmd_t pmd,
>> + struct vm_area_struct *vma,
>> + int dirty)
>> +{
>> + return pmd;
>> +}
>
> I don't really see why you're splitting out these trivial ...filter()
> functions, rather than just doing it inline in the (single) caller.
No specific reason other than keeping the hugepmd related code similar
to PTE related access code. This should enable us to easily enable THP
support for subarchs.
>
>> +
>> +/*
>> + * This is called when relaxing access to a hugepage. It's also called in the page
>> + * fault path when we don't hit any of the major fault cases, ie, a minor
>> + * update of _PAGE_ACCESSED, _PAGE_DIRTY, etc... The generic code will have
>> + * handled those two for us, we additionally deal with missing execute
>> + * permission here on some processors
>> + */
>> +int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
>> + pmd_t *pmdp, pmd_t entry, int dirty)
>> +{
>> + int changed;
>> + entry = set_hugepage_access_flags_filter(entry, vma, dirty);
>> + changed = !pmd_same(*(pmdp), entry);
>> + if (changed) {
>> + __pmdp_set_access_flags(pmdp, entry);
>> + /*
>> + * Since we are not supporting SW TLB systems, we don't
>> + * have any thing similar to flush_tlb_page_nohash()
>> + */
>> + }
>> + return changed;
>> +}
>> +
>> +int pmdp_test_and_clear_young(struct vm_area_struct *vma,
>> + unsigned long address, pmd_t *pmdp)
>> +{
>> + return __pmdp_test_and_clear_young(vma->vm_mm, address, pmdp);
>> +}
>> +
>> +/*
>> + * We currently remove entries from the hashtable regardless of whether
>> + * the entry was young or dirty. The generic routines only flush if the
>> + * entry was young or dirty which is not good enough.
>> + *
>> + * We should be more intelligent about this but for the moment we override
>> + * these functions and force a tlb flush unconditionally
>> + */
>> +int pmdp_clear_flush_young(struct vm_area_struct *vma,
>> + unsigned long address, pmd_t *pmdp)
>> +{
>> + return __pmdp_test_and_clear_young(vma->vm_mm, address, pmdp);
>> +}
>> +
>> +/*
>> + * We mark the pmd splitting and invalidate all the hpte
>> + * entries for this hugepage.
>> + */
>> +void pmdp_splitting_flush(struct vm_area_struct *vma,
>> + unsigned long address, pmd_t *pmdp)
>> +{
>> + unsigned long old, tmp;
>> +
>> + VM_BUG_ON(address & ~HPAGE_PMD_MASK);
>> +#ifdef PTE_ATOMIC_UPDATES
>> +
>> + __asm__ __volatile__(
>> + "1: ldarx %0,0,%3\n\
>> + andi. %1,%0,%6\n\
>> + bne- 1b \n\
>> + ori %1,%0,%4 \n\
>> + stdcx. %1,0,%3 \n\
>> + bne- 1b"
>> + : "=&r" (old), "=&r" (tmp), "=m" (*pmdp)
>> + : "r" (pmdp), "i" (PMD_HUGE_SPLITTING), "m" (*pmdp), "i" (PMD_HUGE_BUSY)
>> + : "cc" );
>> +#else
>> + old = pmd_val(*pmdp);
>> + *pmdp = __pmd(old | PMD_HUGE_SPLITTING);
>> +#endif
>> + /*
>> + * If we didn't had the splitting flag set, go and flush the
>> + * HPTE entries and serialize against gup fast.
>> + */
>> + if (!(old & PMD_HUGE_SPLITTING)) {
>> +#ifdef CONFIG_PPC_STD_MMU_64
>> + /* We need to flush the hpte */
>> + if (old & PMD_HUGE_HASHPTE)
>> + hpte_need_hugepage_flush(vma->vm_mm, address, pmdp);
>> +#endif
>> + /* need tlb flush only to serialize against gup-fast */
>> + flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
>> + }
>> +}
>> +
>> +/*
>> + * We want to put the pgtable in pmd and use pgtable for tracking
>> + * the base page size hptes
>> + */
>> +void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
>> + pgtable_t pgtable)
>> +{
>> + unsigned long *pgtable_slot;
>> + assert_spin_locked(&mm->page_table_lock);
>> + /*
>> + * we store the pgtable in the second half of PMD
>> + */
>> + pgtable_slot = pmdp + PTRS_PER_PMD;
>> + *pgtable_slot = (unsigned long)pgtable;
>> +}
>> +
>> +#define PTE_FRAG_SIZE (2 * PTRS_PER_PTE * sizeof(pte_t))
>
> Another example of why this define should be moved to a header.
will drop.
>
>> +pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
>> +{
>> + pgtable_t pgtable;
>> + unsigned long *pgtable_slot;
>> +
>> + assert_spin_locked(&mm->page_table_lock);
>> + pgtable_slot = pmdp + PTRS_PER_PMD;
>> + pgtable = (pgtable_t) *pgtable_slot;
>> + /*
>> + * We store HPTE information in the deposited PTE fragment.
>> + * zero out the content on withdraw.
>> + */
>> + memset(pgtable, 0, PTE_FRAG_SIZE);
>> + return pgtable;
>> +}
>> +
>> +/*
>> + * Since we are looking at latest ppc64, we don't need to worry about
>> + * i/d cache coherency on exec fault
>> + */
>> +static pmd_t set_pmd_filter(pmd_t pmd, unsigned long addr)
>> +{
>> + pmd = __pmd(pmd_val(pmd) & ~PMD_HUGE_HPTEFLAGS);
>> + return pmd;
>> +}
>> +
>> +/*
>> + * We can make it less convoluted than __set_pte_at, because
>> + * we can ignore lot of hardware here, because this is only for
>> + * MPSS
>> + */
>> +static inline void __set_pmd_at(struct mm_struct *mm, unsigned long addr,
>> + pmd_t *pmdp, pmd_t pmd, int percpu)
>> +{
>> + /*
>> + * There is nothing in hash page table now, so nothing to
>> + * invalidate, set_pte_at is used for adding new entry.
>> + * For updating we should use update_hugepage_pmd()
>> + */
>> + *pmdp = pmd;
>> +}
>> +
>> +/*
>> + * set a new huge pmd. We should not be called for updating
>> + * an existing pmd entry. That should go via pmd_hugepage_update.
>> + */
>> +void set_pmd_at(struct mm_struct *mm, unsigned long addr,
>> + pmd_t *pmdp, pmd_t pmd)
>> +{
>> + /*
>> + * Note: mm->context.id might not yet have been assigned as
>> + * this context might not have been activated yet when this
>> + * is called.
>> + */
>> + pmd = set_pmd_filter(pmd, addr);
>> +
>> + __set_pmd_at(mm, addr, pmdp, pmd, 0);
>> +
>> +}
>> +
>> +void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
>> + pmd_t *pmdp)
>> +{
>> + pmd_hugepage_update(vma->vm_mm, address, pmdp, PMD_HUGE_PRESENT);
>> + flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
>> +}
>> +
>> +/*
>> + * A linux hugepage PMD was changed and the corresponding hash table entry
>> + * neesd to be flushed.
>> + *
>> + * The linux hugepage PMD now include the pmd entries followed by the address
>> + * to the stashed pgtable_t. The stashed pgtable_t contains the hpte bits.
>> + * [ secondary group | 3 bit hidx | valid ]. We use one byte per each HPTE entry.
>> + * With 16MB hugepage and 64K HPTE we need 256 entries and with 4K HPTE we need
>> + * 4096 entries. Both will fit in a 4K pgtable_t.
>> + */
>> +void hpte_need_hugepage_flush(struct mm_struct *mm, unsigned long addr,
>> + pmd_t *pmdp)
>> +{
>> + int ssize, i;
>> + unsigned long s_addr;
>> + unsigned int psize, valid;
>> + unsigned char *hpte_slot_array;
>> + unsigned long hidx, vpn, vsid, hash, shift, slot;
>> +
>> + /*
>> + * Flush all the hptes mapping this hugepage
>> + */
>> + s_addr = addr & HUGE_PAGE_MASK;
>> + /*
>> + * The hpte hindex are stored in the pgtable whose address is in the
>> + * second half of the PMD
>> + */
>> + hpte_slot_array = *(char **)(pmdp + PTRS_PER_PMD);
>> +
>> + /* get the base page size */
>> + psize = get_slice_psize(mm, s_addr);
>> + shift = mmu_psize_defs[psize].shift;
>> +
>> + for (i = 0; i < HUGE_PAGE_SIZE/(1ul << shift); i++) {
>
> HUGE_PAGE_SIZE >> shift would be a simpler way to do this calculation.
Wonder how I missed that
>
>> + /*
>> + * 8 bits per each hpte entries
>> + * 000| [ secondary group (one bit) | hidx (3 bits) | valid bit]
>> + */
>> + valid = hpte_slot_array[i] & 0x1;
>> + if (!valid)
>> + continue;
>> + hidx = hpte_slot_array[i] >> 1;
>> +
>> + /* get the vpn */
>> + addr = s_addr + (i * (1ul << shift));
>> + if (!is_kernel_addr(addr)) {
>> + ssize = user_segment_size(addr);
>> + vsid = get_vsid(mm->context.id, addr, ssize);
>> + WARN_ON(vsid == 0);
>> + } else {
>> + vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
>> + ssize = mmu_kernel_ssize;
>> + }
>> +
>> + vpn = hpt_vpn(addr, vsid, ssize);
>> + hash = hpt_hash(vpn, shift, ssize);
>> + if (hidx & _PTEIDX_SECONDARY)
>> + hash = ~hash;
>> +
>> + slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
>> + slot += hidx & _PTEIDX_GROUP_IX;
>> + ppc_md.hpte_invalidate(slot, vpn, psize, ssize, 0);
>> + }
>> +}
>> +
>> +static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot)
>> +{
>> + unsigned long pmd_prot = 0;
>> + unsigned long prot = pgprot_val(pgprot);
>> +
>> + if (prot & _PAGE_PRESENT)
>> + pmd_prot |= PMD_HUGE_PRESENT;
>> + if (prot & _PAGE_USER)
>> + pmd_prot |= PMD_HUGE_USER;
>> + if (prot & _PAGE_FILE)
>> + pmd_prot |= PMD_HUGE_FILE;
>> + if (prot & _PAGE_EXEC)
>> + pmd_prot |= PMD_HUGE_EXEC;
>> + /*
>> + * _PAGE_COHERENT should always be set
>> + */
>> + VM_BUG_ON(!(prot & _PAGE_COHERENT));
>> +
>> + if (prot & _PAGE_SAO)
>> + pmd_prot |= PMD_HUGE_SAO;
>
> This looks dubious because _PAGE_SAO is not a single bit. What
> happens if WRITETHRU or NO_CACHE is set without the other?
yes that should be
if ((prot & _PAGE_SAO) == _PAGE_SAO )
>
>> + if (prot & _PAGE_DIRTY)
>> + pmd_prot |= PMD_HUGE_DIRTY;
>> + if (prot & _PAGE_ACCESSED)
>> + pmd_prot |= PMD_HUGE_ACCESSED;
>> + if (prot & _PAGE_RW)
>> + pmd_prot |= PMD_HUGE_RW;
>> +
>> + pmd_val(pmd) |= pmd_prot;
>> + return pmd;
>> +}
>> +
>> +pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
>> +{
>> + pmd_t pmd;
>> +
>> + pmd_val(pmd) = pfn << PMD_HUGE_RPN_SHIFT;
>> + pmd_val(pmd) |= PMD_ISHUGE;
>> + pmd = pmd_set_protbits(pmd, pgprot);
>> + return pmd;
>> +}
>> +
>> +pmd_t mk_pmd(struct page *page, pgprot_t pgprot)
>> +{
>> + return pfn_pmd(page_to_pfn(page), pgprot);
>> +}
>> +
>> +pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
>> +{
>> + /* FIXME!! why are this bits cleared ? */
>
> You really need to answer this question...
will check.
>
>> + pmd_val(pmd) &= ~(PMD_HUGE_PRESENT |
>> + PMD_HUGE_RW |
>> + PMD_HUGE_EXEC);
>> + pmd = pmd_set_protbits(pmd, newprot);
>> + return pmd;
>> +}
>> +
>> +/*
>> + * This is called at the end of handling a user page fault, when the
>> + * fault has been handled by updating a HUGE PMD entry in the linux page tables.
>> + * We use it to preload an HPTE into the hash table corresponding to
>> + * the updated linux HUGE PMD entry.
>> + */
>> +void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
>> + pmd_t *pmd)
>> +{
>> + /* FIXME!!
>> + * Will be done in a later patch
>> + */
>
> If you need another patch to make the code in this patch work, they
> should probably be folded together.
>
I have that as TODO, we can do a hash_preload for hugepage here. But I
don't see we doing that for HugeTLB. So I haven't yet done that for
hugepage. Do you know why we don't do hash_preload for HugeTLB page ?
>> +}
>> +
>> +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
>> diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
>> index e79840b..6fc3488 100644
>> --- a/arch/powerpc/mm/pgtable_64.c
>> +++ b/arch/powerpc/mm/pgtable_64.c
>> @@ -338,6 +338,19 @@ EXPORT_SYMBOL(iounmap);
>> EXPORT_SYMBOL(__iounmap);
>> EXPORT_SYMBOL(__iounmap_at);
>>
>> +/*
>> + * For hugepage we have pfn in the pmd, we use PMD_HUGE_RPN_SHIFT bits for flags
>> + * For PTE page, we have a PTE_FRAG_SIZE (4K) aligned virtual address.
>> + */
>> +struct page *pmd_page(pmd_t pmd)
>> +{
>> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
>> + if (pmd_val(pmd) & PMD_ISHUGE)
>> + return pfn_to_page(pmd_pfn(pmd));
>> +#endif
>> + return virt_to_page(pmd_page_vaddr(pmd));
>> +}
>> +
>> #ifdef CONFIG_PPC_64K_PAGES
>> /*
>> * we support 16 fragments per PTE page. This is limited by how many
>> diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
>> index 72afd28..90ee19b 100644
>> --- a/arch/powerpc/platforms/Kconfig.cputype
>> +++ b/arch/powerpc/platforms/Kconfig.cputype
>> @@ -71,6 +71,7 @@ config PPC_BOOK3S_64
>> select PPC_FPU
>> select PPC_HAVE_PMU_SUPPORT
>> select SYS_SUPPORTS_HUGETLBFS
>> + select HAVE_ARCH_TRANSPARENT_HUGEPAGE if PPC_64K_PAGES
>>
>> config PPC_BOOK3E_64
>> bool "Embedded processors"
-aneesh
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox