#include <asm/mmu_context.h>
#include <asm/ppcdebug.h>
#include <asm/iommu.h>
-#include <asm/naca.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
#include <asm/prom.h>
int vtermno; /* virtual terminal# for udbg */
+#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
+static void udbg_hvsi_putc(unsigned char c)
+{
+ /* packet's seqno isn't used anyways */
+ uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
+ int rc;
+
+ if (c == '\n')
+ udbg_hvsi_putc('\r');
+
+ do {
+ rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
+ } while (rc == H_Busy);
+}
+
+static long hvsi_udbg_buf_len;
+static uint8_t hvsi_udbg_buf[256];
+
+static int udbg_hvsi_getc_poll(void)
+{
+ unsigned char ch;
+ int rc, i;
+
+ if (hvsi_udbg_buf_len == 0) {
+ rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
+ if (rc != H_Success || hvsi_udbg_buf[0] != 0xff) {
+ /* bad read or non-data packet */
+ hvsi_udbg_buf_len = 0;
+ } else {
+ /* remove the packet header */
+ for (i = 4; i < hvsi_udbg_buf_len; i++)
+ hvsi_udbg_buf[i-4] = hvsi_udbg_buf[i];
+ hvsi_udbg_buf_len -= 4;
+ }
+ }
+
+ if (hvsi_udbg_buf_len <= 0 || hvsi_udbg_buf_len > 256) {
+ /* no data ready */
+ hvsi_udbg_buf_len = 0;
+ return -1;
+ }
+
+ ch = hvsi_udbg_buf[0];
+ /* shift remaining data down */
+ for (i = 1; i < hvsi_udbg_buf_len; i++) {
+ hvsi_udbg_buf[i-1] = hvsi_udbg_buf[i];
+ }
+ hvsi_udbg_buf_len--;
+
+ return ch;
+}
+
+static unsigned char udbg_hvsi_getc(void)
+{
+ int ch;
+ for (;;) {
+ ch = udbg_hvsi_getc_poll();
+ if (ch == -1) {
+ /* This shouldn't be needed...but... */
+ volatile unsigned long delay;
+ for (delay=0; delay < 2000000; delay++)
+ ;
+ } else {
+ return ch;
+ }
+ }
+}
+
static void udbg_putcLP(unsigned char c)
{
char buf[16];
ppc_md.udbg_getc_poll = udbg_getc_pollLP;
found = 1;
}
- } else {
- /* XXX implement udbg_putcLP_vtty for hvterm-protocol1 case */
- printk(KERN_WARNING "%s doesn't speak hvterm1; "
- "can't print udbg messages\n",
- stdout_node->full_name);
+ } else if (device_is_compatible(stdout_node, "hvterm-protocol")) {
+ termno = (u32 *)get_property(stdout_node, "reg", NULL);
+ if (termno) {
+ vtermno = termno[0];
+ ppc_md.udbg_putc = udbg_hvsi_putc;
+ ppc_md.udbg_getc = udbg_hvsi_getc;
+ ppc_md.udbg_getc_poll = udbg_hvsi_getc_poll;
+ found = 1;
+ }
}
} else if (strncmp(name, "serial", 6)) {
/* XXX fix ISA serial console */
return found;
}
+void vpa_init(int cpu)
+{
+ int hwcpu = get_hard_smp_processor_id(cpu);
+ unsigned long vpa = (unsigned long)&(paca[cpu].lppaca);
+ long ret;
+ unsigned long flags;
+
+ /* Register the Virtual Processor Area (VPA) */
+ flags = 1UL << (63 - 18);
+ ret = register_vpa(flags, hwcpu, __pa(vpa));
+
+ if (ret)
+ printk(KERN_ERR "WARNING: vpa_init: VPA registration for "
+ "cpu %d (hw %d) of area %lx returns %ld\n",
+ cpu, hwcpu, __pa(vpa), ret);
+}
long pSeries_lpar_hpte_insert(unsigned long hpte_group,
unsigned long va, unsigned long prpn,
return (slot & 7) | (secondary << 3);
}
-static spinlock_t pSeries_lpar_tlbie_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pSeries_lpar_tlbie_lock);
static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
{
static void pSeries_lpar_hptab_clear(void)
{
- unsigned long size_bytes = 1UL << naca->pftSize;
+ unsigned long size_bytes = 1UL << ppc64_pft_size;
unsigned long hpte_count = size_bytes >> 4;
unsigned long dummy1, dummy2;
int i;
hash = hpt_hash(vpn, 0);
for (j = 0; j < 2; j++) {
- slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+ slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
for (i = 0; i < HPTES_PER_GROUP; i++) {
hpte_dw0.dword0 = pSeries_lpar_hpte_getword0(slot);
dw0 = hpte_dw0.dw0;
int local)
{
int i;
- unsigned long flags;
+ unsigned long flags = 0;
struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);