mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
Merged.
This commit is contained in:
commit
39dbaabab7
27 files changed
+491
-460
No files matched your search
@@ -1059,6 +1059,21 @@ This path contains:
|
||||
\item[domain] the name of the frontend
|
||||
\end{description}
|
||||
\end{description}
|
||||
|
||||
\item[vtpm/] a directory containin vtpm backends
|
||||
\begin{description}
|
||||
\item[$<$domid$>$/] a directory containing vtpm's for domid
|
||||
\begin{description}
|
||||
\item[$<$vtpm number$>$/] a directory for each vtpm
|
||||
\item[frontend-id] the domain id of the frontend
|
||||
\item[frontend] the path to the frontend
|
||||
\item[instance] the instance of the virtual TPM that is used
|
||||
\item[pref{\textunderscore}instance] the instance number as given in the VM configuration file;
|
||||
may be different from {\bf instance}
|
||||
\item[domain] the name of the domain of the frontend
|
||||
\end{description}
|
||||
\end{description}
|
||||
|
||||
\end{description}
|
||||
|
||||
\item[device/] a directory containing the frontend devices for the
|
||||
@@ -1094,6 +1109,18 @@ This path contains:
|
||||
\item[event-channel] the event channel used for the two ring queues
|
||||
\end{description}
|
||||
\end{description}
|
||||
|
||||
\item[vtpm/] a directory containing the vtpm frontend device for the
|
||||
domain
|
||||
\begin{description}
|
||||
\item[$<$id$>$] a directory for vtpm id frontend device for the domain
|
||||
\begin{description}
|
||||
\item[backend-id] the backend domain id
|
||||
\item[backend] a path to the backend's store entry
|
||||
\item[ring-ref] the grant table reference for the tx/rx ring
|
||||
\item[event-channel] the event channel used for the ring
|
||||
\end{description}
|
||||
\end{description}
|
||||
|
||||
\item[device-misc/] miscellanous information for devices
|
||||
\begin{description}
|
||||
@@ -1450,6 +1477,76 @@ The fields are as follows:
|
||||
value of {\tt first\_sect}.
|
||||
\end{description}
|
||||
|
||||
\section{Virtual TPM}
|
||||
|
||||
Virtual TPM (VTPM) support provides TPM functionality to each virtual
|
||||
machine that requests this functionality in its configuration file.
|
||||
The interface enables domains to access therr own private TPM like it
|
||||
was a hardware TPM built into the machine.
|
||||
|
||||
The virtual TPM interface is implemented as a split driver,
|
||||
similar to the network and block interfaces described above.
|
||||
The user domain hosting the frontend exports a character device /dev/tpm0
|
||||
to user-level applications for communicating with the virtual TPM.
|
||||
This is the same device interface that is also offered if a hardware TPM
|
||||
is available in the system. The backend provides a single interface
|
||||
/dev/vtpm where the virtual TPM is waiting for commands from all domains
|
||||
that have located their backend in a given domain.
|
||||
|
||||
\subsection{Data Transfer}
|
||||
|
||||
A single shared memory ring is used between the frontend and backend
|
||||
drivers. TPM requests and responses are sent in pages where a pointer
|
||||
to those pages and other information is placed into the ring such that
|
||||
the backend can map the pages into its memory space using the grant
|
||||
table mechanism.
|
||||
|
||||
The backend driver has been implemented to only accept well-formed
|
||||
TPM requests. To meet this requirement, the length inidicator in the
|
||||
TPM request must correctly indicate the length of the request.
|
||||
Otherwise an error message is automatically sent back by the device driver.
|
||||
|
||||
The virtual TPM implementation listenes for TPM request on /dev/vtpm. Since
|
||||
it must be able to apply the TPM request packet to the virtual TPM instance
|
||||
associated with the virtual machine, a 4-byte virtual TPM instance
|
||||
identifier is prepended to each packet by the backend driver (in network
|
||||
byte order) for internal routing of the request.
|
||||
|
||||
\subsection{Virtual TPM ring interface}
|
||||
|
||||
The TPM protocol is a strict request/response protocol and therefore
|
||||
only one ring is used to send requests from the frontend to the backend
|
||||
and responses on the reverse path.
|
||||
|
||||
The request/response structure is defined as follows:
|
||||
|
||||
\scriptsize
|
||||
\begin{verbatim}
|
||||
typedef struct {
|
||||
unsigned long addr; /* Machine address of packet. */
|
||||
grant_ref_t ref; /* grant table access reference. */
|
||||
uint16_t unused; /* unused */
|
||||
uint16_t size; /* Packet size in bytes. */
|
||||
} tpmif_tx_request_t;
|
||||
\end{verbatim}
|
||||
\normalsize
|
||||
|
||||
The fields are as follows:
|
||||
|
||||
\begin{description}
|
||||
\item[addr] The machine address of the page asscoiated with the TPM
|
||||
request/response; a request/response may span multiple
|
||||
pages
|
||||
\item[ref] The grant table reference associated with the address.
|
||||
\item[size] The size of the remaining packet; up to
|
||||
PAGE{\textunderscore}SIZE bytes can be found in the
|
||||
page referenced by 'addr'
|
||||
\end{description}
|
||||
|
||||
The frontend initially allocates several pages whose addresses
|
||||
are stored in the ring. Only these pages are used for exchange of
|
||||
requests and responses.
|
||||
|
||||
|
||||
\chapter{Further Information}
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg)
|
||||
int ret;
|
||||
|
||||
op.cmd = PHYSDEVOP_APIC_READ;
|
||||
op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
|
||||
op.u.apic_op.offset = reg;
|
||||
op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
|
||||
op.u.apic_op.reg = reg;
|
||||
ret = HYPERVISOR_physdev_op(&op);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -74,8 +74,8 @@ static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsign
|
||||
physdev_op_t op;
|
||||
|
||||
op.cmd = PHYSDEVOP_APIC_WRITE;
|
||||
op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
|
||||
op.u.apic_op.offset = reg;
|
||||
op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
|
||||
op.u.apic_op.reg = reg;
|
||||
op.u.apic_op.value = value;
|
||||
HYPERVISOR_physdev_op(&op);
|
||||
}
|
||||
|
||||
@@ -108,8 +108,8 @@ static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg)
|
||||
int ret;
|
||||
|
||||
op.cmd = PHYSDEVOP_APIC_READ;
|
||||
op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
|
||||
op.u.apic_op.offset = reg;
|
||||
op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
|
||||
op.u.apic_op.reg = reg;
|
||||
ret = HYPERVISOR_physdev_op(&op);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -121,8 +121,8 @@ static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsign
|
||||
physdev_op_t op;
|
||||
|
||||
op.cmd = PHYSDEVOP_APIC_WRITE;
|
||||
op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
|
||||
op.u.apic_op.offset = reg;
|
||||
op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
|
||||
op.u.apic_op.reg = reg;
|
||||
op.u.apic_op.value = value;
|
||||
HYPERVISOR_physdev_op(&op);
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@ int num_frontends = 0;
|
||||
|
||||
LIST_HEAD(tpmif_list);
|
||||
|
||||
tpmif_t *
|
||||
alloc_tpmif(domid_t domid, long int instance)
|
||||
static tpmif_t *alloc_tpmif(domid_t domid, long int instance)
|
||||
{
|
||||
struct page *page;
|
||||
tpmif_t *tpmif;
|
||||
@@ -45,16 +44,14 @@ alloc_tpmif(domid_t domid, long int instance)
|
||||
return tpmif;
|
||||
}
|
||||
|
||||
void
|
||||
free_tpmif(tpmif_t * tpmif)
|
||||
static void free_tpmif(tpmif_t * tpmif)
|
||||
{
|
||||
num_frontends--;
|
||||
list_del(&tpmif->tpmif_list);
|
||||
kmem_cache_free(tpmif_cachep, tpmif);
|
||||
}
|
||||
|
||||
tpmif_t *
|
||||
tpmif_find(domid_t domid, long int instance)
|
||||
tpmif_t *tpmif_find(domid_t domid, long int instance)
|
||||
{
|
||||
tpmif_t *tpmif;
|
||||
|
||||
@@ -72,8 +69,7 @@ tpmif_find(domid_t domid, long int instance)
|
||||
return alloc_tpmif(domid, instance);
|
||||
}
|
||||
|
||||
static int
|
||||
map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
|
||||
static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
|
||||
{
|
||||
int ret;
|
||||
struct gnttab_map_grant_ref op = {
|
||||
@@ -99,8 +95,7 @@ map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_frontend_page(tpmif_t *tpmif)
|
||||
static void unmap_frontend_page(tpmif_t *tpmif)
|
||||
{
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
int ret;
|
||||
@@ -115,14 +110,14 @@ unmap_frontend_page(tpmif_t *tpmif)
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
int
|
||||
tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
|
||||
int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
|
||||
{
|
||||
int err;
|
||||
evtchn_op_t op = {
|
||||
.cmd = EVTCHNOP_bind_interdomain,
|
||||
.u.bind_interdomain.remote_dom = tpmif->domid,
|
||||
.u.bind_interdomain.remote_port = evtchn };
|
||||
.u.bind_interdomain.remote_port = evtchn,
|
||||
};
|
||||
|
||||
if (tpmif->irq) {
|
||||
return 0;
|
||||
@@ -156,8 +151,7 @@ tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
__tpmif_disconnect_complete(void *arg)
|
||||
static void __tpmif_disconnect_complete(void *arg)
|
||||
{
|
||||
tpmif_t *tpmif = (tpmif_t *) arg;
|
||||
|
||||
@@ -172,22 +166,19 @@ __tpmif_disconnect_complete(void *arg)
|
||||
free_tpmif(tpmif);
|
||||
}
|
||||
|
||||
void
|
||||
tpmif_disconnect_complete(tpmif_t * tpmif)
|
||||
void tpmif_disconnect_complete(tpmif_t * tpmif)
|
||||
{
|
||||
INIT_WORK(&tpmif->work, __tpmif_disconnect_complete, (void *)tpmif);
|
||||
schedule_work(&tpmif->work);
|
||||
}
|
||||
|
||||
void __init
|
||||
tpmif_interface_init(void)
|
||||
void __init tpmif_interface_init(void)
|
||||
{
|
||||
tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t),
|
||||
0, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
void __init
|
||||
tpmif_interface_exit(void)
|
||||
void __init tpmif_interface_exit(void)
|
||||
{
|
||||
kmem_cache_destroy(tpmif_cachep);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -602,7 +602,6 @@ tpm_xmit(struct tpm_private *tp,
|
||||
|
||||
tx = &tp->tx->ring[i].req;
|
||||
|
||||
tx->id = i;
|
||||
tx->addr = virt_to_machine(txb->data);
|
||||
tx->size = txb->len;
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "$GDB_MIRROR" ] || GDB_MIRROR="ftp://ftp.gnu.org/gnu/gdb/"
|
||||
|
||||
rm -rf gdb-6.2.1 gdb-6.2.1-linux-i386-xen
|
||||
[ -a gdb-6.2.1.tar.bz2 ] || wget -c ftp://ftp.gnu.org/gnu/gdb/gdb-6.2.1.tar.bz2
|
||||
[ -a gdb-6.2.1.tar.bz2 ] || wget -c "$GDB_MIRROR/gdb-6.2.1.tar.bz2"
|
||||
tar xjf gdb-6.2.1.tar.bz2
|
||||
|
||||
cd gdb-6.2.1-xen-sparse
|
||||
@@ -12,8 +14,10 @@ mkdir gdb-6.2.1-linux-i386-xen
|
||||
cd gdb-6.2.1-linux-i386-xen
|
||||
../gdb-6.2.1/configure
|
||||
|
||||
# some people don't have gmake
|
||||
if which gmake ; then
|
||||
# Use $MAKE if set, else use gmake if present, otherwise use make
|
||||
if [ "$MAKE" ]; then
|
||||
$MAKE
|
||||
elif which gmake ; then
|
||||
gmake -j4
|
||||
else
|
||||
make -j4
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
# Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
#
|
||||
|
||||
# External CFLAGS can do more harm than good.
|
||||
CFLAGS :=
|
||||
|
||||
XEN_ROOT = ../../..
|
||||
include $(XEN_ROOT)/Config.mk
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
# Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
#
|
||||
|
||||
# External CFLAGS can do more harm than good.
|
||||
CFLAGS :=
|
||||
|
||||
XEN_ROOT = ../../..
|
||||
include $(XEN_ROOT)/Config.mk
|
||||
|
||||
|
||||
@@ -274,6 +274,10 @@ class HVMImageHandler(ImageHandler):
|
||||
uname = sxp.child_value(info, 'uname')
|
||||
typedev = sxp.child_value(info, 'dev')
|
||||
(_, vbdparam) = string.split(uname, ':', 1)
|
||||
|
||||
if 'file:' in uname and not os.path.isfile(vbdparam):
|
||||
raise VmError('Disk image does not exist: %s' % vbdparam)
|
||||
|
||||
if 'ioemu:' in typedev:
|
||||
(emtype, vbddev) = string.split(typedev, ':', 1)
|
||||
else:
|
||||
|
||||
@@ -42,10 +42,6 @@ class BlkifController(DevController):
|
||||
"""@see DevController.getDeviceDetails"""
|
||||
|
||||
dev = sxp.child_value(config, 'dev')
|
||||
if 'ioemu:' in dev:
|
||||
return (None,{},{})
|
||||
|
||||
devid = blkif.blkdev_name_to_number(dev)
|
||||
|
||||
(typ, params) = string.split(sxp.child_value(config, 'uname'), ':', 1)
|
||||
back = { 'dev' : dev,
|
||||
@@ -54,7 +50,13 @@ class BlkifController(DevController):
|
||||
'mode' : sxp.child_value(config, 'mode', 'r')
|
||||
}
|
||||
|
||||
front = { 'virtual-device' : "%i" % devid }
|
||||
if 'ioemu:' in dev:
|
||||
(dummy, dev1) = string.split(dev, ':', 1)
|
||||
devid = blkif.blkdev_name_to_number(dev1)
|
||||
front = {}
|
||||
else:
|
||||
devid = blkif.blkdev_name_to_number(dev)
|
||||
front = { 'virtual-device' : "%i" % devid }
|
||||
|
||||
return (devid, back, front)
|
||||
|
||||
|
||||
@@ -74,7 +74,13 @@ TPM_RESULT close_dmi( VTPM_DMI_RESOURCE *dmi_res) {
|
||||
|
||||
close(dmi_res->guest_tx_fh); dmi_res->guest_tx_fh = -1;
|
||||
close(dmi_res->vtpm_tx_fh); dmi_res->vtpm_tx_fh = -1;
|
||||
|
||||
vtpm_globals->connected_dmis--;
|
||||
|
||||
if (vtpm_globals->connected_dmis == 0) {
|
||||
// No more DMI's connected. Close fifo to prevent a broken pipe.
|
||||
close(vtpm_globals->guest_rx_fh);
|
||||
vtpm_globals->guest_rx_fh = -1;
|
||||
}
|
||||
#ifndef MANUAL_DM_LAUNCH
|
||||
if (dmi_res->dmi_id != VTPM_CTL_DM) {
|
||||
if (dmi_res->dmi_pid != 0) {
|
||||
@@ -118,6 +124,7 @@ TPM_RESULT VTPM_Handle_New_DMI( const buffer_t *param_buf) {
|
||||
status = TPM_BAD_PARAMETER;
|
||||
goto abort_egress;
|
||||
} else {
|
||||
vtpm_globals->connected_dmis++; // Put this here so we don't count Dom0
|
||||
BSG_UnpackList( param_buf->bytes, 3,
|
||||
BSG_TYPE_BYTE, &type,
|
||||
BSG_TYPE_UINT32, &domain_id,
|
||||
|
||||
@@ -307,8 +307,8 @@ TPM_RESULT VTPM_SaveService(void) {
|
||||
TPM_RESULT status=TPM_SUCCESS;
|
||||
int fh, dmis=-1;
|
||||
|
||||
BYTE *flat_boot_key, *flat_dmis, *flat_enc;
|
||||
buffer_t clear_flat_global, enc_flat_global;
|
||||
BYTE *flat_boot_key=NULL, *flat_dmis=NULL, *flat_enc=NULL;
|
||||
buffer_t clear_flat_global=NULL_BUF, enc_flat_global=NULL_BUF;
|
||||
UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap);
|
||||
UINT32 bootKeySize = buffer_len(&vtpm_globals->bootKeyWrap);
|
||||
struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes};
|
||||
@@ -328,12 +328,9 @@ TPM_RESULT VTPM_SaveService(void) {
|
||||
sizeof(UINT32) +// storagekeysize
|
||||
storageKeySize, NULL) ); // storage key
|
||||
|
||||
flat_dmis_size = (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0)
|
||||
(sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info
|
||||
|
||||
flat_boot_key = (BYTE *) malloc( boot_key_size );
|
||||
flat_enc = (BYTE *) malloc( sizeof(UINT32) );
|
||||
flat_dmis = (BYTE *) malloc( flat_dmis_size );
|
||||
|
||||
boot_key_size = BSG_PackList(flat_boot_key, 1,
|
||||
BSG_TPM_SIZE32_DATA, &boot_key_pack);
|
||||
@@ -349,9 +346,13 @@ TPM_RESULT VTPM_SaveService(void) {
|
||||
|
||||
BSG_PackConst(buffer_len(&enc_flat_global), 4, flat_enc);
|
||||
|
||||
// Per DMI values to be saved
|
||||
// Per DMI values to be saved (if any exit)
|
||||
if (hashtable_count(vtpm_globals->dmi_map) > 0) {
|
||||
|
||||
flat_dmis_size = (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0)
|
||||
(sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info
|
||||
flat_dmis = (BYTE *) malloc( flat_dmis_size );
|
||||
|
||||
dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);
|
||||
do {
|
||||
dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);
|
||||
|
||||
@@ -754,6 +754,7 @@ TPM_RESULT VTPM_Init_Service() {
|
||||
#ifndef VTPM_MULTI_VM
|
||||
vtpm_globals->vtpm_rx_fh = -1;
|
||||
vtpm_globals->guest_rx_fh = -1;
|
||||
vtpm_globals->connected_dmis = 0;
|
||||
#endif
|
||||
if ((vtpm_globals->dmi_map = create_hashtable(10, hashfunc32, equals32)) == NULL){
|
||||
status = TPM_FAIL;
|
||||
|
||||
@@ -98,6 +98,7 @@ typedef struct tdVTPM_GLOBALS {
|
||||
#ifndef VTPM_MULTI_VM
|
||||
int vtpm_rx_fh;
|
||||
int guest_rx_fh;
|
||||
int connected_dmis; // Used to close guest_rx when no dmis are connected
|
||||
|
||||
pid_t master_pid;
|
||||
#endif
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <xen/sched.h>
|
||||
#include <xen/mm.h>
|
||||
#include <public/version.h>
|
||||
//#include <xen/delay.h>
|
||||
#include <xen/gdbstub.h>
|
||||
#include <xen/compile.h>
|
||||
#include <xen/console.h>
|
||||
#include <xen/serial.h>
|
||||
@@ -360,6 +360,8 @@ printk("About to call __cpu_up(%d)\n",i);
|
||||
smp_cpus_done(max_cpus);
|
||||
#endif
|
||||
|
||||
initialise_gdb(); /* could be moved earlier */
|
||||
|
||||
do_initcalls();
|
||||
printk("About to call sort_main_extable()\n");
|
||||
sort_main_extable();
|
||||
|
||||
+13
-15
@@ -52,20 +52,6 @@ static void ioapic_enable(hvm_vioapic_t *s, uint8_t enable)
|
||||
s->flags &= ~IOAPIC_ENABLE_FLAG;
|
||||
}
|
||||
|
||||
static void ioapic_dump_redir(hvm_vioapic_t *s, uint8_t entry)
|
||||
{
|
||||
RedirStatus redir = s->redirtbl[entry];
|
||||
|
||||
printk("ioapic_dump_redir entry %x vector %x "
|
||||
"deliver_mod %x destmode %x delivestatus %x "
|
||||
"polarity %x remote_irr %x trigmod %x mask %x dest_id %x\n",
|
||||
entry, redir.RedirForm.vector, redir.RedirForm.deliver_mode,
|
||||
redir.RedirForm.destmode, redir.RedirForm.delivestatus,
|
||||
redir.RedirForm.polarity, redir.RedirForm.remoteirr,
|
||||
redir.RedirForm.trigmod, redir.RedirForm.mask,
|
||||
redir.RedirForm.dest_id);
|
||||
}
|
||||
|
||||
#ifdef HVM_DOMAIN_SAVE_RESTORE
|
||||
void ioapic_save(QEMUFile* f, void* opaque)
|
||||
{
|
||||
@@ -534,7 +520,19 @@ void hvm_vioapic_set_irq(struct domain *d, int irq, int level)
|
||||
if (!IOAPICEnabled(s) || s->redirtbl[irq].RedirForm.mask)
|
||||
return;
|
||||
|
||||
ioapic_dump_redir(s, irq);
|
||||
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_set_irq entry %x "
|
||||
"vector %x deliver_mod %x destmode %x delivestatus %x "
|
||||
"polarity %x remote_irr %x trigmod %x mask %x dest_id %x\n",
|
||||
irq,
|
||||
s->redirtbl[irq].RedirForm.vector,
|
||||
s->redirtbl[irq].RedirForm.deliver_mode,
|
||||
s->redirtbl[irq].RedirForm.destmode,
|
||||
s->redirtbl[irq].RedirForm.delivestatus,
|
||||
s->redirtbl[irq].RedirForm.polarity,
|
||||
s->redirtbl[irq].RedirForm.remoteirr,
|
||||
s->redirtbl[irq].RedirForm.trigmod,
|
||||
s->redirtbl[irq].RedirForm.mask,
|
||||
s->redirtbl[irq].RedirForm.dest_id);
|
||||
|
||||
if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
|
||||
uint32_t bit = 1 << irq;
|
||||
|
||||
+29
-45
@@ -1548,8 +1548,9 @@ static inline void check_timer(void)
|
||||
*/
|
||||
apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
|
||||
init_8259A(1);
|
||||
timer_ack = 1;
|
||||
enable_8259A_irq(0);
|
||||
/* XEN: Ripped out the legacy missed-tick logic, so below is not needed. */
|
||||
/*timer_ack = 1;*/
|
||||
/*enable_8259A_irq(0);*/
|
||||
|
||||
pin1 = find_isa_irq_pin(0, mp_INT);
|
||||
apic1 = find_isa_irq_apic(0, mp_INT);
|
||||
@@ -1617,7 +1618,7 @@ static inline void check_timer(void)
|
||||
|
||||
printk(KERN_INFO "...trying to set up timer as ExtINT IRQ...");
|
||||
|
||||
timer_ack = 0;
|
||||
/*timer_ack = 0;*/
|
||||
init_8259A(0);
|
||||
make_8259A_irq(0);
|
||||
apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
|
||||
@@ -1633,16 +1634,6 @@ static inline void check_timer(void)
|
||||
"report. Then try booting with the 'noapic' option");
|
||||
}
|
||||
|
||||
#define NR_IOAPIC_BIOSIDS 256
|
||||
static u8 ioapic_biosid_to_apic_enum[NR_IOAPIC_BIOSIDS];
|
||||
static void store_ioapic_biosid_mapping(void)
|
||||
{
|
||||
u8 apic;
|
||||
memset(ioapic_biosid_to_apic_enum, ~0, NR_IOAPIC_BIOSIDS);
|
||||
for ( apic = 0; apic < nr_ioapics; apic++ )
|
||||
ioapic_biosid_to_apic_enum[mp_ioapics[apic].mpc_apicid] = apic;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* IRQ's that are handled by the PIC in the MPS IOAPIC case.
|
||||
@@ -1654,8 +1645,6 @@ static void store_ioapic_biosid_mapping(void)
|
||||
|
||||
void __init setup_IO_APIC(void)
|
||||
{
|
||||
store_ioapic_biosid_mapping();
|
||||
|
||||
enable_IO_APIC();
|
||||
|
||||
if (acpi_ioapic)
|
||||
@@ -1839,50 +1828,45 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
|
||||
|
||||
#endif /*CONFIG_ACPI_BOOT*/
|
||||
|
||||
|
||||
int ioapic_guest_read(int apicid, int address, u32 *pval)
|
||||
static int ioapic_physbase_to_id(unsigned long physbase)
|
||||
{
|
||||
u32 val;
|
||||
int apicenum;
|
||||
union IO_APIC_reg_00 reg_00;
|
||||
int apic;
|
||||
for ( apic = 0; apic < nr_ioapics; apic++ )
|
||||
if ( mp_ioapics[apic].mpc_apicaddr == physbase )
|
||||
return apic;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval)
|
||||
{
|
||||
int apic;
|
||||
unsigned long flags;
|
||||
|
||||
if ( (apicid >= NR_IOAPIC_BIOSIDS) ||
|
||||
((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) )
|
||||
return -EINVAL;
|
||||
if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )
|
||||
return apic;
|
||||
|
||||
spin_lock_irqsave(&ioapic_lock, flags);
|
||||
val = io_apic_read(apicenum, address);
|
||||
*pval = io_apic_read(apic, reg);
|
||||
spin_unlock_irqrestore(&ioapic_lock, flags);
|
||||
|
||||
/* Rewrite APIC ID to what the BIOS originally specified. */
|
||||
if ( address == 0 )
|
||||
{
|
||||
reg_00.raw = val;
|
||||
reg_00.bits.ID = apicid;
|
||||
val = reg_00.raw;
|
||||
}
|
||||
|
||||
*pval = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ioapic_guest_write(int apicid, int address, u32 val)
|
||||
int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
|
||||
{
|
||||
int apicenum, pin, irq;
|
||||
int apic, pin, irq;
|
||||
struct IO_APIC_route_entry rte = { 0 };
|
||||
struct irq_pin_list *entry;
|
||||
unsigned long flags;
|
||||
|
||||
if ( (apicid >= NR_IOAPIC_BIOSIDS) ||
|
||||
((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) )
|
||||
return -EINVAL;
|
||||
if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )
|
||||
return apic;
|
||||
|
||||
/* Only write to the first half of a route entry. */
|
||||
if ( (address < 0x10) || (address & 1) )
|
||||
if ( (reg < 0x10) || (reg & 1) )
|
||||
return 0;
|
||||
|
||||
pin = (address - 0x10) >> 1;
|
||||
pin = (reg - 0x10) >> 1;
|
||||
|
||||
*(u32 *)&rte = val;
|
||||
rte.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
|
||||
@@ -1898,7 +1882,7 @@ int ioapic_guest_write(int apicid, int address, u32 val)
|
||||
if ( rte.delivery_mode > dest_LowestPrio )
|
||||
{
|
||||
printk("ERROR: Attempt to write weird IOAPIC destination mode!\n");
|
||||
printk(" APIC=%d/%d, lo-reg=%x\n", apicid, pin, val);
|
||||
printk(" APIC=%d/%d, lo-reg=%x\n", apic, pin, val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1923,19 +1907,19 @@ int ioapic_guest_write(int apicid, int address, u32 val)
|
||||
/* Record the pin<->irq mapping. */
|
||||
for ( entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next] )
|
||||
{
|
||||
if ( (entry->apic == apicenum) && (entry->pin == pin) )
|
||||
if ( (entry->apic == apic) && (entry->pin == pin) )
|
||||
break;
|
||||
if ( !entry->next )
|
||||
{
|
||||
add_pin_to_irq(irq, apicenum, pin);
|
||||
add_pin_to_irq(irq, apic, pin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ioapic_lock, flags);
|
||||
io_apic_write(apicenum, 0x10 + 2 * pin, *(((int *)&rte) + 0));
|
||||
io_apic_write(apicenum, 0x11 + 2 * pin, *(((int *)&rte) + 1));
|
||||
io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0));
|
||||
io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1));
|
||||
spin_unlock_irqrestore(&ioapic_lock, flags);
|
||||
|
||||
return 0;
|
||||
|
||||
+12
-4
@@ -11,8 +11,12 @@
|
||||
#include <public/xen.h>
|
||||
#include <public/physdev.h>
|
||||
|
||||
extern int ioapic_guest_read(int apicid, int address, u32 *pval);
|
||||
extern int ioapic_guest_write(int apicid, int address, u32 pval);
|
||||
extern int
|
||||
ioapic_guest_read(
|
||||
unsigned long physbase, unsigned int reg, u32 *pval);
|
||||
extern int
|
||||
ioapic_guest_write(
|
||||
unsigned long physbase, unsigned int reg, u32 pval);
|
||||
|
||||
/*
|
||||
* Demuxing hypercall.
|
||||
@@ -49,7 +53,9 @@ long do_physdev_op(struct physdev_op *uop)
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
break;
|
||||
ret = ioapic_guest_read(
|
||||
op.u.apic_op.apic, op.u.apic_op.offset, &op.u.apic_op.value);
|
||||
op.u.apic_op.apic_physbase,
|
||||
op.u.apic_op.reg,
|
||||
&op.u.apic_op.value);
|
||||
break;
|
||||
|
||||
case PHYSDEVOP_APIC_WRITE:
|
||||
@@ -57,7 +63,9 @@ long do_physdev_op(struct physdev_op *uop)
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
break;
|
||||
ret = ioapic_guest_write(
|
||||
op.u.apic_op.apic, op.u.apic_op.offset, op.u.apic_op.value);
|
||||
op.u.apic_op.apic_physbase,
|
||||
op.u.apic_op.reg,
|
||||
op.u.apic_op.value);
|
||||
break;
|
||||
|
||||
case PHYSDEVOP_ASSIGN_VECTOR:
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <xen/multiboot.h>
|
||||
#include <xen/domain_page.h>
|
||||
#include <xen/compile.h>
|
||||
#include <xen/gdbstub.h>
|
||||
#include <public/version.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <asm/smp.h>
|
||||
@@ -479,6 +480,8 @@ void __init __start_xen(multiboot_info_t *mbi)
|
||||
printk("Brought up %ld CPUs\n", (long)num_online_cpus());
|
||||
smp_cpus_done(max_cpus);
|
||||
|
||||
initialise_gdb(); /* could be moved earlier */
|
||||
|
||||
do_initcalls();
|
||||
|
||||
schedulers_start();
|
||||
|
||||
@@ -41,7 +41,6 @@ boolean_param("hpet_force", opt_hpet_force);
|
||||
unsigned long cpu_khz; /* CPU clock frequency in kHz. */
|
||||
unsigned long hpet_address;
|
||||
spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
|
||||
int timer_ack = 0;
|
||||
unsigned long volatile jiffies;
|
||||
static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */
|
||||
static spinlock_t wc_lock = SPIN_LOCK_UNLOCKED;
|
||||
@@ -148,16 +147,6 @@ void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
|
||||
{
|
||||
ASSERT(local_irq_is_enabled());
|
||||
|
||||
if ( timer_ack )
|
||||
{
|
||||
extern spinlock_t i8259A_lock;
|
||||
spin_lock_irq(&i8259A_lock);
|
||||
outb(0x0c, 0x20);
|
||||
/* Ack the IRQ; AEOI will end it automatically. */
|
||||
inb(0x20);
|
||||
spin_unlock_irq(&i8259A_lock);
|
||||
}
|
||||
|
||||
/* Update jiffies counter. */
|
||||
(*(unsigned long *)&jiffies)++;
|
||||
|
||||
|
||||
@@ -1410,7 +1410,13 @@ long do_set_trap_table(struct trap_info *traps)
|
||||
struct trap_info *dst = current->arch.guest_context.trap_ctxt;
|
||||
long rc = 0;
|
||||
|
||||
LOCK_BIGLOCK(current->domain);
|
||||
/* If no table is presented then clear the entire virtual IDT. */
|
||||
if ( traps == NULL )
|
||||
{
|
||||
memset(dst, 0, 256 * sizeof(*dst));
|
||||
init_int80_direct_trap(current);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
@@ -1440,8 +1446,6 @@ long do_set_trap_table(struct trap_info *traps)
|
||||
traps++;
|
||||
}
|
||||
|
||||
UNLOCK_BIGLOCK(current->domain);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
+7
-27
@@ -376,7 +376,6 @@ process_command(struct cpu_user_regs *regs, struct gdb_context *ctx)
|
||||
break;
|
||||
case 'g': /* Read registers */
|
||||
gdb_arch_read_reg_array(regs, ctx);
|
||||
ASSERT(!local_irq_is_enabled());
|
||||
break;
|
||||
case 'G': /* Write registers */
|
||||
gdb_arch_write_reg_array(regs, ctx->in_buf + 1, ctx);
|
||||
@@ -395,7 +394,6 @@ process_command(struct cpu_user_regs *regs, struct gdb_context *ctx)
|
||||
return 0;
|
||||
}
|
||||
gdb_cmd_read_mem(addr, length, ctx);
|
||||
ASSERT(!local_irq_is_enabled());
|
||||
break;
|
||||
case 'M': /* Write memory */
|
||||
addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
|
||||
@@ -477,7 +475,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
|
||||
{
|
||||
int resume = 0;
|
||||
int r;
|
||||
unsigned flags;
|
||||
unsigned long flags;
|
||||
|
||||
if ( gdb_ctx->serhnd < 0 )
|
||||
{
|
||||
@@ -506,7 +504,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
|
||||
|
||||
if ( !gdb_ctx->connected )
|
||||
{
|
||||
printk("GDB connection activated\n");
|
||||
printk("GDB connection activated.\n");
|
||||
gdb_arch_print_state(regs);
|
||||
gdb_ctx->connected = 1;
|
||||
}
|
||||
@@ -522,7 +520,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
|
||||
|
||||
/* Shouldn't really do this, but otherwise we stop for no
|
||||
obvious reason, which is Bad */
|
||||
printk("Waiting for GDB to attach to Gdb\n");
|
||||
printk("Waiting for GDB to attach...\n");
|
||||
|
||||
gdb_arch_enter(regs);
|
||||
gdb_ctx->signum = gdb_arch_signal_num(regs, cookie);
|
||||
@@ -535,9 +533,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
|
||||
|
||||
while ( resume == 0 )
|
||||
{
|
||||
ASSERT(!local_irq_is_enabled());
|
||||
r = receive_command(gdb_ctx);
|
||||
ASSERT(!local_irq_is_enabled());
|
||||
if ( r < 0 )
|
||||
{
|
||||
dbg_printk("GDB disappeared, trying to resume Xen...\n");
|
||||
@@ -545,9 +541,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(!local_irq_is_enabled());
|
||||
resume = process_command(regs, gdb_ctx);
|
||||
ASSERT(!local_irq_is_enabled());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,28 +555,14 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* initialization
|
||||
* XXX TODO
|
||||
* This should be an explicit call from architecture code.
|
||||
* initcall is far too late for some early debugging, and only the
|
||||
* architecture code knows when this call can be made.
|
||||
*/
|
||||
static int
|
||||
initialize_gdb(void)
|
||||
void
|
||||
initialise_gdb(void)
|
||||
{
|
||||
if ( !strcmp(opt_gdb, "none") )
|
||||
return 0;
|
||||
gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
|
||||
if ( gdb_ctx->serhnd == -1 )
|
||||
panic("Can't parse %s as GDB serial info.\n", opt_gdb);
|
||||
|
||||
printk("Gdb initialised.\n");
|
||||
return 0;
|
||||
if ( gdb_ctx->serhnd != -1 )
|
||||
printk("GDB stub initialised.\n");
|
||||
}
|
||||
|
||||
__initcall(initialize_gdb);
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#include <asm/msr.h>
|
||||
|
||||
extern int timer_ack;
|
||||
|
||||
extern void calibrate_tsc_bp(void);
|
||||
extern void calibrate_tsc_ap(void);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
typedef struct {
|
||||
unsigned long addr; /* Machine address of packet. */
|
||||
grant_ref_t ref; /* grant table access reference */
|
||||
uint16_t id; /* Echoed in response message. */
|
||||
uint16_t unused;
|
||||
uint16_t size; /* Packet size in bytes. */
|
||||
} tpmif_tx_request_t;
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ typedef struct physdevop_set_iobitmap {
|
||||
|
||||
typedef struct physdevop_apic {
|
||||
/* IN */
|
||||
uint32_t apic;
|
||||
uint32_t offset;
|
||||
unsigned long apic_physbase;
|
||||
uint32_t reg;
|
||||
/* IN or OUT */
|
||||
uint32_t value;
|
||||
} physdevop_apic_t;
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#ifndef __XEN_GDBSTUB_H__
|
||||
#define __XEN_GDBSTUB_H__
|
||||
|
||||
#ifdef CRASH_DEBUG
|
||||
|
||||
/* value <-> char (de)serialzers for arch specific gdb backends */
|
||||
char hex2char(unsigned long x);
|
||||
int char2hex(unsigned char c);
|
||||
@@ -84,6 +86,14 @@ void gdb_arch_exit(struct cpu_user_regs *regs);
|
||||
#define SIGALRM 14
|
||||
#define SIGTERM 15
|
||||
|
||||
void initialise_gdb(void);
|
||||
|
||||
#else
|
||||
|
||||
#define initialise_gdb() ((void)0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __XEN_GDBSTUB_H__ */
|
||||
|
||||
/*
|
||||
|
||||