nvdimm acpi: emulate dsm method
Emulate dsm method after IO VM-exit Currently, we only introduce the framework and no function is actually supported Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									18c440e1e1
								
							
						
					
					
						commit
						f7df22de56
					
				@ -390,15 +390,71 @@ struct NvdimmDsmOut {
 | 
				
			|||||||
} QEMU_PACKED;
 | 
					} QEMU_PACKED;
 | 
				
			||||||
typedef struct NvdimmDsmOut NvdimmDsmOut;
 | 
					typedef struct NvdimmDsmOut NvdimmDsmOut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct NvdimmDsmFunc0Out {
 | 
				
			||||||
 | 
					    /* the size of buffer filled by QEMU. */
 | 
				
			||||||
 | 
					     uint32_t len;
 | 
				
			||||||
 | 
					     uint32_t supported_func;
 | 
				
			||||||
 | 
					} QEMU_PACKED;
 | 
				
			||||||
 | 
					typedef struct NvdimmDsmFunc0Out NvdimmDsmFunc0Out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct NvdimmDsmFuncNoPayloadOut {
 | 
				
			||||||
 | 
					    /* the size of buffer filled by QEMU. */
 | 
				
			||||||
 | 
					     uint32_t len;
 | 
				
			||||||
 | 
					     uint32_t func_ret_status;
 | 
				
			||||||
 | 
					} QEMU_PACKED;
 | 
				
			||||||
 | 
					typedef struct NvdimmDsmFuncNoPayloadOut NvdimmDsmFuncNoPayloadOut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint64_t
 | 
					static uint64_t
 | 
				
			||||||
nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
 | 
					nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    nvdimm_debug("BUG: we never read _DSM IO Port.\n");
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 | 
					nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    NvdimmDsmIn *in;
 | 
				
			||||||
 | 
					    hwaddr dsm_mem_addr = val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    nvdimm_debug("dsm memory address %#" HWADDR_PRIx ".\n", dsm_mem_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * The DSM memory is mapped to guest address space so an evil guest
 | 
				
			||||||
 | 
					     * can change its content while we are doing DSM emulation. Avoid
 | 
				
			||||||
 | 
					     * this by copying DSM memory to QEMU local memory.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    in = g_malloc(TARGET_PAGE_SIZE);
 | 
				
			||||||
 | 
					    cpu_physical_memory_read(dsm_mem_addr, in, TARGET_PAGE_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    le32_to_cpus(&in->revision);
 | 
				
			||||||
 | 
					    le32_to_cpus(&in->function);
 | 
				
			||||||
 | 
					    le32_to_cpus(&in->handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    nvdimm_debug("Revision %#x Handler %#x Function %#x.\n", in->revision,
 | 
				
			||||||
 | 
					                 in->handle, in->function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * function 0 is called to inquire which functions are supported by
 | 
				
			||||||
 | 
					     * OSPM
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    if (in->function == 0) {
 | 
				
			||||||
 | 
					        NvdimmDsmFunc0Out func0 = {
 | 
				
			||||||
 | 
					            .len = cpu_to_le32(sizeof(func0)),
 | 
				
			||||||
 | 
					             /* No function supported other than function 0 */
 | 
				
			||||||
 | 
					            .supported_func = cpu_to_le32(0),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        cpu_physical_memory_write(dsm_mem_addr, &func0, sizeof func0);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        /* No function except function 0 is supported yet. */
 | 
				
			||||||
 | 
					        NvdimmDsmFuncNoPayloadOut out = {
 | 
				
			||||||
 | 
					            .len = cpu_to_le32(sizeof(out)),
 | 
				
			||||||
 | 
					            .func_ret_status = cpu_to_le32(1)  /* Not Supported */,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        cpu_physical_memory_write(dsm_mem_addr, &out, sizeof(out));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_free(in);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const MemoryRegionOps nvdimm_dsm_ops = {
 | 
					static const MemoryRegionOps nvdimm_dsm_ops = {
 | 
				
			||||||
 | 
				
			|||||||
@ -25,6 +25,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "hw/mem/pc-dimm.h"
 | 
					#include "hw/mem/pc-dimm.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NVDIMM_DEBUG 0
 | 
				
			||||||
 | 
					#define nvdimm_debug(fmt, ...)                                \
 | 
				
			||||||
 | 
					    do {                                                      \
 | 
				
			||||||
 | 
					        if (NVDIMM_DEBUG) {                                   \
 | 
				
			||||||
 | 
					            fprintf(stderr, "nvdimm: " fmt, ## __VA_ARGS__);  \
 | 
				
			||||||
 | 
					        }                                                     \
 | 
				
			||||||
 | 
					    } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TYPE_NVDIMM             "nvdimm"
 | 
					#define TYPE_NVDIMM             "nvdimm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NVDIMM_DSM_MEM_FILE     "etc/acpi/nvdimm-mem"
 | 
					#define NVDIMM_DSM_MEM_FILE     "etc/acpi/nvdimm-mem"
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user