From: Fenghua Yu <fenghua.yu@intel.com>
To: linux-ia64@vger.kernel.org
Subject: [PATCH] Multiple outstanding ptc.g instructions support
Date: Tue, 29 Jan 2008 23:49:20 +0000 [thread overview]
Message-ID: <20080129234920.GA21517@linux-os.sc.intel.com> (raw)
According to SDM2.2, Itanium supports multiple outstanding ptc.g instructions.
But current kernel function ia64_global_tlb_purge() uses a spinlock to serialize
ptc.g instructions issued by multiple processors. This serialization might have
scalability issue on a big SMP machine where many processors could purge TLB
in parallel.
The patch fixes this problem by issuing multiple ptc.g instructions in
ia64_global_tlb_purge(). It queries PALO table to get max number of outstanding
ptc.g instructions. PALO specification can be found at:
http://www.dig64.org/home/DIG64_PALO_R1_0.pdf
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
arch/ia64/kernel/efi.c | 61 +++++++++++++++++++++++++++++++++++++++++++++
arch/ia64/kernel/palinfo.c | 21 +++++++++++----
arch/ia64/mm/tlb.c | 44 +++++++++++++++++++++-----------
include/asm-ia64/sal.h | 21 +++++++++++++++
4 files changed, 126 insertions(+), 21 deletions(-)
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 242d793..bdb079a 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -388,6 +388,58 @@ efi_get_pal_addr (void)
return NULL;
}
+
+static u8 __init palo_checksum(u8 *buffer, u32 length)
+{
+ u8 sum = 0;
+ u8 *end = buffer + length;
+
+ while (buffer < end)
+ sum = (u8) (sum + *(buffer++));
+
+ return sum;
+}
+
+/*
+ * Parse and handle PALO table which is published at:
+ * http://www.dig64.org/home/DIG64_PALO_R1_0.pdf
+ */
+static int __init handle_palo(unsigned long palo_phys)
+{
+ struct palo_table *tmp;
+ u8 checksum;
+
+ if (palo_phys = EFI_INVALID_TABLE_ADDR) {
+ printk(KERN_INFO "PALO not found.\n");
+ nptcg = 1;
+ goto exit_nptcg;
+ }
+
+ tmp = (struct palo_table *)__va(palo_phys);
+ if (strncmp(tmp->signature, PALO_SIG, sizeof(PALO_SIG) - 1)) {
+ printk(KERN_INFO "PALO signature incorrect.\n");
+ nptcg = 1;
+ goto exit_nptcg;
+ }
+
+ checksum = palo_checksum((u8 *)tmp, tmp->length);
+ if (checksum) {
+ printk(KERN_INFO "PALO checksum incorrect.\n");
+ nptcg = 1;
+ goto exit_nptcg;
+ }
+
+ /* When getting to here, palo points to a valid PALO table. */
+ palo = tmp;
+ nptcg = palo->max_tlb_purges;
+ if (nptcg = 0)
+ panic("Woah! Don't support global TLB purges.\n");
+
+exit_nptcg:
+ sema_init(&ptcg_sem, nptcg);
+ return nptcg;
+}
+
void
efi_map_pal_code (void)
{
@@ -417,6 +469,7 @@ efi_init (void)
u64 efi_desc_size;
char *cp, vendor[100] = "unknown";
int i;
+ unsigned long palo_phys;
/* it's too early to be able to use the standard kernel command line support... */
for (cp = boot_command_line; *cp; ) {
@@ -475,6 +528,8 @@ efi_init (void)
efi.hcdp = EFI_INVALID_TABLE_ADDR;
efi.uga = EFI_INVALID_TABLE_ADDR;
+ palo_phys = EFI_INVALID_TABLE_ADDR;
+
for (i = 0; i < (int) efi.systab->nr_tables; i++) {
if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) = 0) {
efi.mps = config_tables[i].table;
@@ -494,10 +549,16 @@ efi_init (void)
} else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) = 0) {
efi.hcdp = config_tables[i].table;
printk(" HCDP=0x%lx", config_tables[i].table);
+ } else if (efi_guidcmp(config_tables[i].guid,
+ PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID) = 0) {
+ palo_phys = config_tables[i].table;
+ printk(" PALO=0x%lx", config_tables[i].table);
}
}
printk("\n");
+ handle_palo(palo_phys);
+
runtime = __va(efi.systab->runtime);
efi.get_time = phys_get_time;
efi.set_time = phys_set_time;
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 396004e..6fe8570 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -323,12 +323,21 @@ vm_info(char *page)
vm_info_1.pal_vm_info_1_s.key_size,
vm_info_1.pal_vm_info_1_s.hash_tag_id,
vm_info_2.pal_vm_info_2_s.rid_size);
- if (vm_info_2.pal_vm_info_2_s.max_purges = PAL_MAX_PURGES)
- p += sprintf(p, "unlimited\n");
- else
- p += sprintf(p, "%d\n",
- vm_info_2.pal_vm_info_2_s.max_purges ?
- vm_info_2.pal_vm_info_2_s.max_purges : 1);
+ if (!palo) {
+ if (vm_info_2.pal_vm_info_2_s.max_purges
+ = PAL_MAX_PURGES)
+ p += sprintf(p, "unlimited\n");
+ else
+ p += sprintf(p, "%d\n",
+ vm_info_2.pal_vm_info_2_s.max_purges ?
+ vm_info_2.pal_vm_info_2_s.max_purges:1);
+ } else {
+ if (palo->max_tlb_purges = PALO_MAX_TLB_PURGES)
+ p += sprintf(p, "unlimited\n");
+ else
+ p += sprintf(p, "%d\n",
+ palo->max_tlb_purges);
+ }
}
if (ia64_pal_mem_attrib(&attrib) = 0) {
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index 655da24..e3935d3 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -11,6 +11,9 @@
* Rohit Seth <rohit.seth@intel.com>
* Ken Chen <kenneth.w.chen@intel.com>
* Christophe de Dinechin <ddd@hp.com>: Avoid ptc.e on memory allocation
+ * Copyright (C) 2007 Intel Corp
+ * Fenghua Yu <fenghua.yu@intel.com>
+ * Add multiple ptc.g/ptc.ga instruction support in global tlb purge.
*/
#include <linux/module.h>
#include <linux/init.h>
@@ -26,6 +29,7 @@
#include <asm/pal.h>
#include <asm/tlbflush.h>
#include <asm/dma.h>
+#include <asm/sal.h>
static struct {
unsigned long mask; /* mask of supported purge page-sizes */
@@ -84,12 +88,15 @@ wrap_mmu_context (struct mm_struct *mm)
local_flush_tlb_all();
}
+struct palo_table *palo;
+struct semaphore ptcg_sem;
+u16 nptcg = 1;
+
void
ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
unsigned long end, unsigned long nbits)
{
- static DEFINE_SPINLOCK(ptcg_lock);
-
+ int do_ptcg_sem;
struct mm_struct *active_mm = current->active_mm;
if (mm != active_mm) {
@@ -102,19 +109,26 @@ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
}
}
- /* HW requires global serialization of ptc.ga. */
- spin_lock(&ptcg_lock);
- {
- do {
- /*
- * Flush ALAT entries also.
- */
- ia64_ptcga(start, (nbits<<2));
- ia64_srlz_i();
- start += (1UL << nbits);
- } while (start < end);
- }
- spin_unlock(&ptcg_lock);
+ /*
+ * If unlimited outstanding ptc.g (nptcg=0xffff), it's unnecessary to
+ * serialize ptc.g instructions.
+ */
+ do_ptcg_sem = nptcg = PALO_MAX_TLB_PURGES ? 0 : 1;
+ if (do_ptcg_sem)
+ /* This might put the process into sleep. */
+ down(&ptcg_sem);
+
+ do {
+ /*
+ * Flush ALAT entries also.
+ */
+ ia64_ptcga(start, (nbits << 2));
+ ia64_srlz_i();
+ start += (1UL << nbits);
+ } while (start < end);
+
+ if (do_ptcg_sem)
+ up(&ptcg_sem);
if (mm != active_mm) {
activate_context(active_mm);
diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
index 1f5412d..ad63ac7 100644
--- a/include/asm-ia64/sal.h
+++ b/include/asm-ia64/sal.h
@@ -296,6 +296,9 @@ enum {
EFI_GUID(0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
#define SAL_PLAT_BUS_ERR_SECT_GUID \
EFI_GUID(0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
+#define PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID \
+ EFI_GUID(0x6cb0a200, 0x893a, 0x11da, 0x96, 0xd2, 0x0, 0x10, 0x83, 0xff, \
+ 0xca, 0x4d)
#define MAX_CACHE_ERRORS 6
#define MAX_TLB_ERRORS 6
@@ -883,6 +886,24 @@ extern void ia64_jump_to_sal(struct sal_to_os_boot *);
extern void ia64_sal_handler_init(void *entry_point, void *gpval);
+#define PALO_MAX_TLB_PURGES 0xFFFF
+#define PALO_SIG "PALO"
+
+struct palo_table {
+ u8 signature[4]; /* Should be "PALO" */
+ u32 length;
+ u8 minor_revision;
+ u8 major_revision;
+ u8 checksum;
+ u8 reserved1[5];
+ u16 max_tlb_purges;
+ u8 reserved2[6];
+};
+
+extern struct palo_table *palo;
+extern struct semaphore ptcg_sem;
+extern u16 nptcg;
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_IA64_SAL_H */
next reply other threads:[~2008-01-29 23:49 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-29 23:49 Fenghua Yu [this message]
-- strict thread matches above, loose matches on Subject: below --
2008-02-07 21:34 [PATCH] Multiple outstanding ptc.g instructions support Luck, Tony
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080129234920.GA21517@linux-os.sc.intel.com \
--to=fenghua.yu@intel.com \
--cc=linux-ia64@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.