aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/ia64/xenmisc.c
blob: da9c034e96bb28b4dff5fcd6b1b4c8a1a48fa4c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/*
 * Xen misc
 * 
 * Functions/decls that are/may be needed to link with Xen because
 * of x86 dependencies
 *
 * Copyright (C) 2004 Hewlett-Packard Co.
 *	Dan Magenheimer (dan.magenheimer@hp.com)
 *
 */

#include <linux/config.h>
#include <xen/sched.h>
#include <linux/efi.h>
#include <asm/processor.h>
#include <xen/serial.h>
#include <asm/io.h>
#include <xen/softirq.h>

efi_memory_desc_t ia64_efi_io_md;
EXPORT_SYMBOL(ia64_efi_io_md);
unsigned long wait_init_idle;
int phys_proc_id[NR_CPUS];
unsigned long loops_per_jiffy = (1<<12);	// from linux/init/main.c

void unw_init(void) { printf("unw_init() skipped (NEED FOR KERNEL UNWIND)\n"); }
void ia64_mca_init(void) { printf("ia64_mca_init() skipped (Machine check abort handling)\n"); }
void ia64_mca_cpu_init(void *x) { }
void ia64_patch_mckinley_e9(unsigned long a, unsigned long b) { }
void ia64_patch_vtop(unsigned long a, unsigned long b) { }
void hpsim_setup(char **x) { }

// called from mem_init... don't think s/w I/O tlb is needed in Xen
//void swiotlb_init(void) { }  ...looks like it IS needed

long
is_platform_hp_ski(void)
{
	int i;
	long cpuid[6];

	for (i = 0; i < 5; ++i)
		cpuid[i] = ia64_get_cpuid(i);
	if ((cpuid[0] & 0xff) != 'H') return 0;
	if ((cpuid[3] & 0xff) != 0x4) return 0;
	if (((cpuid[3] >> 8) & 0xff) != 0x0) return 0;
	if (((cpuid[3] >> 16) & 0xff) != 0x0) return 0;
	if (((cpuid[3] >> 24) & 0x7) != 0x7) return 0;
	return 1;
}

long
platform_is_hp_ski(void)
{
	extern long running_on_sim;
	return running_on_sim;
}

/* calls in xen/common code that are unused on ia64 */

void sync_lazy_execstate_cpu(unsigned int cpu) {}
void sync_lazy_execstate_mask(cpumask_t mask) {}
void sync_lazy_execstate_all(void) {}

#ifdef CONFIG_VTI
int grant_table_create(struct domain *d) { return 0; }
void grant_table_destroy(struct domain *d) { return; }
#endif

struct pt_regs *guest_cpu_user_regs(void) { return ia64_task_regs(current); }

void raise_actimer_softirq(void)
{
	raise_softirq(AC_TIMER_SOFTIRQ);
}

#ifndef CONFIG_VTI
unsigned long
__gpfn_to_mfn_foreign(struct domain *d, unsigned long gpfn)
{
	if (d == dom0)
		return(gpfn);
	else {
		unsigned long pte = lookup_domain_mpa(d,gpfn << PAGE_SHIFT);
		if (!pte) {
printk("__gpfn_to_mfn_foreign: bad gpfn. spinning...\n");
while(1);
			return 0;
		}
		return ((pte & _PFN_MASK) >> PAGE_SHIFT);
	}
}

u32
__mfn_to_gpfn(struct domain *d, unsigned long frame)
{
	// FIXME: is this right?
if ((frame << PAGE_SHIFT) & _PAGE_PPN_MASK) {
printk("__mfn_to_gpfn: bad frame. spinning...\n");
while(1);
}
	return frame;
}
#endif

unsigned long __hypercall_create_continuation(
	unsigned int op, unsigned int nr_args, ...)
{
	printf("__hypercall_create_continuation: not implemented!!!\n");
}

///////////////////////////////

///////////////////////////////
// from arch/x86/apic.c
///////////////////////////////

int reprogram_ac_timer(s_time_t timeout)
{
	struct vcpu *v = current;

#ifdef CONFIG_VTI
	if(VMX_DOMAIN(v))
		return 1;
#endif // CONFIG_VTI
	local_cpu_data->itm_next = timeout;
	if (is_idle_task(v->domain)) vcpu_safe_set_itm(timeout);
	else vcpu_set_next_timer(current);
	return 1;
}

///////////////////////////////
// from arch/ia64/page_alloc.c
///////////////////////////////
DEFINE_PER_CPU(struct page_state, page_states) = {0};
unsigned long totalram_pages;

void __mod_page_state(unsigned offset, unsigned long delta)
{
	unsigned long flags;
	void* ptr;

	local_irq_save(flags);
	ptr = &__get_cpu_var(page_states);
	*(unsigned long*)(ptr + offset) += delta;
	local_irq_restore(flags);
}

///////////////////////////////
// from arch/x86/flushtlb.c
///////////////////////////////

u32 tlbflush_clock;
u32 tlbflush_time[NR_CPUS];

///////////////////////////////
// from arch/x86/memory.c
///////////////////////////////

void init_percpu_info(void)
{
	dummy();
    //memset(percpu_info, 0, sizeof(percpu_info));
}

void free_page_type(struct pfn_info *page, unsigned int type)
{
	dummy();
}

///////////////////////////////
// from arch/ia64/traps.c
///////////////////////////////

void show_registers(struct pt_regs *regs)
{
	printf("*** ADD REGISTER DUMP HERE FOR DEBUGGING\n");
}

///////////////////////////////
// from common/keyhandler.c
///////////////////////////////
void dump_pageframe_info(struct domain *d)
{
	printk("dump_pageframe_info not implemented\n");
}

///////////////////////////////
// called from arch/ia64/head.S
///////////////////////////////

void console_print(char *msg)
{
	printk("console_print called, how did start_kernel return???\n");
}

void kernel_thread_helper(void)
{
	printk("kernel_thread_helper not implemented\n");
	dummy();
}

void sys_exit(void)
{
	printk("sys_exit not implemented\n");
	dummy();
}

////////////////////////////////////
// called from unaligned.c
////////////////////////////////////

void die_if_kernel(char *str, struct pt_regs *regs, long err) /* __attribute__ ((noreturn)) */
{
	printk("die_if_kernel: called, not implemented\n");
}

long
ia64_peek (struct task_struct *child, struct switch_stack *child_stack,
	   unsigned long user_rbs_end, unsigned long addr, long *val)
{
	printk("ia64_peek: called, not implemented\n");
}

long
ia64_poke (struct task_struct *child, struct switch_stack *child_stack,
	   unsigned long user_rbs_end, unsigned long addr, long val)
{
	printk("ia64_poke: called, not implemented\n");
}

void
ia64_sync_fph (struct task_struct *task)
{
	printk("ia64_sync_fph: called, not implemented\n");
}

void
ia64_flush_fph (struct task_struct *task)
{
	printk("ia64_flush_fph: called, not implemented\n");
}

////////////////////////////////////
// called from irq_ia64.c:init_IRQ()
//   (because CONFIG_IA64_HP_SIM is specified)
////////////////////////////////////
void hpsim_irq_init(void) { }


// accomodate linux extable.c
//const struct exception_table_entry *
void *search_module_extables(unsigned long addr) { return NULL; }
void *__module_text_address(unsigned long addr) { return NULL; }
void *module_text_address(unsigned long addr) { return NULL; }

void cs10foo(void) {}
void cs01foo(void) {}

// context_switch
void context_switch(struct vcpu *prev, struct vcpu *next)
{
//printk("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
//printk("@@@@@@ context switch from domain %d (%x) to domain %d (%x)\n",
//prev->domain->domain_id,(long)prev&0xffffff,next->domain->domain_id,(long)next&0xffffff);
//if (prev->domain->domain_id == 1 && next->domain->domain_id == 0) cs10foo();
//if (prev->domain->domain_id == 0 && next->domain->domain_id == 1) cs01foo();
//printk("@@sw %d->%d\n",prev->domain->domain_id,next->domain->domain_id);
#ifdef CONFIG_VTI
	unsigned long psr;
	/* Interrupt is enabled after next task is chosen.
	 * So we have to disable it for stack switch.
	 */
	local_irq_save(psr);
	vtm_domain_out(prev);
	/* Housekeeping for prev domain */
#endif // CONFIG_VTI

	switch_to(prev,next,prev);
#ifdef CONFIG_VTI
	/* Post-setup for new domain */
	 vtm_domain_in(current);
	local_irq_restore(psr);
#endif // CONFIG_VTI
// leave this debug for now: it acts as a heartbeat when more than
// one domain is active
{
static long cnt[16] = { 50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50};
static int i = 100;
int id = ((struct vcpu *)current)->domain->domain_id & 0xf;
if (!cnt[id]--) { printk("%x",id); cnt[id] = 500; }
if (!i--) { printk("+",id); cnt[id] = 1000; }
}
	clear_bit(_VCPUF_running, &prev->vcpu_flags);
	//if (!is_idle_task(next->domain) )
		//send_guest_virq(next, VIRQ_TIMER);
#ifdef CONFIG_VTI
	if (VMX_DOMAIN(current))
		vmx_load_all_rr(current);
	return;
#else // CONFIG_VTI
	if (!is_idle_task(current->domain)) {
		load_region_regs(current);
		if (vcpu_timer_expired(current)) vcpu_pend_timer(current);
	}
	if (vcpu_timer_expired(current)) vcpu_pend_timer(current);
#endif // CONFIG_VTI
}

void continue_running(struct vcpu *same)
{
    /* nothing to do */
}

void panic_domain(struct pt_regs *regs, const char *fmt, ...)
{
	va_list args;
	char buf[128];
	struct vcpu *v = current;
	static volatile int test = 1;	// so can continue easily in debug
	extern spinlock_t console_lock;
	unsigned long flags;
    
loop:
	printf("$$$$$ PANIC in domain %d (k6=%p): ",
		v->domain->domain_id, ia64_get_kr(IA64_KR_CURRENT));
	va_start(args, fmt);
	(void)vsnprintf(buf, sizeof(buf), fmt, args);
	va_end(args);
	printf(buf);
	if (regs) show_registers(regs);
	domain_pause_by_systemcontroller(current->domain);
	v->domain->shutdown_code = SHUTDOWN_crash;
	set_bit(_DOMF_shutdown, v->domain->domain_flags);
	if (v->domain->domain_id == 0) {
		int i = 1000000000L;
		// if domain0 crashes, just periodically print out panic
		// message to make post-mortem easier
		while(i--);
		goto loop;
	}
}