* Re: [PATCH 3/4] KVM: PPC: Add support for IOMMU in-kernel handling
From: David Gibson @ 2013-06-24 3:54 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: kvm@vger.kernel.org mailing list, Alexey Kardashevskiy,
Joerg Roedel, Rusty Russell, Alexander Graf, kvm-ppc, open list,
Alex Williamson, Paul Mackerras, linuxppc-dev
In-Reply-To: <1371943693.3944.104.camel@pasglop>
[-- Attachment #1: Type: text/plain, Size: 1457 bytes --]
On Sun, Jun 23, 2013 at 09:28:13AM +1000, Benjamin Herrenschmidt wrote:
> On Sat, 2013-06-22 at 22:03 +1000, David Gibson wrote:
> > I think the interface should not take the group fd, but the container
> > fd. Holding a reference to *that* would keep the necessary things
> > around. But more to the point, it's the right thing semantically:
> >
> > The container is essentially the handle on a host iommu address space,
> > and so that's what should be bound by the KVM call to a particular
> > guest iommu address space. e.g. it would make no sense to bind two
> > different groups to different guest iommu address spaces, if they were
> > in the same container - the guest thinks they are different spaces,
> > but if they're in the same container they must be the same space.
>
> Interestingly, how are we going to extend that when/if we implement
> DDW ?
>
> DDW means an API by which the guest can request the creation of
> additional iommus for a given device (typically, in addition to the
> default smallish 32-bit one using 4k pages, the guest can request
> a larger window in 64-bit space using a larger page size).
So, would a PAPR gest requesting this expect the new window to have
a new liobn, or an existing liobn?
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [PATCH 3/4] KVM: PPC: Add support for IOMMU in-kernel handling
From: Benjamin Herrenschmidt @ 2013-06-24 3:58 UTC (permalink / raw)
To: David Gibson
Cc: kvm@vger.kernel.org mailing list, Alexey Kardashevskiy,
Joerg Roedel, Rusty Russell, Alexander Graf, kvm-ppc, open list,
Alex Williamson, Paul Mackerras, linuxppc-dev
In-Reply-To: <20130624035426.GE25265@voom.fritz.box>
On Mon, 2013-06-24 at 13:54 +1000, David Gibson wrote:
> > DDW means an API by which the guest can request the creation of
> > additional iommus for a given device (typically, in addition to the
> > default smallish 32-bit one using 4k pages, the guest can request
> > a larger window in 64-bit space using a larger page size).
>
> So, would a PAPR gest requesting this expect the new window to have
> a new liobn, or an existing liobn?
New liobn or there is no way to H_PUT_TCE it (it exists in addition
to the legacy window).
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH v2] powerpc/pci: Improve device hotplug initialization
From: Guenter Roeck @ 2013-06-24 4:48 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Yuanquan Chen, linuxppc-dev, linux-kernel, Hiroo Matsumoto
In-Reply-To: <1372038589.3944.118.camel@pasglop>
On Mon, Jun 24, 2013 at 11:49:49AM +1000, Benjamin Herrenschmidt wrote:
> On Fri, 2013-06-21 at 09:54 -0700, Guenter Roeck wrote:
>
> > > v2: Ensure that PCI bus fixup code has been executed before calling
> > > device setup code.
> > >
> > Hi Ben,
> >
> > any comments/feedback on this approach ?
> >
> > It is much less invasive than before and should address your concerns.
>
> And also less nice cleanup :-) I'll have a look.
>
I know :(.
Reminds me of that old story of being stuck between a rock and a hard place ...
Guenter
> Cheers,
> Ben.
>
> > Thanks,
> > Guenter
> >
> > > arch/powerpc/kernel/pci-common.c | 17 ++++++++++++-----
> > > 1 file changed, 12 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
> > > index 7f2273c..6909b13 100644
> > > --- a/arch/powerpc/kernel/pci-common.c
> > > +++ b/arch/powerpc/kernel/pci-common.c
> > > @@ -992,7 +992,7 @@ void pcibios_setup_bus_self(struct pci_bus *bus)
> > > ppc_md.pci_dma_bus_setup(bus);
> > > }
> > >
> > > -void pcibios_setup_device(struct pci_dev *dev)
> > > +static void pcibios_setup_device(struct pci_dev *dev)
> > > {
> > > /* Fixup NUMA node as it may not be setup yet by the generic
> > > * code and is needed by the DMA init
> > > @@ -1013,6 +1013,17 @@ void pcibios_setup_device(struct pci_dev *dev)
> > > ppc_md.pci_irq_fixup(dev);
> > > }
> > >
> > > +int pcibios_add_device(struct pci_dev *dev)
> > > +{
> > > + /*
> > > + * We can only call pcibios_setup_device() after bus setup is complete,
> > > + * since some of the platform specific DMA setup code depends on it.
> > > + */
> > > + if (dev->bus->is_added)
> > > + pcibios_setup_device(dev);
> > > + return 0;
> > > +}
> > > +
> > > void pcibios_setup_bus_devices(struct pci_bus *bus)
> > > {
> > > struct pci_dev *dev;
> > > @@ -1467,10 +1478,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
> > > if (ppc_md.pcibios_enable_device_hook(dev))
> > > return -EINVAL;
> > >
> > > - /* avoid pcie irq fix up impact on cardbus */
> > > - if (dev->hdr_type != PCI_HEADER_TYPE_CARDBUS)
> > > - pcibios_setup_device(dev);
> > > -
> > > return pci_enable_resources(dev, mask);
> > > }
> > >
> > > --
> > > 1.7.9.7
> > >
> > >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at http://www.tux.org/lkml/
>
>
>
^ permalink raw reply
* Re: [PATCH 3/4] KVM: PPC: Add support for IOMMU in-kernel handling
From: Alex Williamson @ 2013-06-24 4:41 UTC (permalink / raw)
To: David Gibson
Cc: kvm@vger.kernel.org mailing list, Alexey Kardashevskiy,
Joerg Roedel, Rusty Russell, Alexander Graf, kvm-ppc, open list,
Paul Mackerras, linuxppc-dev
In-Reply-To: <20130624035249.GD25265@voom.fritz.box>
On Mon, 2013-06-24 at 13:52 +1000, David Gibson wrote:
> On Sat, Jun 22, 2013 at 08:28:06AM -0600, Alex Williamson wrote:
> > On Sat, 2013-06-22 at 22:03 +1000, David Gibson wrote:
> > > On Thu, Jun 20, 2013 at 08:55:13AM -0600, Alex Williamson wrote:
> > > > On Thu, 2013-06-20 at 18:48 +1000, Alexey Kardashevskiy wrote:
> > > > > On 06/20/2013 05:47 PM, Benjamin Herrenschmidt wrote:
> > > > > > On Thu, 2013-06-20 at 15:28 +1000, David Gibson wrote:
> > > > > >>> Just out of curiosity - would not get_file() and fput_atomic() on a
> > > > > >> group's
> > > > > >>> file* do the right job instead of vfio_group_add_external_user() and
> > > > > >>> vfio_group_del_external_user()?
> > > > > >>
> > > > > >> I was thinking that too. Grabbing a file reference would certainly be
> > > > > >> the usual way of handling this sort of thing.
> > > > > >
> > > > > > But that wouldn't prevent the group ownership to be returned to
> > > > > > the kernel or another user would it ?
> > > > >
> > > > >
> > > > > Holding the file pointer does not let the group->container_users counter go
> > > > > to zero
> > > >
> > > > How so? Holding the file pointer means the file won't go away, which
> > > > means the group release function won't be called. That means the group
> > > > won't go away, but that doesn't mean it's attached to an IOMMU. A user
> > > > could call UNSET_CONTAINER.
> > >
> > > Uhh... *thinks*. Ah, I see.
> > >
> > > I think the interface should not take the group fd, but the container
> > > fd. Holding a reference to *that* would keep the necessary things
> > > around. But more to the point, it's the right thing semantically:
> > >
> > > The container is essentially the handle on a host iommu address space,
> > > and so that's what should be bound by the KVM call to a particular
> > > guest iommu address space. e.g. it would make no sense to bind two
> > > different groups to different guest iommu address spaces, if they were
> > > in the same container - the guest thinks they are different spaces,
> > > but if they're in the same container they must be the same space.
> >
> > While the container is the gateway to the iommu, what empowers the
> > container to maintain an iommu is the group. What happens to a
> > container when all the groups are disconnected or closed? Groups are
> > the unit that indicates hardware access, not containers. Thanks,
>
> Uh... huh? I'm really not sure what you're getting at.
>
> The operation we're doing for KVM here is binding a guest iommu
> address space to a particular host iommu address space. Why would we
> not want to use the obvious handle on the host iommu address space,
> which is the container fd?
AIUI, the request isn't for an interface through which to do iommu
mappings. The request is for an interface to show that the user has
sufficient privileges to do mappings. Groups are what gives the user
that ability. The iommu is also possibly associated with multiple iommu
groups and I believe what is being asked for here is a way to hold and
lock a single iommu group with iommu protection.
>From a practical point of view, the iommu interface is de-privileged
once the groups are disconnected or closed. Holding a reference count
on the iommu fd won't prevent that. That means we'd have to use a
notifier to have KVM stop the side-channel iommu access. Meanwhile
holding the file descriptor for the group and adding an interface that
bumps use counter allows KVM to lock itself in, just as if it had a
device opened itself. Thanks,
Alex
^ permalink raw reply
* [PATCH 1/2] powerpc/hw_brk: Fix setting of length for exact mode breakpoints
From: Michael Neuling @ 2013-06-24 5:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Edjunior Barbosa Machado
The smallest match region for both the DABR and DAWR is 8 bytes, so the
kernel needs to filter matches when users want to look at regions smaller than
this.
Currently we set the length of PPC_BREAKPOINT_MODE_EXACT breakpoints to 8.
This is wrong as in exact mode we should only match on 1 address, hence the
length should be 1.
This ensures that the kernel will filter out any exact mode hardware breakpoint
matches on any addresses other than the requested one.
Signed-off-by: Michael Neuling <mikey@neuling.org>
Reported-by: Edjunior Barbosa Machado <emachado@linux.vnet.ibm.com>
Cc: stable@vger.kernel.org
---
arch/powerpc/kernel/ptrace.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 98c2fc1..64f7bd5 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1449,7 +1449,9 @@ static long ppc_set_hwdebug(struct task_struct *child,
*/
if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) {
len = bp_info->addr2 - bp_info->addr;
- } else if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) {
+ } else if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT)
+ len = 1;
+ else {
ptrace_put_breakpoints(child);
return -EINVAL;
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/2] powerpc/hw_brk: Fix clearing of extraneous IRQ
From: Michael Neuling @ 2013-06-24 5:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Edjunior Barbosa Machado
In-Reply-To: <1372052843-19109-1-git-send-email-mikey@neuling.org>
In 9422de3 "powerpc: Hardware breakpoints rewrite to handle non DABR breakpoint
registers" we changed the way we mark extraneous irqs with this:
- info->extraneous_interrupt = !((bp->attr.bp_addr <= dar) &&
- (dar - bp->attr.bp_addr < bp->attr.bp_len));
+ if (!((bp->attr.bp_addr <= dar) &&
+ (dar - bp->attr.bp_addr < bp->attr.bp_len)))
+ info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
Unfortunately this is bogus as it never clears extraneous IRQ if it's already
set.
This correctly clears extraneous IRQ before possibly setting it.
Signed-off-by: Michael Neuling <mikey@neuling.org>
Reported-by: Edjunior Barbosa Machado <emachado@linux.vnet.ibm.com>
Cc: stable@vger.kernel.org
---
arch/powerpc/kernel/hw_breakpoint.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index a949bdf..1150ae7 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -250,6 +250,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
* we still need to single-step the instruction, but we don't
* generate an event.
*/
+ info->type &= ~HW_BRK_TYPE_EXTRANEOUS_IRQ;
if (!((bp->attr.bp_addr <= dar) &&
(dar - bp->attr.bp_addr < bp->attr.bp_len)))
info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
--
1.7.10.4
^ permalink raw reply related
* [RESEND PATCH 0/3] Nvram-to-pstore: compression support for oops data
From: Aruna Balakrishnaiah @ 2013-06-24 6:22 UTC (permalink / raw)
To: linuxppc-dev, paulus, linux-kernel, benh
Cc: jkenisto, tony.luck, mahesh, cbouatmailru, anton, ccross,
keescook
The patchset takes care of compressing oops messages while writing to NVRAM,
so that more oops data can be captured in the given space.
big_oops_buf (2.22 * oops_data_sz) is allocated for compression.
oops_data_sz is oops header size less of oops partition size.
Pstore will internally call kmsg_dump to capture messages from printk
buffer. While returning the data to nvram it adds is own header.
For compression:
Register pstore with big_oops_buf.
In case compression fails, copy header added by pstore and
last oops_data_sz bytes (recent messages) of big_oops_buf to
nvram for which we need to know header size.
patch 01/03 will add a function in pstore to return the header size.
pstore read callback of nvram will read the compressed data and return the
decompressed data so that dmesg file (under /dev/pstore) is readable.
In case decompression fails, instead of having the compressed data (junk) in the
dmesg file it will skip and continue reading other partitions. This results in
absence of dmesg file but will still have files relating to other parititons.
---
Aruna Balakrishnaiah (3):
Retreive header size from pstore
powerpc/pseries: Re-organise the oops compression code
powerpc/pseries: Support compression of oops text via pstore
arch/powerpc/platforms/pseries/nvram.c | 236 +++++++++++++++++++++++---------
fs/pstore/platform.c | 7 +
include/linux/pstore.h | 6 +
3 files changed, 182 insertions(+), 67 deletions(-)
--
^ permalink raw reply
* [PATCH 1/3] Retreive header size from pstore
From: Aruna Balakrishnaiah @ 2013-06-24 6:22 UTC (permalink / raw)
To: linuxppc-dev, paulus, linux-kernel, benh
Cc: jkenisto, tony.luck, mahesh, cbouatmailru, anton, ccross,
keescook
In-Reply-To: <20130624061936.12963.72529.stgit@aruna-ThinkPad-T420>
pstore_get_header_size will return the size of the header added by pstore
while logging messages to the registered buffer.
Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
---
fs/pstore/platform.c | 7 ++++++-
include/linux/pstore.h | 6 ++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 86d1038..e8260ea 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -49,6 +49,7 @@ MODULE_PARM_DESC(update_ms, "milliseconds before pstore updates its content "
"corruption on Oopses)");
static int pstore_new_entry;
+static int hsize;
static void pstore_timefunc(unsigned long);
static DEFINE_TIMER(pstore_timer, pstore_timefunc, 0, 0);
@@ -68,6 +69,11 @@ static char *backend;
/* How much of the console log to snapshot */
static unsigned long kmsg_bytes = 10240;
+int pstore_get_header_size(void)
+{
+ return hsize;
+}
+
void pstore_set_kmsg_bytes(int bytes)
{
kmsg_bytes = bytes;
@@ -147,7 +153,6 @@ static void pstore_dump(struct kmsg_dumper *dumper,
while (total < kmsg_bytes) {
char *dst;
unsigned long size;
- int hsize;
size_t len;
dst = psinfo->buf;
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 656699f..f43b64f 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -73,6 +73,7 @@ struct pstore_info {
#ifdef CONFIG_PSTORE
extern int pstore_register(struct pstore_info *);
extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
+extern int pstore_get_header_size(void);
#else
static inline int
pstore_register(struct pstore_info *psi)
@@ -84,6 +85,11 @@ pstore_cannot_block_path(enum kmsg_dump_reason reason)
{
return false;
}
+static inline int
+pstore_get_header_size(void)
+{
+ return 0;
+}
#endif
#endif /*_LINUX_PSTORE_H*/
^ permalink raw reply related
* [PATCH 2/3] powerpc/pseries: Re-organise the oops compression code
From: Aruna Balakrishnaiah @ 2013-06-24 6:23 UTC (permalink / raw)
To: linuxppc-dev, paulus, linux-kernel, benh
Cc: jkenisto, tony.luck, mahesh, cbouatmailru, anton, ccross,
keescook
In-Reply-To: <20130624061936.12963.72529.stgit@aruna-ThinkPad-T420>
nvram_compress() and zip_oops() is used by the nvram_pstore_write
API to compress oops messages hence re-organise the functions
accordingly to avoid forward declarations.
Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
---
arch/powerpc/platforms/pseries/nvram.c | 104 ++++++++++++++++----------------
1 file changed, 52 insertions(+), 52 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 14cc486..0159d74 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -486,6 +486,58 @@ static int clobbering_unread_rtas_event(void)
NVRAM_RTAS_READ_TIMEOUT);
}
+/* Derived from logfs_compress() */
+static int nvram_compress(const void *in, void *out, size_t inlen,
+ size_t outlen)
+{
+ int err, ret;
+
+ ret = -EIO;
+ err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
+ MEM_LEVEL, Z_DEFAULT_STRATEGY);
+ if (err != Z_OK)
+ goto error;
+
+ stream.next_in = in;
+ stream.avail_in = inlen;
+ stream.total_in = 0;
+ stream.next_out = out;
+ stream.avail_out = outlen;
+ stream.total_out = 0;
+
+ err = zlib_deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END)
+ goto error;
+
+ err = zlib_deflateEnd(&stream);
+ if (err != Z_OK)
+ goto error;
+
+ if (stream.total_out >= stream.total_in)
+ goto error;
+
+ ret = stream.total_out;
+error:
+ return ret;
+}
+
+/* Compress the text from big_oops_buf into oops_buf. */
+static int zip_oops(size_t text_len)
+{
+ struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
+ int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
+ oops_data_sz);
+ if (zipped_len < 0) {
+ pr_err("nvram: compression failed; returned %d\n", zipped_len);
+ pr_err("nvram: logging uncompressed oops/panic report\n");
+ return -1;
+ }
+ oops_hdr->version = OOPS_HDR_VERSION;
+ oops_hdr->report_length = (u16) zipped_len;
+ oops_hdr->timestamp = get_seconds();
+ return 0;
+}
+
#ifdef CONFIG_PSTORE
static int nvram_pstore_open(struct pstore_info *psi)
{
@@ -757,58 +809,6 @@ int __init pSeries_nvram_init(void)
}
-/* Derived from logfs_compress() */
-static int nvram_compress(const void *in, void *out, size_t inlen,
- size_t outlen)
-{
- int err, ret;
-
- ret = -EIO;
- err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
- MEM_LEVEL, Z_DEFAULT_STRATEGY);
- if (err != Z_OK)
- goto error;
-
- stream.next_in = in;
- stream.avail_in = inlen;
- stream.total_in = 0;
- stream.next_out = out;
- stream.avail_out = outlen;
- stream.total_out = 0;
-
- err = zlib_deflate(&stream, Z_FINISH);
- if (err != Z_STREAM_END)
- goto error;
-
- err = zlib_deflateEnd(&stream);
- if (err != Z_OK)
- goto error;
-
- if (stream.total_out >= stream.total_in)
- goto error;
-
- ret = stream.total_out;
-error:
- return ret;
-}
-
-/* Compress the text from big_oops_buf into oops_buf. */
-static int zip_oops(size_t text_len)
-{
- struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
- int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
- oops_data_sz);
- if (zipped_len < 0) {
- pr_err("nvram: compression failed; returned %d\n", zipped_len);
- pr_err("nvram: logging uncompressed oops/panic report\n");
- return -1;
- }
- oops_hdr->version = OOPS_HDR_VERSION;
- oops_hdr->report_length = (u16) zipped_len;
- oops_hdr->timestamp = get_seconds();
- return 0;
-}
-
/*
* This is our kmsg_dump callback, called after an oops or panic report
* has been written to the printk buffer. We want to capture as much
^ permalink raw reply related
* [PATCH 3/3] powerpc/pseries: Support compression of oops text via pstore
From: Aruna Balakrishnaiah @ 2013-06-24 6:23 UTC (permalink / raw)
To: linuxppc-dev, paulus, linux-kernel, benh
Cc: jkenisto, tony.luck, mahesh, cbouatmailru, anton, ccross,
keescook
In-Reply-To: <20130624061936.12963.72529.stgit@aruna-ThinkPad-T420>
The patch set supports compression of oops messages while writing to NVRAM,
this helps in capturing more of oops data to lnx,oops-log. The pstore file
for oops messages will be in decompressed format making it readable.
In case compression fails, the patch takes care of copying the header added
by pstore and last oops_data_sz bytes of big_oops_buf to NVRAM so that we
have recent oops messages in lnx,oops-log.
In case decompression fails, it will result in absence of oops file but still
have files (in /dev/pstore) for other partitions.
Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
---
arch/powerpc/platforms/pseries/nvram.c | 132 +++++++++++++++++++++++++++++---
1 file changed, 118 insertions(+), 14 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 0159d74..b5ba5e2 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -539,6 +539,65 @@ static int zip_oops(size_t text_len)
}
#ifdef CONFIG_PSTORE
+/* Derived from logfs_uncompress */
+int nvram_decompress(void *in, void *out, size_t inlen, size_t outlen)
+{
+ int err, ret;
+
+ ret = -EIO;
+ err = zlib_inflateInit(&stream);
+ if (err != Z_OK)
+ goto error;
+
+ stream.next_in = in;
+ stream.avail_in = inlen;
+ stream.total_in = 0;
+ stream.next_out = out;
+ stream.avail_out = outlen;
+ stream.total_out = 0;
+
+ err = zlib_inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END)
+ goto error;
+
+ err = zlib_inflateEnd(&stream);
+ if (err != Z_OK)
+ goto error;
+
+ ret = stream.total_out;
+error:
+ return ret;
+}
+
+static int unzip_oops(char *oops_buf, char *big_buf)
+{
+ struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
+ u64 timestamp = oops_hdr->timestamp;
+ char *big_oops_data = NULL;
+ char *oops_data_buf = NULL;
+ size_t big_oops_data_sz;
+ int unzipped_len;
+
+ big_oops_data = big_buf + sizeof(struct oops_log_info);
+ big_oops_data_sz = big_oops_buf_sz - sizeof(struct oops_log_info);
+ oops_data_buf = oops_buf + sizeof(struct oops_log_info);
+
+ unzipped_len = nvram_decompress(oops_data_buf, big_oops_data,
+ oops_hdr->report_length,
+ big_oops_data_sz);
+
+ if (unzipped_len < 0) {
+ pr_err("nvram: decompression failed; returned %d\n",
+ unzipped_len);
+ return -1;
+ }
+ oops_hdr = (struct oops_log_info *)big_buf;
+ oops_hdr->version = OOPS_HDR_VERSION;
+ oops_hdr->report_length = (u16) unzipped_len;
+ oops_hdr->timestamp = timestamp;
+ return 0;
+}
+
static int nvram_pstore_open(struct pstore_info *psi)
{
/* Reset the iterator to start reading partitions again */
@@ -567,6 +626,7 @@ static int nvram_pstore_write(enum pstore_type_id type,
size_t size, struct pstore_info *psi)
{
int rc;
+ unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
/* part 1 has the recent messages from printk buffer */
@@ -577,8 +637,31 @@ static int nvram_pstore_write(enum pstore_type_id type,
oops_hdr->version = OOPS_HDR_VERSION;
oops_hdr->report_length = (u16) size;
oops_hdr->timestamp = get_seconds();
+
+ if (big_oops_buf) {
+ rc = zip_oops(size);
+ /*
+ * If compression fails copy recent log messages from
+ * big_oops_buf to oops_data.
+ */
+ if (rc != 0) {
+ int hsize = pstore_get_header_size();
+ size_t diff = size - oops_data_sz + hsize;
+
+ if (size > oops_data_sz) {
+ memcpy(oops_data, big_oops_buf, hsize);
+ memcpy(oops_data + hsize, big_oops_buf + diff,
+ oops_data_sz - hsize);
+
+ oops_hdr->report_length = (u16) oops_data_sz;
+ } else
+ memcpy(oops_data, big_oops_buf, size);
+ } else
+ err_type = ERR_TYPE_KERNEL_PANIC_GZ;
+ }
+
rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
- (int) (sizeof(*oops_hdr) + size), ERR_TYPE_KERNEL_PANIC,
+ (int) (sizeof(*oops_hdr) + oops_hdr->report_length), err_type,
count);
if (rc != 0)
@@ -600,10 +683,11 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
struct oops_log_info *oops_hdr;
unsigned int err_type, id_no, size = 0;
struct nvram_os_partition *part = NULL;
- char *buff = NULL;
- int sig = 0;
+ char *buff = NULL, *big_buff = NULL;
+ int rc, sig = 0;
loff_t p;
+read_partition:
read_type++;
switch (nvram_type_ids[read_type]) {
@@ -666,6 +750,25 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
oops_hdr = (struct oops_log_info *)buff;
*buf = buff + sizeof(*oops_hdr);
+
+ if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) {
+ big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL);
+ if (!big_buff)
+ return -ENOMEM;
+
+ rc = unzip_oops(buff, big_buff);
+
+ if (rc != 0) {
+ kfree(buff);
+ kfree(big_buff);
+ goto read_partition;
+ }
+
+ oops_hdr = (struct oops_log_info *)big_buff;
+ *buf = big_buff + sizeof(*oops_hdr);
+ kfree(buff);
+ }
+
time->tv_sec = oops_hdr->timestamp;
time->tv_nsec = 0;
return oops_hdr->report_length;
@@ -687,17 +790,18 @@ static int nvram_pstore_init(void)
{
int rc = 0;
- nvram_pstore_info.buf = oops_data;
- nvram_pstore_info.bufsize = oops_data_sz;
+ if (big_oops_buf) {
+ nvram_pstore_info.buf = big_oops_buf;
+ nvram_pstore_info.bufsize = big_oops_buf_sz;
+ } else {
+ nvram_pstore_info.buf = oops_data;
+ nvram_pstore_info.bufsize = oops_data_sz;
+ }
rc = pstore_register(&nvram_pstore_info);
if (rc != 0)
pr_err("nvram: pstore_register() failed, defaults to "
"kmsg_dump; returned %d\n", rc);
- else
- /*TODO: Support compression when pstore is configured */
- pr_info("nvram: Compression of oops text supported only when "
- "pstore is not configured");
return rc;
}
@@ -731,11 +835,6 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
oops_data = oops_buf + sizeof(struct oops_log_info);
oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
- rc = nvram_pstore_init();
-
- if (!rc)
- return;
-
/*
* Figure compression (preceded by elimination of each line's <n>
* severity prefix) will reduce the oops/panic report to at most
@@ -759,6 +858,11 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
stream.workspace = NULL;
}
+ rc = nvram_pstore_init();
+
+ if (!rc)
+ return;
+
rc = kmsg_dump_register(&nvram_kmsg_dumper);
if (rc != 0) {
pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
^ permalink raw reply related
* [PATCH v2] powerpc/pseries: Enable PSTORE in pseries_defconfig
From: Aruna Balakrishnaiah @ 2013-06-24 6:38 UTC (permalink / raw)
To: linuxppc-dev, mikey, linux-kernel, benh; +Cc: mahesh
Since now we have pstore support for nvram in pseries, enable it
in the default config. With this config option enabled, pstore
infra-structure will be used to read/write the messages from/to nvram.
Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
---
arch/powerpc/configs/pseries_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index c4dfbaf..9630a50 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -347,3 +347,4 @@ CONFIG_VIRTUALIZATION=y
CONFIG_KVM_BOOK3S_64=m
CONFIG_KVM_BOOK3S_64_HV=y
CONFIG_VHOST_NET=m
+CONFIG_PSTORE=y
^ permalink raw reply related
* Re: [PATCH] powerpc/pseries: Enable PSTORE in pseries_defconfig
From: Aruna Balakrishnaiah @ 2013-06-24 6:43 UTC (permalink / raw)
To: Michael Neuling; +Cc: mahesh, linux-kernel, linuxppc-dev
In-Reply-To: <7684.1372036896@ale.ozlabs.ibm.com>
Hi Michael,
On Monday 24 June 2013 06:51 AM, Michael Neuling wrote:
>> Enable PSTORE in pseries_defconfig
> Please add a "why" to your changelogs eg. "Now we have pstore support for
> nvram on pseries, enable it in the default config"
>
> "Why" you are changing something is more important than "what", since
> you can always determine "what" is being changed, by looking at the diff.
> The "why" will be long forgotten.
>
>> Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
>> ---
>> arch/powerpc/configs/pseries_defconfig | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
>> index c4dfbaf..9630a50 100644
>> --- a/arch/powerpc/configs/pseries_defconfig
>> +++ b/arch/powerpc/configs/pseries_defconfig
>> @@ -347,3 +347,4 @@ CONFIG_VIRTUALIZATION=y
>> CONFIG_KVM_BOOK3S_64=m
>> CONFIG_KVM_BOOK3S_64_HV=y
>> CONFIG_VHOST_NET=m
>> +CONFIG_PSTORE=y
> This should really be added in the right location on the config, not
> just at the end. ie.
Sorry, I overlooked this commentin my v2 patch. Will resend.
> @@ -296,6 +293,7 @@
> CONFIG_SQUASHFS_XATTR=y
> CONFIG_SQUASHFS_LZO=y
> CONFIG_SQUASHFS_XZ=y
> +CONFIG_PSTORE=y
> CONFIG_NFS_FS=y
> CONFIG_NFS_V3_ACL=y
> CONFIG_NFS_V4=y
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
^ permalink raw reply
* Re: [PATCH 33/45] cris/smp: Use get/put_online_cpus_atomic() to prevent CPU offline
From: Jesper Nilsson @ 2013-06-24 6:41 UTC (permalink / raw)
To: Srivatsa S. Bhat
Cc: peterz, fweisbec, linux-kernel, walken, mingo, linux-arch,
vincent.guittot, linux-cris-kernel, xiaoguangrong, wangyun,
paulmck, nikunj, linux-pm, rusty, rostedt, Jesper Nilsson,
Mikael Starvik, namhyung, tglx, laijs, zhong, netdev, oleg, sbw,
tj, akpm, linuxppc-dev
In-Reply-To: <20130623134536.19094.52797.stgit@srivatsabhat.in.ibm.com>
On Sun, Jun 23, 2013 at 07:15:39PM +0530, Srivatsa S. Bhat wrote:
> Once stop_machine() is gone from the CPU offline path, we won't be able
> to depend on disabling preemption to prevent CPUs from going offline
> from under us.
>
> Use the get/put_online_cpus_atomic() APIs to prevent CPUs from going
> offline, while invoking from atomic context.
>
> Cc: Mikael Starvik <starvik@axis.com>
Acked-by: Jesper Nilsson <jesper.nilsson@axis.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: linux-cris-kernel@axis.com
> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
> ---
>
> arch/cris/arch-v32/kernel/smp.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
> index cdd1202..b2d4612 100644
> --- a/arch/cris/arch-v32/kernel/smp.c
> +++ b/arch/cris/arch-v32/kernel/smp.c
> @@ -13,6 +13,7 @@
> #include <linux/init.h>
> #include <linux/timex.h>
> #include <linux/sched.h>
> +#include <linux/cpu.h>
> #include <linux/kernel.h>
> #include <linux/cpumask.h>
> #include <linux/interrupt.h>
> @@ -222,6 +223,7 @@ void flush_tlb_common(struct mm_struct* mm, struct vm_area_struct* vma, unsigned
> unsigned long flags;
> cpumask_t cpu_mask;
>
> + get_online_cpus_atomic();
> spin_lock_irqsave(&tlbstate_lock, flags);
> cpu_mask = (mm == FLUSH_ALL ? cpu_all_mask : *mm_cpumask(mm));
> cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
> @@ -230,6 +232,7 @@ void flush_tlb_common(struct mm_struct* mm, struct vm_area_struct* vma, unsigned
> flush_addr = addr;
> send_ipi(IPI_FLUSH_TLB, 1, cpu_mask);
> spin_unlock_irqrestore(&tlbstate_lock, flags);
> + put_online_cpus_atomic();
> }
>
> void flush_tlb_all(void)
> @@ -319,10 +322,12 @@ int smp_call_function(void (*func)(void *info), void *info, int wait)
> data.info = info;
> data.wait = wait;
>
> + get_online_cpus_atomic();
> spin_lock(&call_lock);
> call_data = &data;
> ret = send_ipi(IPI_CALL, wait, cpu_mask);
> spin_unlock(&call_lock);
> + put_online_cpus_atomic();
>
> return ret;
> }
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
/^JN - Jesper Nilsson
--
Jesper Nilsson -- jesper.nilsson@axis.com
^ permalink raw reply
* [PATCH v3] powerpc/pseries: Enable PSTORE in pseries_defconfig
From: Aruna Balakrishnaiah @ 2013-06-24 6:53 UTC (permalink / raw)
To: linuxppc-dev, mikey, linux-kernel, benh; +Cc: mahesh
Since now we have pstore support for nvram in pseries, enable it
in the default config. With this config option enabled, pstore
infra-structure will be used to read/write the messages from/to nvram.
Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
---
v3:
Move pstore config to right place
v2:
Change patch description
arch/powerpc/configs/pseries_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index c4dfbaf..bea8587 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -296,6 +296,7 @@ CONFIG_SQUASHFS=m
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_LZO=y
CONFIG_SQUASHFS_XZ=y
+CONFIG_PSTORE=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
^ permalink raw reply related
* Re: [PATCH v3] powerpc/pseries: Enable PSTORE in pseries_defconfig
From: Michael Neuling @ 2013-06-24 7:13 UTC (permalink / raw)
To: Aruna Balakrishnaiah; +Cc: mahesh, linuxppc-dev, linux-kernel
In-Reply-To: <20130624064534.16842.3582.stgit@aruna-ThinkPad-T420>
Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com> wrote:
> Since now we have pstore support for nvram in pseries, enable it
> in the default config. With this config option enabled, pstore
> infra-structure will be used to read/write the messages from/to nvram.
>
> Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
Acked-by: Michael Neuling <mikey@neuling.org>
> ---
> v3:
> Move pstore config to right place
> v2:
> Change patch description
>
> arch/powerpc/configs/pseries_defconfig | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
> index c4dfbaf..bea8587 100644
> --- a/arch/powerpc/configs/pseries_defconfig
> +++ b/arch/powerpc/configs/pseries_defconfig
> @@ -296,6 +296,7 @@ CONFIG_SQUASHFS=m
> CONFIG_SQUASHFS_XATTR=y
> CONFIG_SQUASHFS_LZO=y
> CONFIG_SQUASHFS_XZ=y
> +CONFIG_PSTORE=y
> CONFIG_NFS_FS=y
> CONFIG_NFS_V3_ACL=y
> CONFIG_NFS_V4=y
>
^ permalink raw reply
* Re: [PATCH V3 1/2] powerpc, perf: Ignore separate BHRB privilege state filter request
From: Michael Neuling @ 2013-06-24 7:19 UTC (permalink / raw)
To: Anshuman Khandual; +Cc: linuxppc-dev
In-Reply-To: <1370843609-32618-2-git-send-email-khandual@linux.vnet.ibm.com>
Anshuman Khandual <khandual@linux.vnet.ibm.com> wrote:
> Completely ignore BHRB privilege state filter request as we are
> already configuring that with privilege state filtering attribute
> for the accompanying PMU event. This would help achieve cleaner
> user space interaction for BHRB.
>
> This patch fixes a situation like this
>
> Before patch:-
> ------------
> ./perf record -j any -e branch-misses:k ls
> Error:
> The sys_perf_event_open() syscall returned with 95 (Operation not
> supported) for event (branch-misses:k).
> /bin/dmesg may provide additional information.
> No CONFIG_PERF_EVENTS=y kernel support configured?
>
> Here 'perf record' actually copies over ':k' filter request into BHRB
> privilege state filter config and our previous check in kernel would
> fail that.
>
> After patch:-
> -------------
> ./perf record -j any -e branch-misses:k ls
> perf perf.data perf.data.old test-mmap-ring
> [ perf record: Woken up 1 times to write data ]
> [ perf record: Captured and wrote 0.002 MB perf.data (~102 samples)]
>
> Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Acked-by: Michael Neuling <mikey@neuling.org>
> ---
> arch/powerpc/perf/power8-pmu.c | 13 ++++---------
> 1 file changed, 4 insertions(+), 9 deletions(-)
>
> diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
> index f7d1c4f..371c6e7 100644
> --- a/arch/powerpc/perf/power8-pmu.c
> +++ b/arch/powerpc/perf/power8-pmu.c
> @@ -523,18 +523,13 @@ static int power8_generic_events[] = {
> static u64 power8_bhrb_filter_map(u64 branch_sample_type)
> {
> u64 pmu_bhrb_filter = 0;
> - u64 br_privilege = branch_sample_type & ONLY_PLM;
>
> - /* BHRB and regular PMU events share the same prvillege state
> + /* BHRB and regular PMU events share the same privilege state
> * filter configuration. BHRB is always recorded along with a
> - * regular PMU event. So privilege state filter criteria for BHRB
> - * and the companion PMU events has to be the same. As a default
> - * "perf record" tool sets all privillege bits ON when no filter
> - * criteria is provided in the command line. So as along as all
> - * privillege bits are ON or they are OFF, we are good to go.
> + * regular PMU event. As the privilege state filter is handled
> + * in the basic PMC configuration of the accompanying regular
> + * PMU event, we ignore any separate BHRB specific request.
> */
> - if ((br_privilege != 7) && (br_privilege != 0))
> - return -1;
>
> /* No branch filter requested */
> if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY)
> --
> 1.7.11.7
>
^ permalink raw reply
* Re: [PATCH V3 2/2] powerpc, perf: BHRB filter configuration should follow the task
From: Michael Neuling @ 2013-06-24 7:20 UTC (permalink / raw)
To: Anshuman Khandual; +Cc: linuxppc-dev
In-Reply-To: <1370843609-32618-3-git-send-email-khandual@linux.vnet.ibm.com>
Anshuman Khandual <khandual@linux.vnet.ibm.com> wrote:
> When the task moves around the system, the corresponding cpuhw
> per cpu strcuture should be popullated with the BHRB filter
> request value so that PMU could be configured appropriately with
> that during the next call into power_pmu_enable().
>
> Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
benh you might want to fix the spelling mistakes above
strcuture -> structure
popullated -> populated
Otherwise:
Acked-by: Michael Neuling <mikey@neuling.org>
> ---
> arch/powerpc/perf/core-book3s.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
> index 426180b..48c68a8 100644
> --- a/arch/powerpc/perf/core-book3s.c
> +++ b/arch/powerpc/perf/core-book3s.c
> @@ -1122,8 +1122,11 @@ nocheck:
>
> ret = 0;
> out:
> - if (has_branch_stack(event))
> + if (has_branch_stack(event)) {
> power_pmu_bhrb_enable(event);
> + cpuhw->bhrb_filter = ppmu->bhrb_filter_map(
> + event->attr.branch_sample_type);
> + }
>
> perf_pmu_enable(event->pmu);
> local_irq_restore(flags);
> --
> 1.7.11.7
>
^ permalink raw reply
* [RFC PATCH 3/3] powerpc: Contiguous memory allocator based RMA allocation
From: Aneesh Kumar K.V @ 2013-06-24 8:25 UTC (permalink / raw)
To: linux-mm, benh, paulus; +Cc: linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <1372062327-7028-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Use CMA for allocation of RMA region for guest. Also remove linear allocator
now that it is not used
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/kvm_book3s_64.h | 1 +
arch/powerpc/include/asm/kvm_host.h | 12 +--
arch/powerpc/include/asm/kvm_ppc.h | 8 +-
arch/powerpc/kernel/setup_64.c | 2 -
arch/powerpc/kvm/book3s_hv.c | 44 ++++++---
arch/powerpc/kvm/book3s_hv_builtin.c | 164 +++++++------------------------
6 files changed, 71 insertions(+), 160 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index f8355a9..76ff0b5 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -37,6 +37,7 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu)
#ifdef CONFIG_KVM_BOOK3S_64_HV
#define KVM_DEFAULT_HPT_ORDER 24 /* 16MB HPT by default */
+extern unsigned long kvm_rma_pages;
#endif
#define VRMA_VSID 0x1ffffffUL /* 1TB VSID reserved for VRMA */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 0097dab..525684c 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -183,13 +183,9 @@ struct kvmppc_spapr_tce_table {
struct page *pages[0];
};
-struct kvmppc_linear_info {
- void *base_virt;
- unsigned long base_pfn;
- unsigned long npages;
- struct list_head list;
- atomic_t use_count;
- int type;
+struct kvm_rma_info {
+ atomic_t use_count;
+ unsigned long base_pfn;
};
/* XICS components, defined in book3s_xics.c */
@@ -246,7 +242,7 @@ struct kvm_arch {
int tlbie_lock;
unsigned long lpcr;
unsigned long rmor;
- struct kvmppc_linear_info *rma;
+ struct kvm_rma_info *ri;
unsigned long vrma_slb_v;
int rma_setup_done;
int using_mmu_notifiers;
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 058ac93..7a09cf5 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -137,8 +137,8 @@ extern long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
unsigned long ioba, unsigned long tce);
extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm,
struct kvm_allocate_rma *rma);
-extern struct kvmppc_linear_info *kvm_alloc_rma(void);
-extern void kvm_release_rma(struct kvmppc_linear_info *ri);
+extern struct kvm_rma_info *kvm_alloc_rma(void);
+extern void kvm_release_rma(struct kvm_rma_info *ri);
extern struct page *kvm_alloc_hpt(int nr_pages);
extern void kvm_release_hpt(struct page *page, int nr_pages);
extern int kvmppc_core_init_vm(struct kvm *kvm);
@@ -282,7 +282,6 @@ static inline void kvmppc_set_host_ipi(int cpu, u8 host_ipi)
}
extern void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu);
-extern void kvm_linear_init(void);
#else
static inline void __init kvm_cma_reserve(void)
@@ -291,9 +290,6 @@ static inline void __init kvm_cma_reserve(void)
static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
{}
-static inline void kvm_linear_init(void)
-{}
-
static inline u32 kvmppc_get_xics_latch(void)
{
return 0;
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index ee28d1f..8a022f5 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -611,8 +611,6 @@ void __init setup_arch(char **cmdline_p)
/* Initialize the MMU context management stuff */
mmu_context_init();
- kvm_linear_init();
-
/* Interrupt code needs to be 64K-aligned */
if ((unsigned long)_stext & 0xffff)
panic("Kernelbase not 64K-aligned (0x%lx)!\n",
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 550f592..0f0d05e 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1511,10 +1511,10 @@ static inline int lpcr_rmls(unsigned long rma_size)
static int kvm_rma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
- struct kvmppc_linear_info *ri = vma->vm_file->private_data;
struct page *page;
+ struct kvm_rma_info *ri = vma->vm_file->private_data;
- if (vmf->pgoff >= ri->npages)
+ if (vmf->pgoff >= kvm_rma_pages)
return VM_FAULT_SIGBUS;
page = pfn_to_page(ri->base_pfn + vmf->pgoff);
@@ -1536,7 +1536,7 @@ static int kvm_rma_mmap(struct file *file, struct vm_area_struct *vma)
static int kvm_rma_release(struct inode *inode, struct file *filp)
{
- struct kvmppc_linear_info *ri = filp->private_data;
+ struct kvm_rma_info *ri = filp->private_data;
kvm_release_rma(ri);
return 0;
@@ -1549,8 +1549,24 @@ static const struct file_operations kvm_rma_fops = {
long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, struct kvm_allocate_rma *ret)
{
- struct kvmppc_linear_info *ri;
long fd;
+ struct kvm_rma_info *ri;
+ /*
+ * Only do this on PPC970 in HV mode
+ */
+ if (!cpu_has_feature(CPU_FTR_HVMODE) ||
+ !cpu_has_feature(CPU_FTR_ARCH_201))
+ return -EINVAL;
+
+ if (!kvm_rma_pages)
+ return -EINVAL;
+ /*
+ * Check that the requested size is one supported in hardware
+ */
+ if (lpcr_rmls(kvm_rma_pages << PAGE_SHIFT) < 0) {
+ pr_err("RMA pages of %lu not supported\n", kvm_rma_pages);
+ return -EINVAL;
+ }
ri = kvm_alloc_rma();
if (!ri)
@@ -1560,7 +1576,7 @@ long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, struct kvm_allocate_rma *ret)
if (fd < 0)
kvm_release_rma(ri);
- ret->rma_size = ri->npages << PAGE_SHIFT;
+ ret->rma_size = kvm_rma_pages << PAGE_SHIFT;
return fd;
}
@@ -1725,7 +1741,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
{
int err = 0;
struct kvm *kvm = vcpu->kvm;
- struct kvmppc_linear_info *ri = NULL;
+ struct kvm_rma_info *ri = NULL;
unsigned long hva;
struct kvm_memory_slot *memslot;
struct vm_area_struct *vma;
@@ -1803,7 +1819,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
} else {
/* Set up to use an RMO region */
- rma_size = ri->npages;
+ rma_size = kvm_rma_pages;
if (rma_size > memslot->npages)
rma_size = memslot->npages;
rma_size <<= PAGE_SHIFT;
@@ -1814,7 +1830,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
goto out_srcu;
}
atomic_inc(&ri->use_count);
- kvm->arch.rma = ri;
+ kvm->arch.ri = ri;
/* Update LPCR and RMOR */
lpcr = kvm->arch.lpcr;
@@ -1831,14 +1847,14 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
/* POWER7 */
lpcr &= ~(LPCR_VPM0 | LPCR_VRMA_L);
lpcr |= rmls << LPCR_RMLS_SH;
- kvm->arch.rmor = kvm->arch.rma->base_pfn << PAGE_SHIFT;
+ kvm->arch.rmor = ri->base_pfn << PAGE_SHIFT;
}
kvm->arch.lpcr = lpcr;
pr_info("KVM: Using RMO at %lx size %lx (LPCR = %lx)\n",
ri->base_pfn << PAGE_SHIFT, rma_size, lpcr);
/* Initialize phys addrs of pages in RMO */
- npages = ri->npages;
+ npages = kvm_rma_pages;
porder = __ilog2(npages);
physp = memslot->arch.slot_phys;
if (physp) {
@@ -1888,7 +1904,7 @@ int kvmppc_core_init_vm(struct kvm *kvm)
INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
INIT_LIST_HEAD(&kvm->arch.rtas_tokens);
- kvm->arch.rma = NULL;
+ kvm->arch.ri = NULL;
kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
@@ -1927,9 +1943,9 @@ void kvmppc_core_destroy_vm(struct kvm *kvm)
{
uninhibit_secondary_onlining();
- if (kvm->arch.rma) {
- kvm_release_rma(kvm->arch.rma);
- kvm->arch.rma = NULL;
+ if (kvm->arch.ri) {
+ kvm_release_rma(kvm->arch.ri);
+ kvm->arch.ri = NULL;
}
kvmppc_rtas_tokens_free(kvm);
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index cf8e25a..b33d3a0 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -21,13 +21,6 @@
#include <asm/kvm_book3s.h>
#include "book3s_hv_cma.h"
-
-#define KVM_LINEAR_RMA 0
-#define KVM_LINEAR_HPT 1
-
-static void __init kvm_linear_init_one(ulong size, int count, int type);
-static struct kvmppc_linear_info *kvm_alloc_linear(int type);
-static void kvm_release_linear(struct kvmppc_linear_info *ri);
/*
* should be power of 2
*/
@@ -36,19 +29,17 @@ static unsigned long hpt_align_pages = (1 << 18) >> PAGE_SHIFT; /* 256k */
* By default we reserve 5% of memory for hash pagetable allocation.
*/
static unsigned long kvm_cma_resv_ratio = 5;
-
-/*************** RMA *************/
-
/*
- * This maintains a list of RMAs (real mode areas) for KVM guests to use.
+ * We allocate RMAs (real mode areas) for KVM guests from the KVM CMA area.
* Each RMA has to be physically contiguous and of a size that the
* hardware supports. PPC970 and POWER7 support 64MB, 128MB and 256MB,
* and other larger sizes. Since we are unlikely to be allocate that
* much physically contiguous memory after the system is up and running,
- * we preallocate a set of RMAs in early boot for KVM to use.
+ * we preallocate a set of RMAs in early boot using CMA.
+ * should be power of 2.
*/
-static unsigned long kvm_rma_size = 64 << 20; /* 64MB */
-static unsigned long kvm_rma_count;
+unsigned long kvm_rma_pages = (1 << 26) >> PAGE_SHIFT; /* 64MB */
+EXPORT_SYMBOL_GPL(kvm_rma_pages);
/* Work out RMLS (real mode limit selector) field value for a given RMA size.
Assumes POWER7 or PPC970. */
@@ -78,35 +69,44 @@ static inline int lpcr_rmls(unsigned long rma_size)
static int __init early_parse_rma_size(char *p)
{
- if (!p)
- return 1;
+ unsigned long kvm_rma_size;
+ pr_debug("%s(%s)\n", __func__, p);
+ if (!p)
+ return -EINVAL;
kvm_rma_size = memparse(p, &p);
-
+ kvm_rma_pages = kvm_rma_size >> PAGE_SHIFT;
return 0;
}
early_param("kvm_rma_size", early_parse_rma_size);
-static int __init early_parse_rma_count(char *p)
-{
- if (!p)
- return 1;
-
- kvm_rma_count = simple_strtoul(p, NULL, 0);
-
- return 0;
-}
-early_param("kvm_rma_count", early_parse_rma_count);
-
-struct kvmppc_linear_info *kvm_alloc_rma(void)
+struct kvm_rma_info *kvm_alloc_rma()
{
- return kvm_alloc_linear(KVM_LINEAR_RMA);
+ struct page *page;
+ struct kvm_rma_info *ri;
+
+ ri = kmalloc(sizeof(struct kvm_rma_info), GFP_KERNEL);
+ if (!ri)
+ return NULL;
+ page = kvm_alloc_cma(kvm_rma_pages,
+ get_order(kvm_rma_pages << PAGE_SHIFT));
+ if (!page)
+ goto err_out;
+ atomic_set(&ri->use_count, 1);
+ ri->base_pfn = page_to_pfn(page);
+ return ri;
+err_out:
+ kfree(ri);
+ return NULL;
}
EXPORT_SYMBOL_GPL(kvm_alloc_rma);
-void kvm_release_rma(struct kvmppc_linear_info *ri)
+void kvm_release_rma(struct kvm_rma_info *ri)
{
- kvm_release_linear(ri);
+ if (atomic_dec_and_test(&ri->use_count)) {
+ kvm_release_cma(pfn_to_page(ri->base_pfn), kvm_rma_pages);
+ kfree(ri);
+ }
}
EXPORT_SYMBOL_GPL(kvm_release_rma);
@@ -121,8 +121,7 @@ early_param("kvm_cma_resv_ratio", early_parse_kvm_cma_resv);
struct page *kvm_alloc_hpt(int nr_pages)
{
- return kvm_alloc_cma(nr_pages,
- get_order(hpt_align_pages << PAGE_SHIFT));
+ return kvm_alloc_cma(nr_pages, get_order(hpt_align_pages << PAGE_SHIFT));
}
EXPORT_SYMBOL_GPL(kvm_alloc_hpt);
@@ -132,101 +131,6 @@ void kvm_release_hpt(struct page *page, int nr_pages)
}
EXPORT_SYMBOL_GPL(kvm_release_hpt);
-/*************** generic *************/
-
-static LIST_HEAD(free_linears);
-static DEFINE_SPINLOCK(linear_lock);
-
-static void __init kvm_linear_init_one(ulong size, int count, int type)
-{
- unsigned long i;
- unsigned long j, npages;
- void *linear;
- struct page *pg;
- const char *typestr;
- struct kvmppc_linear_info *linear_info;
-
- if (!count)
- return;
-
- typestr = (type == KVM_LINEAR_RMA) ? "RMA" : "HPT";
-
- npages = size >> PAGE_SHIFT;
- linear_info = alloc_bootmem(count * sizeof(struct kvmppc_linear_info));
- for (i = 0; i < count; ++i) {
- linear = alloc_bootmem_align(size, size);
- pr_debug("Allocated KVM %s at %p (%ld MB)\n", typestr, linear,
- size >> 20);
- linear_info[i].base_virt = linear;
- linear_info[i].base_pfn = __pa(linear) >> PAGE_SHIFT;
- linear_info[i].npages = npages;
- linear_info[i].type = type;
- list_add_tail(&linear_info[i].list, &free_linears);
- atomic_set(&linear_info[i].use_count, 0);
-
- pg = pfn_to_page(linear_info[i].base_pfn);
- for (j = 0; j < npages; ++j) {
- atomic_inc(&pg->_count);
- ++pg;
- }
- }
-}
-
-static struct kvmppc_linear_info *kvm_alloc_linear(int type)
-{
- struct kvmppc_linear_info *ri, *ret;
-
- ret = NULL;
- spin_lock(&linear_lock);
- list_for_each_entry(ri, &free_linears, list) {
- if (ri->type != type)
- continue;
-
- list_del(&ri->list);
- atomic_inc(&ri->use_count);
- memset(ri->base_virt, 0, ri->npages << PAGE_SHIFT);
- ret = ri;
- break;
- }
- spin_unlock(&linear_lock);
- return ret;
-}
-
-static void kvm_release_linear(struct kvmppc_linear_info *ri)
-{
- if (atomic_dec_and_test(&ri->use_count)) {
- spin_lock(&linear_lock);
- list_add_tail(&ri->list, &free_linears);
- spin_unlock(&linear_lock);
-
- }
-}
-
-/*
- * Called at boot time while the bootmem allocator is active,
- * to allocate contiguous physical memory for the hash page
- * tables for guests.
- */
-void __init kvm_linear_init(void)
-{
- /* RMA */
- /* Only do this on PPC970 in HV mode */
- if (!cpu_has_feature(CPU_FTR_HVMODE) ||
- !cpu_has_feature(CPU_FTR_ARCH_201))
- return;
-
- if (!kvm_rma_size || !kvm_rma_count)
- return;
-
- /* Check that the requested size is one supported in hardware */
- if (lpcr_rmls(kvm_rma_size) < 0) {
- pr_err("RMA size of 0x%lx not supported\n", kvm_rma_size);
- return;
- }
-
- kvm_linear_init_one(kvm_rma_size, kvm_rma_count, KVM_LINEAR_RMA);
-}
-
/**
* kvm_cma_reserve() - reserve area for kvm hash pagetable
*
@@ -252,7 +156,7 @@ void __init kvm_cma_reserve(void)
if (selected_size) {
pr_debug("%s: reserving %ld MiB for global area\n", __func__,
(unsigned long)selected_size / SZ_1M);
- align_size = hpt_align_pages << PAGE_SHIFT;
+ align_size = max(kvm_rma_pages, hpt_align_pages) << PAGE_SHIFT;
kvm_cma_declare_contiguous(selected_size, align_size);
}
}
--
1.8.1.2
^ permalink raw reply related
* [RFC PATCH 2/3] powerpc: Contiguous memory allocator based hash page allocation
From: Aneesh Kumar K.V @ 2013-06-24 8:25 UTC (permalink / raw)
To: linux-mm, benh, paulus; +Cc: linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <1372062327-7028-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Use CMA for allocation of guest hash page.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/kvm_book3s_64.h | 1 -
arch/powerpc/include/asm/kvm_host.h | 2 +-
arch/powerpc/include/asm/kvm_ppc.h | 8 +-
arch/powerpc/kernel/setup_64.c | 2 +
arch/powerpc/kvm/Kconfig | 1 +
arch/powerpc/kvm/Makefile | 3 +
arch/powerpc/kvm/book3s_64_mmu_hv.c | 36 +++--
arch/powerpc/kvm/book3s_hv_builtin.c | 79 +++++++----
arch/powerpc/kvm/book3s_hv_cma.c | 220 +++++++++++++++++++++++++++++++
arch/powerpc/kvm/book3s_hv_cma.h | 21 +++
10 files changed, 322 insertions(+), 51 deletions(-)
create mode 100644 arch/powerpc/kvm/book3s_hv_cma.c
create mode 100644 arch/powerpc/kvm/book3s_hv_cma.h
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 9c1ff33..f8355a9 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -37,7 +37,6 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu)
#ifdef CONFIG_KVM_BOOK3S_64_HV
#define KVM_DEFAULT_HPT_ORDER 24 /* 16MB HPT by default */
-extern int kvm_hpt_order; /* order of preallocated HPTs */
#endif
#define VRMA_VSID 0x1ffffffUL /* 1TB VSID reserved for VRMA */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index af326cd..0097dab 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -259,7 +259,7 @@ struct kvm_arch {
spinlock_t slot_phys_lock;
cpumask_t need_tlb_flush;
struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
- struct kvmppc_linear_info *hpt_li;
+ int hpt_cma_alloc;
#endif /* CONFIG_KVM_BOOK3S_64_HV */
#ifdef CONFIG_PPC_BOOK3S_64
struct list_head spapr_tce_tables;
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index a5287fe..058ac93 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -139,8 +139,8 @@ extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm,
struct kvm_allocate_rma *rma);
extern struct kvmppc_linear_info *kvm_alloc_rma(void);
extern void kvm_release_rma(struct kvmppc_linear_info *ri);
-extern struct kvmppc_linear_info *kvm_alloc_hpt(void);
-extern void kvm_release_hpt(struct kvmppc_linear_info *li);
+extern struct page *kvm_alloc_hpt(int nr_pages);
+extern void kvm_release_hpt(struct page *page, int nr_pages);
extern int kvmppc_core_init_vm(struct kvm *kvm);
extern void kvmppc_core_destroy_vm(struct kvm *kvm);
extern void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
@@ -261,6 +261,7 @@ void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
struct openpic;
#ifdef CONFIG_KVM_BOOK3S_64_HV
+extern void kvm_cma_reserve(void) __init;
static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
{
paca[cpu].kvm_hstate.xics_phys = addr;
@@ -284,6 +285,9 @@ extern void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu);
extern void kvm_linear_init(void);
#else
+static inline void __init kvm_cma_reserve(void)
+{}
+
static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
{}
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index e379d3f..ee28d1f 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -229,6 +229,8 @@ void __init early_setup(unsigned long dt_ptr)
/* Initialize the hash table or TLB handling */
early_init_mmu();
+ kvm_cma_reserve();
+
/*
* Reserve any gigantic pages requested on the command line.
* memblock needs to have been initialized by the time this is
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index eb643f8..ffaef2c 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -72,6 +72,7 @@ config KVM_BOOK3S_64_HV
bool "KVM support for POWER7 and PPC970 using hypervisor mode in host"
depends on KVM_BOOK3S_64
select MMU_NOTIFIER
+ select CMA
---help---
Support running unmodified book3s_64 guest kernels in
virtual machines on POWER7 and PPC970 processors that have
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 422de3f..dc155de 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -74,12 +74,15 @@ kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
book3s_64_mmu_hv.o
kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \
book3s_hv_rm_xics.o
+kvm-book3s_64-builtin-cma-objs-$(CONFIG_CMA) := \
+ book3s_hv_cma.o
kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
book3s_hv_rmhandlers.o \
book3s_hv_rm_mmu.o \
book3s_64_vio_hv.o \
book3s_hv_ras.o \
book3s_hv_builtin.o \
+ $(kvm-book3s_64-builtin-cma-objs-y) \
$(kvm-book3s_64-builtin-xics-objs-y)
kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 5880dfb..e96470d 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -52,8 +52,8 @@ long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp)
{
unsigned long hpt;
struct revmap_entry *rev;
- struct kvmppc_linear_info *li;
- long order = kvm_hpt_order;
+ struct page *page = NULL;
+ long order = KVM_DEFAULT_HPT_ORDER;
if (htab_orderp) {
order = *htab_orderp;
@@ -62,25 +62,20 @@ long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp)
}
/*
- * If the user wants a different size from default,
* try first to allocate it from the kernel page allocator.
+ * We keep the CMA reserved for failed allocation.
*/
- hpt = 0;
- if (order != kvm_hpt_order) {
- hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|
- __GFP_NOWARN, order - PAGE_SHIFT);
- if (!hpt)
- --order;
- }
+ hpt = __get_free_pages(GFP_KERNEL | __GFP_ZERO | __GFP_REPEAT |
+ __GFP_NOWARN, order - PAGE_SHIFT);
/* Next try to allocate from the preallocated pool */
if (!hpt) {
- li = kvm_alloc_hpt();
- if (li) {
- hpt = (ulong)li->base_virt;
- kvm->arch.hpt_li = li;
- order = kvm_hpt_order;
- }
+ page = kvm_alloc_hpt(1 << (order - PAGE_SHIFT));
+ if (page) {
+ hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+ kvm->arch.hpt_cma_alloc = 1;
+ } else
+ --order;
}
/* Lastly try successively smaller sizes from the page allocator */
@@ -118,8 +113,8 @@ long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp)
return 0;
out_freehpt:
- if (kvm->arch.hpt_li)
- kvm_release_hpt(kvm->arch.hpt_li);
+ if (kvm->arch.hpt_cma_alloc)
+ kvm_release_hpt(page, 1 << (order - PAGE_SHIFT));
else
free_pages(hpt, order - PAGE_SHIFT);
return -ENOMEM;
@@ -165,8 +160,9 @@ void kvmppc_free_hpt(struct kvm *kvm)
{
kvmppc_free_lpid(kvm->arch.lpid);
vfree(kvm->arch.revmap);
- if (kvm->arch.hpt_li)
- kvm_release_hpt(kvm->arch.hpt_li);
+ if (kvm->arch.hpt_cma_alloc)
+ kvm_release_hpt(virt_to_page(kvm->arch.hpt_virt),
+ 1 << (kvm->arch.hpt_order - PAGE_SHIFT));
else
free_pages(kvm->arch.hpt_virt,
kvm->arch.hpt_order - PAGE_SHIFT);
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index ec0a9e5..cf8e25a 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -13,20 +13,29 @@
#include <linux/spinlock.h>
#include <linux/bootmem.h>
#include <linux/init.h>
+#include <linux/memblock.h>
+#include <linux/sizes.h>
#include <asm/cputable.h>
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s.h>
+#include "book3s_hv_cma.h"
+
#define KVM_LINEAR_RMA 0
#define KVM_LINEAR_HPT 1
static void __init kvm_linear_init_one(ulong size, int count, int type);
static struct kvmppc_linear_info *kvm_alloc_linear(int type);
static void kvm_release_linear(struct kvmppc_linear_info *ri);
-
-int kvm_hpt_order = KVM_DEFAULT_HPT_ORDER;
-EXPORT_SYMBOL_GPL(kvm_hpt_order);
+/*
+ * should be power of 2
+ */
+static unsigned long hpt_align_pages = (1 << 18) >> PAGE_SHIFT; /* 256k */
+/*
+ * By default we reserve 5% of memory for hash pagetable allocation.
+ */
+static unsigned long kvm_cma_resv_ratio = 5;
/*************** RMA *************/
@@ -101,36 +110,25 @@ void kvm_release_rma(struct kvmppc_linear_info *ri)
}
EXPORT_SYMBOL_GPL(kvm_release_rma);
-/*************** HPT *************/
-
-/*
- * This maintains a list of big linear HPT tables that contain the GVA->HPA
- * memory mappings. If we don't reserve those early on, we might not be able
- * to get a big (usually 16MB) linear memory region from the kernel anymore.
- */
-
-static unsigned long kvm_hpt_count;
-
-static int __init early_parse_hpt_count(char *p)
+static int __init early_parse_kvm_cma_resv(char *p)
{
+ pr_debug("%s(%s)\n", __func__, p);
if (!p)
- return 1;
-
- kvm_hpt_count = simple_strtoul(p, NULL, 0);
-
- return 0;
+ return -EINVAL;
+ return kstrtoul(p, 0, &kvm_cma_resv_ratio);
}
-early_param("kvm_hpt_count", early_parse_hpt_count);
+early_param("kvm_cma_resv_ratio", early_parse_kvm_cma_resv);
-struct kvmppc_linear_info *kvm_alloc_hpt(void)
+struct page *kvm_alloc_hpt(int nr_pages)
{
- return kvm_alloc_linear(KVM_LINEAR_HPT);
+ return kvm_alloc_cma(nr_pages,
+ get_order(hpt_align_pages << PAGE_SHIFT));
}
EXPORT_SYMBOL_GPL(kvm_alloc_hpt);
-void kvm_release_hpt(struct kvmppc_linear_info *li)
+void kvm_release_hpt(struct page *page, int nr_pages)
{
- kvm_release_linear(li);
+ kvm_release_cma(page, nr_pages);
}
EXPORT_SYMBOL_GPL(kvm_release_hpt);
@@ -211,9 +209,6 @@ static void kvm_release_linear(struct kvmppc_linear_info *ri)
*/
void __init kvm_linear_init(void)
{
- /* HPT */
- kvm_linear_init_one(1 << kvm_hpt_order, kvm_hpt_count, KVM_LINEAR_HPT);
-
/* RMA */
/* Only do this on PPC970 in HV mode */
if (!cpu_has_feature(CPU_FTR_HVMODE) ||
@@ -231,3 +226,33 @@ void __init kvm_linear_init(void)
kvm_linear_init_one(kvm_rma_size, kvm_rma_count, KVM_LINEAR_RMA);
}
+
+/**
+ * kvm_cma_reserve() - reserve area for kvm hash pagetable
+ *
+ * This function reserves memory from early allocator. It should be
+ * called by arch specific code once the early allocator (memblock or bootmem)
+ * has been activated and all other subsystems have already allocated/reserved
+ * memory.
+ */
+void __init kvm_cma_reserve(void)
+{
+ int align_size;
+ struct memblock_region *reg;
+ phys_addr_t selected_size = 0;
+ /*
+ * We cannot use memblock_phys_mem_size() here, because
+ * memblock_analyze() has not been called yet.
+ */
+ for_each_memblock(memory, reg)
+ selected_size += memblock_region_memory_end_pfn(reg) -
+ memblock_region_memory_base_pfn(reg);
+
+ selected_size = (selected_size * kvm_cma_resv_ratio / 100) << PAGE_SHIFT;
+ if (selected_size) {
+ pr_debug("%s: reserving %ld MiB for global area\n", __func__,
+ (unsigned long)selected_size / SZ_1M);
+ align_size = hpt_align_pages << PAGE_SHIFT;
+ kvm_cma_declare_contiguous(selected_size, align_size);
+ }
+}
diff --git a/arch/powerpc/kvm/book3s_hv_cma.c b/arch/powerpc/kvm/book3s_hv_cma.c
new file mode 100644
index 0000000..8bd68bc
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_cma.c
@@ -0,0 +1,220 @@
+/*
+ * Contiguous Memory Allocator for ppc KVM hash pagetable based on CMA
+ * for DMA mapping framework
+ *
+ * Copyright IBM Corporation, 2013
+ * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License or (at your optional) any later version of the license.
+ *
+ */
+#define pr_fmt(fmt) "kvm_cma: " fmt
+
+#ifdef CONFIG_CMA_DEBUG
+#ifndef DEBUG
+# define DEBUG
+#endif
+#endif
+
+#include <linux/memblock.h>
+#include <linux/mutex.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+struct kvm_cma {
+ unsigned long base_pfn;
+ unsigned long count;
+ unsigned long *bitmap;
+};
+
+static DEFINE_MUTEX(kvm_cma_mutex);
+static struct kvm_cma kvm_cma_area;
+
+/**
+ * kvm_cma_declare_contiguous() - reserve area for contiguous memory handling
+ * for kvm hash pagetable
+ * @size: Size of the reserved memory.
+ * @alignment: Alignment for the contiguous memory area
+ *
+ * This function reserves memory for kvm cma area. It should be
+ * called by arch code when early allocator (memblock or bootmem)
+ * is still activate.
+ */
+long __init kvm_cma_declare_contiguous(phys_addr_t size, phys_addr_t alignment)
+{
+ long base_pfn;
+ phys_addr_t addr;
+ struct kvm_cma *cma = &kvm_cma_area;
+
+ pr_debug("%s(size %lx)\n", __func__, (unsigned long)size);
+
+ if (!size)
+ return -EINVAL;
+ /*
+ * Sanitise input arguments.
+ * We should be pageblock aligned for CMA.
+ */
+ alignment = max(alignment, (phys_addr_t)(PAGE_SIZE << pageblock_order));
+ size = ALIGN(size, alignment);
+ /*
+ * Reserve memory
+ * Use __memblock_alloc_base() since
+ * memblock_alloc_base() panic()s.
+ */
+ addr = __memblock_alloc_base(size, alignment, 0);
+ if (!addr) {
+ base_pfn = -ENOMEM;
+ goto err;
+ } else
+ base_pfn = PFN_DOWN(addr);
+
+ /*
+ * Each reserved area must be initialised later, when more kernel
+ * subsystems (like slab allocator) are available.
+ */
+ cma->base_pfn = base_pfn;
+ cma->count = size >> PAGE_SHIFT;
+ pr_info("CMA: reserved %ld MiB\n", (unsigned long)size / SZ_1M);
+ return 0;
+err:
+ pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
+ return base_pfn;
+}
+
+/**
+ * kvm_alloc_cma() - allocate pages from contiguous area
+ * @nr_pages: Requested number of pages.
+ * @align_order: Requested alignment of pages in PAGE_SIZE order
+ *
+ * This function allocates memory buffer for hash pagetable.
+ */
+struct page *kvm_alloc_cma(int nr_pages, unsigned long align_order)
+{
+ int ret;
+ struct page *page = NULL;
+ struct kvm_cma *cma = &kvm_cma_area;
+ unsigned long mask, pfn, pageno, start = 0;
+
+
+ if (!cma || !cma->count)
+ return NULL;
+
+ pr_debug("%s(cma %p, count %d, align order %lu)\n", __func__,
+ (void *)cma, nr_pages, align_order);
+
+ if (!nr_pages)
+ return NULL;
+
+ mask = (1 << align_order) - 1;
+
+ mutex_lock(&kvm_cma_mutex);
+ for (;;) {
+ pageno = bitmap_find_next_zero_area(cma->bitmap, cma->count,
+ start, nr_pages, mask);
+ if (pageno >= cma->count)
+ break;
+
+ pfn = cma->base_pfn + pageno;
+ ret = alloc_contig_range(pfn, pfn + nr_pages, MIGRATE_CMA);
+ if (ret == 0) {
+ bitmap_set(cma->bitmap, pageno, nr_pages);
+ page = pfn_to_page(pfn);
+ memset(pfn_to_kaddr(pfn), 0, nr_pages << PAGE_SHIFT);
+ break;
+ } else if (ret != -EBUSY) {
+ break;
+ }
+ pr_debug("%s(): memory range at %p is busy, retrying\n",
+ __func__, pfn_to_page(pfn));
+ /* try again with a bit different memory target */
+ start = pageno + mask + 1;
+ }
+ mutex_unlock(&kvm_cma_mutex);
+ pr_debug("%s(): returned %p\n", __func__, page);
+ return page;
+}
+
+/**
+ * kvm_release_cma() - release allocated pages for hash pagetable
+ * @pages: Allocated pages.
+ * @nr_pages: Number of allocated pages.
+ *
+ * This function releases memory allocated by kvm_alloc_cma().
+ * It returns false when provided pages do not belong to contiguous area and
+ * true otherwise.
+ */
+bool kvm_release_cma(struct page *pages, int nr_pages)
+{
+ unsigned long pfn;
+ struct kvm_cma *cma = &kvm_cma_area;
+
+
+ if (!cma || !pages)
+ return false;
+
+ pr_debug("%s(page %p count %d)\n", __func__, (void *)pages, nr_pages);
+
+ pfn = page_to_pfn(pages);
+
+ if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count)
+ return false;
+
+ VM_BUG_ON(pfn + nr_pages > cma->base_pfn + cma->count);
+
+ mutex_lock(&kvm_cma_mutex);
+ bitmap_clear(cma->bitmap, pfn - cma->base_pfn, nr_pages);
+ free_contig_range(pfn, nr_pages);
+ mutex_unlock(&kvm_cma_mutex);
+
+ return true;
+}
+
+static int __init kvm_cma_activate_area(unsigned long base_pfn,
+ unsigned long count)
+{
+ unsigned long pfn = base_pfn;
+ unsigned i = count >> pageblock_order;
+ struct zone *zone;
+
+ WARN_ON_ONCE(!pfn_valid(pfn));
+ zone = page_zone(pfn_to_page(pfn));
+ do {
+ unsigned j;
+ base_pfn = pfn;
+ for (j = pageblock_nr_pages; j; --j, pfn++) {
+ WARN_ON_ONCE(!pfn_valid(pfn));
+ if (page_zone(pfn_to_page(pfn)) != zone)
+ return -EINVAL;
+ }
+ init_cma_reserved_pageblock(pfn_to_page(base_pfn));
+ } while (--i);
+ return 0;
+}
+
+static int __init kvm_cma_init_reserved_areas(void)
+{
+ int bitmap_size, ret;
+ struct kvm_cma *cma = &kvm_cma_area;
+
+ pr_debug("%s()\n", __func__);
+ if (!cma->count)
+ return 0;
+
+ bitmap_size = BITS_TO_LONGS(cma->count) * sizeof(long);
+ cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+ if (!cma->bitmap)
+ return -ENOMEM;
+
+ ret = kvm_cma_activate_area(cma->base_pfn, cma->count);
+ if (ret)
+ goto error;
+ return 0;
+
+error:
+ kfree(cma->bitmap);
+ return ret;
+}
+core_initcall(kvm_cma_init_reserved_areas);
diff --git a/arch/powerpc/kvm/book3s_hv_cma.h b/arch/powerpc/kvm/book3s_hv_cma.h
new file mode 100644
index 0000000..6c5c75d
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_cma.h
@@ -0,0 +1,21 @@
+/*
+ * Contiguous Memory Allocator for ppc KVM hash pagetable based on CMA
+ * for DMA mapping framework
+ *
+ * Copyright IBM Corporation, 2013
+ * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License or (at your optional) any later version of the license.
+ *
+ */
+
+#ifndef __POWERPC_KVM_CMA_ALLOC_H__
+#define __POWERPC_KVM_CMA_ALLOC_H__
+extern struct page *kvm_alloc_cma(int nr_pages, unsigned long align_order);
+extern bool kvm_release_cma(struct page *pages, int nr_pages);
+extern long kvm_cma_declare_contiguous(phys_addr_t size,
+ phys_addr_t alignment) __init;
+#endif
--
1.8.1.2
^ permalink raw reply related
* [RFC PATCH 1/3] mm/cma: Move dma contiguous changes into a seperate config
From: Aneesh Kumar K.V @ 2013-06-24 8:25 UTC (permalink / raw)
To: linux-mm, benh, paulus; +Cc: linuxppc-dev, Aneesh Kumar K.V
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
We want to use CMA for allocating hash page table and real mode area for
PPC64. Hence move DMA contiguous related changes into a seperate config
so that ppc64 can enable CMA without requiring DMA contiguous.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/arm/configs/omap2plus_defconfig | 2 +-
arch/arm/configs/tegra_defconfig | 2 +-
arch/arm/include/asm/dma-contiguous.h | 2 +-
arch/arm/mm/dma-mapping.c | 6 +++---
drivers/base/Kconfig | 21 +++++----------------
drivers/base/Makefile | 2 +-
include/linux/dma-contiguous.h | 2 +-
mm/Kconfig | 20 ++++++++++++++++++++
8 files changed, 33 insertions(+), 24 deletions(-)
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index abbe319..098268f 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -71,7 +71,7 @@ CONFIG_MAC80211=m
CONFIG_MAC80211_RC_PID=y
CONFIG_MAC80211_RC_DEFAULT_PID=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_CMA=y
+CONFIG_DMA_CMA=y
CONFIG_CONNECTOR=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index f7ba3161..34ae8f2 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -79,7 +79,7 @@ CONFIG_RFKILL_GPIO=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_CMA=y
+CONFIG_DMA_CMA=y
CONFIG_MTD=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_M25P80=y
diff --git a/arch/arm/include/asm/dma-contiguous.h b/arch/arm/include/asm/dma-contiguous.h
index 3ed37b4..e072bb2 100644
--- a/arch/arm/include/asm/dma-contiguous.h
+++ b/arch/arm/include/asm/dma-contiguous.h
@@ -2,7 +2,7 @@
#define ASMARM_DMA_CONTIGUOUS_H
#ifdef __KERNEL__
-#ifdef CONFIG_CMA
+#ifdef CONFIG_DMA_CMA
#include <linux/types.h>
#include <asm-generic/dma-contiguous.h>
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index ef3e0f3..1fb40dc 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -358,7 +358,7 @@ static int __init atomic_pool_init(void)
if (!pages)
goto no_pages;
- if (IS_ENABLED(CONFIG_CMA))
+ if (IS_ENABLED(CONFIG_DMA_CMA))
ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
atomic_pool_init);
else
@@ -670,7 +670,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
addr = __alloc_simple_buffer(dev, size, gfp, &page);
else if (!(gfp & __GFP_WAIT))
addr = __alloc_from_pool(size, &page);
- else if (!IS_ENABLED(CONFIG_CMA))
+ else if (!IS_ENABLED(CONFIG_DMA_CMA))
addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
else
addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
@@ -759,7 +759,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
__dma_free_buffer(page, size);
} else if (__free_from_pool(cpu_addr, size)) {
return;
- } else if (!IS_ENABLED(CONFIG_CMA)) {
+ } else if (!IS_ENABLED(CONFIG_DMA_CMA)) {
__dma_free_remap(cpu_addr, size);
__dma_free_buffer(page, size);
} else {
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 07abd9d..74b7c98 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -202,11 +202,10 @@ config DMA_SHARED_BUFFER
APIs extension; the file's descriptor can then be passed on to other
driver.
-config CMA
- bool "Contiguous Memory Allocator"
- depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK
- select MIGRATION
- select MEMORY_ISOLATION
+config DMA_CMA
+ bool "DMA Contiguous Memory Allocator"
+ depends on HAVE_DMA_CONTIGUOUS
+ select CMA
help
This enables the Contiguous Memory Allocator which allows drivers
to allocate big physically-contiguous blocks of memory for use with
@@ -215,17 +214,7 @@ config CMA
For more information see <include/linux/dma-contiguous.h>.
If unsure, say "n".
-if CMA
-
-config CMA_DEBUG
- bool "CMA debug messages (DEVELOPMENT)"
- depends on DEBUG_KERNEL
- help
- Turns on debug messages in CMA. This produces KERN_DEBUG
- messages for every CMA call as well as various messages while
- processing calls such as dma_alloc_from_contiguous().
- This option does not affect warning and error messages.
-
+if DMA_CMA
comment "Default contiguous memory area size:"
config CMA_SIZE_MBYTES
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 4e22ce3..5d93bb5 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -6,7 +6,7 @@ obj-y := core.o bus.o dd.o syscore.o \
attribute_container.o transport_class.o \
topology.o
obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
-obj-$(CONFIG_CMA) += dma-contiguous.o
+obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
obj-y += power/
obj-$(CONFIG_HAS_DMA) += dma-mapping.o
obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h
index 01b5c84..00141d3 100644
--- a/include/linux/dma-contiguous.h
+++ b/include/linux/dma-contiguous.h
@@ -57,7 +57,7 @@ struct cma;
struct page;
struct device;
-#ifdef CONFIG_CMA
+#ifdef CONFIG_DMA_CMA
/*
* There is always at least global CMA area and a few optional device
diff --git a/mm/Kconfig b/mm/Kconfig
index e742d06..b362369 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -477,3 +477,23 @@ config FRONTSWAP
and swap data is stored as normal on the matching swap device.
If unsure, say Y to enable frontswap.
+
+config CMA
+ bool "Contiguous Memory Allocator"
+ depends on HAVE_MEMBLOCK
+ select MIGRATION
+ select MEMORY_ISOLATION
+ help
+ This enables the Contiguous Memory Allocator which allows other
+ subsystem to allocate big physically-contiguous blocks of memory
+
+ If unsure, say "n".
+
+config CMA_DEBUG
+ bool "CMA debug messages (DEVELOPMENT)"
+ depends on DEBUG_KERNEL && CMA
+ help
+ Turns on debug messages in CMA. This produces KERN_DEBUG
+ messages for every CMA call as well as various messages while
+ processing calls such as dma_alloc_from_contiguous().
+ This option does not affect warning and error messages.
--
1.8.1.2
^ permalink raw reply related
* Re: Build regressions/improvements in v3.10-rc7
From: Geert Uytterhoeven @ 2013-06-24 8:59 UTC (permalink / raw)
To: Linux Kernel Development; +Cc: Linux/PPC Development
In-Reply-To: <alpine.DEB.2.00.1306241054001.10792@ayla.of.borg>
On Mon, 24 Jun 2013, Geert Uytterhoeven wrote:
> JFYI, when comparing v3.10-rc7 to v3.10-rc6[3], the summaries are:
> - build errors: +51/-11
After filtering out false-positives (v3.10-rc6 had only 72% build coverage):
+ arch/powerpc/kernel/fadump.c: error: 'KEXEC_CORE_NOTE_NAME' undeclared (first use in this function): => 521:36
+ arch/powerpc/kernel/fadump.c: error: 'crashing_cpu' undeclared (first use in this function): => 408:2
+ arch/powerpc/kernel/fadump.c: error: 'note_buf_t' undeclared (first use in this function): => 624:49
+ arch/powerpc/kernel/fadump.c: error: 'vmcoreinfo_max_size' undeclared (first use in this function): => 874:18
+ arch/powerpc/kernel/fadump.c: error: implicit declaration of function 'crash_save_vmcoreinfo' [-Werror=implicit-function-declaration]: => 410:2
+ arch/powerpc/kernel/fadump.c: error: implicit declaration of function 'elf_core_copy_kernel_regs' [-Werror=implicit-function-declaration]: => 520:2
+ arch/powerpc/kernel/fadump.c: error: implicit declaration of function 'paddr_vmcoreinfo_note' [-Werror=implicit-function-declaration]: => 872:2
+ arch/powerpc/kernel/fadump.c: error: storage size of 'prstatus' isn't known: => 513:22
+ arch/powerpc/kernel/fadump.c: error: unused variable 'prstatus' [-Werror=unused-variable]: => 513:22
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_ANDCOND' undeclared (first use in this function): => 161:17, 86:16
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_AVPN' undeclared (first use in this function): => 160:17, 85:16, 192:16
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_BULK_REMOVE' undeclared (first use in this function): => 246:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_CEDE' undeclared (first use in this function): => 250:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_CPPR' undeclared (first use in this function): => 257:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_ENTER' undeclared (first use in this function): => 240:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_EOI' undeclared (first use in this function): => 258:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_EXACT' undeclared (first use in this function): => 50:6
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_IPI' undeclared (first use in this function): => 259:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_IPOLL' undeclared (first use in this function): => 260:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_NOT_FOUND' undeclared (first use in this function): => 193:27, 87:27
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_PARAMETER' undeclared (first use in this function): => 138:10
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_PROTECT' undeclared (first use in this function): => 244:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_PTEG_FULL' undeclared (first use in this function): => 54:12
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_PUT_TCE' undeclared (first use in this function): => 248:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_REMOVE' undeclared (first use in this function): => 242:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_RTAS' undeclared (first use in this function): => 265:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_SUCCESS' undeclared (first use in this function): => 67:26, 96:26, 211:26, 125:12
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_TOO_HARD' undeclared (first use in this function): => 224:12
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_XIRR' undeclared (first use in this function): => 256:7
+ arch/powerpc/kvm/book3s_pr_papr.c: error: 'H_XIRR_X' undeclared (first use in this function): => 261:7
All from the powerpc-randconfig police.
> [1] http://kisskb.ellerman.id.au/kisskb/head/6349/ (all 120 configs)
> [3] http://kisskb.ellerman.id.au/kisskb/head/6325/ (86 out of 120 configs)
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH 3/3 v16] iommu/fsl: Freescale PAMU driver and iommu implementation.
From: Joerg Roedel @ 2013-06-24 10:34 UTC (permalink / raw)
To: alex.williamson, Varun Sethi
Cc: Timur Tabi, stuart.yoder, linux-kernel, iommu, scottwood,
linuxppc-dev
In-Reply-To: <1371744089-17780-2-git-send-email-Varun.Sethi@freescale.com>
On Thu, Jun 20, 2013 at 09:31:28PM +0530, Varun Sethi wrote:
> This patch provides the PAMU driver (fsl_pamu.c) and the corresponding IOMMU
> API implementation (fsl_pamu_domain.c). The PAMU hardware driver (fsl_pamu.c)
> has been derived from the work done by Ashish Kalra and Timur Tabi.
AlexW,
can you please have a look at the group-code again and ack the patch if
it looks right to you?
Thanks,
Joerg
^ permalink raw reply
* [PATCH 1/8] powerpc/perf: Check that events only include valid bits on Power8
From: Michael Ellerman @ 2013-06-24 11:28 UTC (permalink / raw)
To: linuxppc-dev; +Cc: sukadev, Paul Mackerras, khandual
A mistake we have made in the past is that we pull out the fields we
need from the event code, but don't check that there are no unknown bits
set. This means that we can't ever assign meaning to those unknown bits
in future.
Although we have once again failed to do this at release, it is still
early days for Power8 so I think we can still slip this in and get away
with it.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/perf/power8-pmu.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index f7d1c4f..84cdc6d 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -109,6 +109,16 @@
#define EVENT_IS_MARKED (EVENT_MARKED_MASK << EVENT_MARKED_SHIFT)
#define EVENT_PSEL_MASK 0xff /* PMCxSEL value */
+#define EVENT_VALID_MASK \
+ ((EVENT_THRESH_MASK << EVENT_THRESH_SHIFT) | \
+ (EVENT_SAMPLE_MASK << EVENT_SAMPLE_SHIFT) | \
+ (EVENT_CACHE_SEL_MASK << EVENT_CACHE_SEL_SHIFT) | \
+ (EVENT_PMC_MASK << EVENT_PMC_SHIFT) | \
+ (EVENT_UNIT_MASK << EVENT_UNIT_SHIFT) | \
+ (EVENT_COMBINE_MASK << EVENT_COMBINE_SHIFT) | \
+ (EVENT_MARKED_MASK << EVENT_MARKED_SHIFT) | \
+ EVENT_PSEL_MASK)
+
/* MMCRA IFM bits - POWER8 */
#define POWER8_MMCRA_IFM1 0x0000000040000000UL
#define POWER8_MMCRA_IFM2 0x0000000080000000UL
@@ -212,6 +222,9 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
mask = value = 0;
+ if (event & ~EVENT_VALID_MASK)
+ return -1;
+
pmc = (event >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK;
unit = (event >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK;
cache = (event >> EVENT_CACHE_SEL_SHIFT) & EVENT_CACHE_SEL_MASK;
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/8] powerpc/perf: Rework disable logic in pmu_disable()
From: Michael Ellerman @ 2013-06-24 11:28 UTC (permalink / raw)
To: linuxppc-dev; +Cc: sukadev, Paul Mackerras, khandual
In-Reply-To: <1372073336-8189-1-git-send-email-michael@ellerman.id.au>
In pmu_disable() we disable the PMU by setting the FC (Freeze Counters)
bit in MMCR0. In order to do this we have to read/modify/write MMCR0.
It's possible that we read a value from MMCR0 which has PMAO (PMU Alert
Occurred) set. When we write that value back it will cause an interrupt
to occur. We will then end up in the PMU interrupt handler even though
we are supposed to have just disabled the PMU.
We can avoid this by making sure we never write PMAO back. We should not
lose interrupts because when the PMU is re-enabled the overflowed values
will cause another interrupt.
We also reorder the clearing of SAMPLE_ENABLE so that is done after the
PMU is frozen. Otherwise there is a small window between the clearing of
SAMPLE_ENABLE and the setting of FC where we could take an interrupt and
incorrectly see SAMPLE_ENABLE not set. This would for example change the
logic in perf_read_regs().
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/perf/core-book3s.c | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 29c6482..1ab3068 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -75,6 +75,7 @@ static unsigned int freeze_events_kernel = MMCR0_FCS;
#define MMCR0_FCHV 0
#define MMCR0_PMCjCE MMCR0_PMCnCE
+#define MMCR0_PMAO 0
#define SPRN_MMCRA SPRN_MMCR2
#define MMCRA_SAMPLE_ENABLE 0
@@ -852,7 +853,7 @@ static void write_mmcr0(struct cpu_hw_events *cpuhw, unsigned long mmcr0)
static void power_pmu_disable(struct pmu *pmu)
{
struct cpu_hw_events *cpuhw;
- unsigned long flags;
+ unsigned long flags, val;
if (!ppmu)
return;
@@ -860,9 +861,6 @@ static void power_pmu_disable(struct pmu *pmu)
cpuhw = &__get_cpu_var(cpu_hw_events);
if (!cpuhw->disabled) {
- cpuhw->disabled = 1;
- cpuhw->n_added = 0;
-
/*
* Check if we ever enabled the PMU on this cpu.
*/
@@ -872,6 +870,21 @@ static void power_pmu_disable(struct pmu *pmu)
}
/*
+ * Set the 'freeze counters' bit, clear PMAO.
+ */
+ val = mfspr(SPRN_MMCR0);
+ val |= MMCR0_FC;
+ val &= ~MMCR0_PMAO;
+
+ /*
+ * The barrier is to make sure the mtspr has been
+ * executed and the PMU has frozen the events etc.
+ * before we return.
+ */
+ write_mmcr0(cpuhw, val);
+ mb();
+
+ /*
* Disable instruction sampling if it was enabled
*/
if (cpuhw->mmcr[2] & MMCRA_SAMPLE_ENABLE) {
@@ -880,14 +893,8 @@ static void power_pmu_disable(struct pmu *pmu)
mb();
}
- /*
- * Set the 'freeze counters' bit.
- * The barrier is to make sure the mtspr has been
- * executed and the PMU has frozen the events
- * before we return.
- */
- write_mmcr0(cpuhw, mfspr(SPRN_MMCR0) | MMCR0_FC);
- mb();
+ cpuhw->disabled = 1;
+ cpuhw->n_added = 0;
}
local_irq_restore(flags);
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH 3/8] powerpc/perf: Freeze PMC5/6 if we're not using them
From: Michael Ellerman @ 2013-06-24 11:28 UTC (permalink / raw)
To: linuxppc-dev; +Cc: sukadev, Paul Mackerras, khandual
In-Reply-To: <1372073336-8189-1-git-send-email-michael@ellerman.id.au>
On Power8 we can freeze PMC5 and 6 if we're not using them. Normally they
run all the time.
As noticed by Anshuman, we should unfreeze them when we disable the PMU
as there are legacy tools which expect them to run all the time.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/include/asm/reg.h | 1 +
arch/powerpc/perf/core-book3s.c | 5 +++--
arch/powerpc/perf/power8-pmu.c | 4 ++++
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 4a9e408..362142b 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -626,6 +626,7 @@
#define MMCR0_TRIGGER 0x00002000UL /* TRIGGER enable */
#define MMCR0_PMAO 0x00000080UL /* performance monitor alert has occurred, set to 0 after handling exception */
#define MMCR0_SHRFC 0x00000040UL /* SHRre freeze conditions between threads */
+#define MMCR0_FC56 0x00000010UL /* freeze counters 5 and 6 */
#define MMCR0_FCTI 0x00000008UL /* freeze counters in tags inactive mode */
#define MMCR0_FCTA 0x00000004UL /* freeze counters in tags active mode */
#define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 1ab3068..3d566ee 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -75,6 +75,7 @@ static unsigned int freeze_events_kernel = MMCR0_FCS;
#define MMCR0_FCHV 0
#define MMCR0_PMCjCE MMCR0_PMCnCE
+#define MMCR0_FC56 0
#define MMCR0_PMAO 0
#define SPRN_MMCRA SPRN_MMCR2
@@ -870,11 +871,11 @@ static void power_pmu_disable(struct pmu *pmu)
}
/*
- * Set the 'freeze counters' bit, clear PMAO.
+ * Set the 'freeze counters' bit, clear PMAO/FC56.
*/
val = mfspr(SPRN_MMCR0);
val |= MMCR0_FC;
- val &= ~MMCR0_PMAO;
+ val &= ~(MMCR0_PMAO | MMCR0_FC56);
/*
* The barrier is to make sure the mtspr has been
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 84cdc6d..d59f5b2 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -391,6 +391,10 @@ static int power8_compute_mmcr(u64 event[], int n_ev,
if (pmc_inuse & 0x7c)
mmcr[0] |= MMCR0_PMCjCE;
+ /* If we're not using PMC 5 or 6, freeze them */
+ if (!(pmc_inuse & 0x60))
+ mmcr[0] |= MMCR0_FC56;
+
mmcr[1] = mmcr1;
mmcr[2] = mmcra;
--
1.7.10.4
^ 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