static void deinit_print_buffers(void)
{
int i;
+
for (i=0;i<NR_CPUS;i++) {
if (print_buffer[i]) {
kfree(print_buffer[i]);
}
}
-static int init_print_buffers(int num_cpus)
+static int init_print_buffers(void)
{
int i;
#if !V3_PRINTK_OLD_STYLE_OUTPUT
- for (i=0;i<num_cpus;i++) {
+ for (i=0;i<NR_CPUS;i++) {
print_buffer[i] = kmalloc(V3_PRINTK_BUF_SIZE,GFP_KERNEL);
if (!print_buffer[i]) {
ERROR("Cannot allocate print buffer for cpu %d\n",i);
* Allocates a contiguous region of pages of the requested size.
* Returns the physical address of the first page in the region.
*/
-static void * palacios_allocate_pages(int num_pages, unsigned int alignment) {
+void *palacios_allocate_pages(int num_pages, unsigned int alignment) {
void * pg_addr = NULL;
pg_addr = (void *)alloc_palacios_pgs(num_pages, alignment);
* a single call while palacios_free_page() only frees a single page.
*/
-static void palacios_free_pages(void * page_paddr, int num_pages) {
+void palacios_free_pages(void * page_paddr, int num_pages) {
pg_frees += num_pages;
free_palacios_pgs((uintptr_t)page_paddr, num_pages);
}
* Allocates 'size' bytes of kernel memory.
* Returns the kernel virtual address of the memory allocated.
*/
-static void *
+void *
palacios_alloc(unsigned int size) {
void * addr = NULL;
} else {
addr = kmalloc(size, GFP_KERNEL);
}
- mallocs++;
+
+ if (addr) {
+ mallocs++;
+ }
-
return addr;
}
/**
* Frees memory that was previously allocated by palacios_alloc().
*/
-static void
+void
palacios_free(
void * addr
)
/**
* Converts a kernel virtual address to the corresponding physical address.
*/
-static void *
+void *
palacios_vaddr_to_paddr(
void * vaddr
)
/**
* Converts a physical address to the corresponding kernel virtual address.
*/
-static void *
+void *
palacios_paddr_to_vaddr(
void * paddr
)
/**
* Runs a function on the specified CPU.
*/
-
-// For now, do call only on local CPU
static void
palacios_xcall(
int cpu_id,
ret = thread_info->fn(thread_info->arg);
- INFO("Palacios Thread (%s) EXITTING\n", thread_info->name);
+ INFO("Palacios Thread (%s) EXITING\n", thread_info->name);
kfree(thread_info);
// handle cleanup
/**
* Creates a kernel thread.
*/
-static void *
+void *
palacios_start_kernel_thread(
int (*fn) (void * arg),
void * arg,
/**
* Starts a kernel thread on the specified CPU.
*/
-static void *
+void *
palacios_start_thread_on_cpu(int cpu_id,
int (*fn)(void * arg),
void * arg,
* The thread will be running on target CPU on return
* non-zero return means failure
*/
-static int
+int
palacios_move_thread_to_cpu(int new_cpu_id,
void * thread_ptr) {
struct task_struct * thread = (struct task_struct *)thread_ptr;
/**
* Returns the CPU frequency in kilohertz.
*/
-static unsigned int
+unsigned int
palacios_get_cpu_khz(void)
{
INFO("cpu_khz is %u\n", cpu_khz);
/**
* Yield the CPU so other host OS tasks can run.
+ * This will return immediately if there is no other thread that is runnable
+ * And there is no real bound on how long it will yield
*/
-static void
+void
palacios_yield_cpu(void)
{
schedule();
return;
}
+/**
+ * Yield the CPU so other host OS tasks can run.
+ * Given now immediately if there is no other thread that is runnable
+ * And there is no real bound on how long it will yield
+ */
+void palacios_yield_cpu_timed(unsigned int us)
+{
+ unsigned int jiffies = 1000000U * HZ / us;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ schedule_timeout(jiffies);
+
+}
/**
* Allocates a mutex.
* Returns NULL on failure.
*/
-static void *
+void *
palacios_mutex_alloc(void)
{
spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
/**
* Frees a mutex.
*/
-static void
+void
palacios_mutex_free(void * mutex) {
kfree(mutex);
}
/**
* Locks a mutex.
*/
-static void
+void
palacios_mutex_lock(void * mutex, int must_spin) {
spin_lock((spinlock_t *)mutex);
}
+
+/**
+ * Locks a mutex, disabling interrupts on this core
+ */
+void *
+palacios_mutex_lock_irqsave(void * mutex, int must_spin) {
+
+ unsigned long flags;
+
+ spin_lock_irqsave((spinlock_t *)mutex,flags);
+
+ return (void *)flags;
+}
+
+
/**
* Unlocks a mutex.
*/
-static void
+void
palacios_mutex_unlock(
void * mutex
)
spin_unlock((spinlock_t *)mutex);
}
+
+/**
+ * Unlocks a mutex.
+ */
+void
+palacios_mutex_unlock_irqrestore(void *mutex, void *flags)
+{
+ // This is correct, flags is opaque
+ spin_unlock_irqrestore((spinlock_t *)mutex,(unsigned long)flags);
+}
+
/**
* Structure used by the Palacios hypervisor to interface with the host kernel.
*/
.get_cpu_khz = palacios_get_cpu_khz,
.start_kernel_thread = palacios_start_kernel_thread,
.yield_cpu = palacios_yield_cpu,
+ .yield_cpu_timed = palacios_yield_cpu_timed,
.mutex_alloc = palacios_mutex_alloc,
.mutex_free = palacios_mutex_free,
.mutex_lock = palacios_mutex_lock,
.mutex_unlock = palacios_mutex_unlock,
+ .mutex_lock_irqsave = palacios_mutex_lock_irqsave,
+ .mutex_unlock_irqrestore= palacios_mutex_unlock_irqrestore,
.get_cpu = palacios_get_cpu,
.interrupt_cpu = palacios_interrupt_cpu,
.call_on_cpu = palacios_xcall,
memset(irq_to_guest_map, 0, sizeof(struct v3_vm_info *) * 256);
- if (init_print_buffers(num_cpus)) {
+ if (init_print_buffers()) {
ERROR("Cannot initialize print buffers\n");
kfree(cpu_mask);
return -1;
int palacios_vmm_exit( void );
-// Exported stubs, for use in other palacios components, like vnet
-void palacios_print(const char *fmt, ...);
+// This is how a component finds the proc dir we are using for global state
+struct proc_dir_entry *palacios_get_procdir(void);
+
+// Selected exported stubs, for use in other palacios components, like vnet
+// The idea is that everything uses the same stubs
+void palacios_print(const char *fmt, ...);
+void *palacios_allocate_pages(int num_pages, unsigned int alignment);
+void palacios_free_pages(void *page_addr, int num_pages);
+void *palacios_alloc(unsigned int size);
+void palacios_free(void *);
+void *palacios_vaddr_to_paddr(void *vaddr);
+void *palacios_paddr_to_vaddr(void *paddr);
+void *palacios_start_kernel_thread(int (*fn)(void * arg), void *arg, char *thread_name);
+void *palacios_start_thread_on_cpu(int cpu_id, int (*fn)(void * arg), void *arg, char *thread_name);
+int palacios_move_thread_to_cpu(int new_cpu_id, void *thread_ptr);
+void palacios_yield_cpu(void);
+void palacios_yield_cpu_timed(unsigned int us);
unsigned int palacios_get_cpu(void);
+unsigned int palacios_get_cpu_khz(void);
+void *palacios_mutex_alloc(void);
+void palacios_mutex_free(void *mutex);
+void palacios_mutex_lock(void *mutex, int must_spin);
+void palacios_mutex_unlock(void *mutex);
+void *palacios_mutex_lock_irqsave(void *mutex, int must_spin);
+void palacios_mutex_unlock_irqrestore(void *mutex, void *flags);