Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Added intial cut at IDE disk support
Jack Lange [Fri, 3 Apr 2009 18:07:43 +0000 (13:07 -0500)]
palacios/build/Makefile
palacios/include/devices/ide.h
palacios/include/devices/ram_hd.h [new file with mode: 0644]
palacios/src/devices/atapi.h
palacios/src/devices/ide.c
palacios/src/devices/ram_hd.c [new file with mode: 0644]
palacios/src/palacios/vmm_config.c

index f243949..46fcc40 100644 (file)
@@ -331,6 +331,7 @@ DEVICES_OBJS := \
        devices/para_net.o \
        devices/ide.o \
        devices/ram_cd.o \
+       devices/ram_hd.o \
 
 #      devices/cdrom.o \
 #      devices/ramdisk.o \
index 4dce588..e0356b2 100644 (file)
@@ -24,6 +24,9 @@
 #include <palacios/vm_dev.h>
 
 
+#define ATAPI_BLOCK_SIZE 2048
+#define IDE_SECTOR_SIZE 512
+
 typedef enum {IDE_DISK, IDE_CDROM, IDE_NONE} v3_ide_dev_type_t;
 
 struct v3_ide_cd_ops {
@@ -35,7 +38,9 @@ struct v3_ide_cd_ops {
 
 
 struct v3_ide_hd_ops {
-    
+    uint32_t (*get_capacity)(void * private_data);
+    // Reads always operate on 2048 byte blocks
+    int (*read)(uint8_t * buf, int count, int lba, void * private_data);    
 
 };
 
diff --git a/palacios/include/devices/ram_hd.h b/palacios/include/devices/ram_hd.h
new file mode 100644 (file)
index 0000000..77adf3e
--- /dev/null
@@ -0,0 +1,36 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __DEVICES_RAM_HD_H__
+#define __DEVICES_RAM_HD_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vm_dev.h>
+
+
+struct vm_device * v3_create_ram_hd(struct vm_device * ide, 
+                                   uint_t bus, uint_t drive, 
+                                   addr_t ramdisk, uint32_t size);
+
+
+
+#endif
+
+#endif
index 3d98a75..3407101 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 #define ATAPI_PACKET_SIZE 12
-#define ATAPI_BLOCK_SIZE 2048
 
 #include "atapi-types.h"
 
index 43858a4..3605050 100644 (file)
@@ -216,6 +216,10 @@ struct ide_internal {
 
 
 
+
+
+/* Utility functions */
+
 static inline uint16_t be_to_le_16(const uint16_t val) {
     uint8_t * buf = (uint8_t *)&val;
     return (buf[0] << 8) | (buf[1]) ;
@@ -265,6 +269,7 @@ static inline int is_lba_enabled(struct ide_channel * channel) {
 }
 
 
+/* Drive Commands */
 static void ide_raise_irq(struct vm_device * dev, struct ide_channel * channel) {
     if (channel->ctrl_reg.irq_disable == 0) {
        PrintDebug("Raising IDE Interrupt %d\n", channel->irq);
@@ -326,11 +331,89 @@ static void ide_abort_command(struct vm_device * dev, struct ide_channel * chann
 }
 
 
-// Include the ATAPI interface handlers
+
+static void ide_identify_device(struct ide_drive * drive) {
+    struct ide_drive_id * drive_id = (struct ide_drive_id *)(drive->data_buf);
+    const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0";
+    const char* firmware = "ALPHA1  ";
+
+    drive->transfer_length = 512;
+    drive->transfer_index = 0;
+
+
+    memset(drive_id->buf, 0, sizeof(drive_id->buf));
+
+    drive_id->fixed_drive = 1;
+    drive_id->removable_media = 0;
+
+    // Black magic...
+    drive_id->disk_speed1 = 1;
+    drive_id->disk_speed3 = 1;
+
+    drive_id->cdrom_flag = 0;
+
+    // Make it the simplest drive possible (1 head, 1 cyl, 1 sect/track)
+    drive_id->num_cylinders = 1;
+    drive_id->num_heads = 1;
+    drive_id->bytes_per_track = IDE_SECTOR_SIZE;
+    drive_id->bytes_per_sector = IDE_SECTOR_SIZE;
+    drive_id->sectors_per_track = 1;
+
+
+    // These buffers do not contain a terminating "\0"
+    memcpy(drive_id->serial_num, serial_number, strlen(serial_number));
+    memcpy(drive_id->firmware_rev, firmware, strlen(firmware));
+    memcpy(drive_id->model_num, drive->model, 40);
+
+    // 32 bits access
+    drive_id->dword_io = 1;
+
+    // enable DMA access
+    drive_id->dma_enable = 1;
+
+    // enable LBA access
+    drive_id->lba_enable = 1;
+    
+    // Drive Capacity
+    drive_id->lba_capacity = drive->hd_ops->get_capacity(drive->private_data);
+
+    drive_id->rw_multiples = 0x80ff;
+
+    // words 64-70, 54-58 valid
+    drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
+
+    // copied from CFA540A
+    drive_id->buf[63] = 0x0103; // variable (DMA stuff)
+    //drive_id->buf[63] = 0x0000; // variable (DMA stuff)
+    
+    //    drive_id->buf[64] = 0x0001; // PIO
+    drive_id->buf[65] = 0x00b4;
+    drive_id->buf[66] = 0x00b4;
+    drive_id->buf[67] = 0x012c;
+    drive_id->buf[68] = 0x00b4;
+
+    drive_id->buf[71] = 30; // faked
+    drive_id->buf[72] = 30; // faked
+
+    //    drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
+    drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
+
+    drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
+}
+
+
+
+
+
+
+
+
+/* ATAPI functions */
 #include "atapi.h"
 
 
 
+/* IO Operations */
 static int dma_read(struct vm_device * dev, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     struct ide_dma_prd prd_entry;
@@ -593,8 +676,12 @@ static int write_cmd_port(ushort_t port, void * src, uint_t length, struct vm_de
                // JRL: Should we abort here?
                ide_abort_command(dev, channel);
            } else {
-               PrintError("IDE Disks currently not implemented\n");
-               return -1;
+               ide_identify_device(drive);
+
+               channel->error_reg.val = 0;
+               channel->status.val = 0x58;
+
+               ide_raise_irq(dev, channel);
            }
            break;
 
@@ -1234,3 +1321,6 @@ int v3_ide_register_harddisk(struct vm_device * ide_dev,
 
     return 0;
 }
+
+
+
diff --git a/palacios/src/devices/ram_hd.c b/palacios/src/devices/ram_hd.c
new file mode 100644 (file)
index 0000000..86554d6
--- /dev/null
@@ -0,0 +1,108 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <devices/ram_hd.h>
+#include <devices/ide.h>
+
+
+struct hd_state {
+    addr_t disk_image;
+    uint32_t capacity; // in bytes
+
+    struct vm_device * ide;
+
+    uint_t bus;
+    uint_t drive;
+};
+
+
+// HDs always read 2048 byte blocks... ?
+static int hd_read(uint8_t * buf, int count, int lba,  void * private_data) {
+    struct vm_device * hd_dev = (struct vm_device *)private_data;
+    struct hd_state * hd = (struct hd_state *)(hd_dev->private_data);
+    int offset = lba * IDE_SECTOR_SIZE;
+    int length = ((offset + count) > hd->capacity) ? (hd->capacity - offset) : count;
+
+    PrintDebug("Reading RAM HD at (LBA=%d) offset %d (length=%d)\n", lba, offset, length);
+
+    memcpy(buf, (uint8_t *)(hd->disk_image + offset), length);
+
+    // Pad out the rest of the buffer with 0's
+    //    memset(buf + length, 0, IDE_SECTOR_SIZE - length);
+
+    return 0;
+}
+
+
+static uint32_t hd_get_capacity(void * private_data) {
+    struct vm_device * hd_dev = (struct vm_device *)private_data;
+    struct hd_state * hd = (struct hd_state *)(hd_dev->private_data);
+    PrintDebug("Querying RAM HD capacity (bytes=%d) (ret = %d)\n", 
+              hd->capacity, (hd->capacity + IDE_SECTOR_SIZE - 1) / IDE_SECTOR_SIZE);
+    return (hd->capacity + IDE_SECTOR_SIZE - 1) / IDE_SECTOR_SIZE;
+}
+
+static struct v3_ide_hd_ops hd_ops = {
+    .read = hd_read, 
+    .get_capacity = hd_get_capacity,
+};
+
+
+static int hd_init(struct vm_device * dev) {
+    struct hd_state * hd = (struct hd_state *)(dev->private_data);
+
+    if (v3_ide_register_harddisk(hd->ide, hd->bus, hd->drive, "V3-RAM-HD", &hd_ops, dev) == -1) {
+       return -1;
+    }
+    
+    return 0;
+}
+
+
+static int hd_deinit(struct vm_device * dev) {
+    return 0;
+}
+
+static struct vm_device_ops dev_ops = {
+    .init = hd_init, 
+    .deinit = hd_deinit,
+    .reset = NULL,
+    .start = NULL,
+    .stop = NULL,
+};
+
+struct vm_device * v3_create_ram_hd(struct vm_device * ide, 
+                                   uint_t bus, uint_t drive, 
+                                   addr_t ramdisk, uint32_t size) {
+    struct hd_state * hd = (struct hd_state *)V3_Malloc(sizeof(struct hd_state));
+
+    PrintDebug("Registering Ram HDD at %p (size=%d)\n", (void *)ramdisk, size);
+
+    hd->disk_image = ramdisk;
+    hd->capacity = size;
+
+    hd->ide = ide;
+    hd->bus = bus;
+    hd->drive = drive;
+       
+    struct vm_device * hd_dev = v3_create_device("RAM-HD", &dev_ops, hd);
+
+    return hd_dev;
+}
index be73f33..75e7834 100644 (file)
@@ -35,6 +35,7 @@
 #include <devices/generic.h>
 #include <devices/ide.h>
 #include <devices/ram_cd.h>
+#include <devices/ram_hd.h>
 #include <devices/bochs_debug.h>
 #include <devices/os_debug.h>
 #include <devices/apic.h>
@@ -280,7 +281,8 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf
 
 static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
     struct vm_device * ide = NULL;
-    struct vm_device * ram_cd = NULL;
+    //    struct vm_device * ram_cd = NULL;
+    struct vm_device * ram_hd = NULL;
     struct vm_device * pci = v3_create_pci();
     struct vm_device * nvram = v3_create_nvram();
     //struct vm_device * timer = v3_create_timer();
@@ -303,7 +305,10 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
 
     if (use_ramdisk) {
        PrintDebug("Creating Ramdisk\n");
-       ram_cd = v3_create_ram_cd(ide, 0, 0, 
+       //      ram_cd = v3_create_ram_cd(ide, 0, 0, 
+       //                        (addr_t)(config_ptr->ramdisk), 
+       //                        config_ptr->ramdisk_size);
+       ram_hd = v3_create_ram_hd(ide, 0, 0, 
                                  (addr_t)(config_ptr->ramdisk), 
                                  config_ptr->ramdisk_size);
     }
@@ -333,7 +338,8 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
     v3_attach_device(info, ide);
 
     if (use_ramdisk) {
-       v3_attach_device(info, ram_cd);
+       //      v3_attach_device(info, ram_cd);
+       v3_attach_device(info, ram_hd);
     }
 
     if (use_generic) {